From b6a376a4797e4988cdae48e0e5395a9b1f4e9f85 Mon Sep 17 00:00:00 2001 From: "Rafael H. Schloming" Date: Fri, 15 Aug 2008 03:40:49 +0000 Subject: updated qpid.0-10/java to match trunk/qpid/java@686097 git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/qpid.0-10@686136 13f79535-47bb-0310-9956-ffa450edef68 --- java/common/Composite.tpl | 73 ++- java/common/Constant.tpl | 2 +- java/common/Enum.tpl | 2 +- java/common/Invoker.tpl | 13 +- java/common/MethodDelegate.tpl | 2 +- java/common/Option.tpl | 5 +- java/common/StructFactory.tpl | 2 +- java/common/Type.tpl | 2 +- java/common/bin/qpid-run | 48 +- java/common/codegen | 2 +- java/common/genutil.py | 17 +- java/common/pom.xml | 2 +- java/common/src/main/java/log4j.properties | 3 + .../mina/common/FixedSizeByteBufferAllocator.java | 63 +-- .../mina/common/support/DefaultIoFuture.java | 1 - .../java/org/apache/qpid/AMQChannelException.java | 2 +- .../apache/qpid/AMQConnectionFailureException.java | 18 + .../main/java/org/apache/qpid/BrokerDetails.java | 138 +++++ .../java/org/apache/qpid/BrokerDetailsImpl.java | 264 +++++++++ .../main/java/org/apache/qpid/ConsoleOutput.java | 54 ++ .../src/main/java/org/apache/qpid/ErrorCode.java | 102 ++++ .../src/main/java/org/apache/qpid/QpidConfig.java | 90 +++ .../main/java/org/apache/qpid/QpidException.java | 58 ++ .../main/java/org/apache/qpid/SecurityHelper.java | 71 +++ .../src/main/java/org/apache/qpid/ToyBroker.java | 197 +++++++ .../src/main/java/org/apache/qpid/ToyClient.java | 126 +++++ .../src/main/java/org/apache/qpid/ToyExchange.java | 133 +++++ .../src/main/java/org/apache/qpid/api/Message.java | 126 +++++ .../org/apache/qpid/common/ClientProperties.java | 23 +- .../src/main/java/org/apache/qpid/dtx/XidImpl.java | 250 +++++++++ .../java/org/apache/qpid/framing/AMQDataBlock.java | 10 + .../org/apache/qpid/framing/AMQShortString.java | 67 ++- .../org/apache/qpid/framing/AMQTypedValue.java | 20 + .../java/org/apache/qpid/framing/FieldTable.java | 105 +++- .../src/main/java/org/apache/qpid/pool/Job.java | 24 +- .../java/org/apache/qpid/pool/PoolingFilter.java | 30 +- .../org/apache/qpid/pool/ReadWriteJobQueue.java | 432 ++++++++++++++ .../org/apache/qpid/pool/ReadWriteRunnable.java | 27 + .../pool/ReferenceCountingExecutorService.java | 24 +- .../protocol/AMQVersionAwareProtocolSession.java | 7 + .../apache/qpid/security/AMQPCallbackHandler.java | 28 + .../qpid/security/CallbackHandlerRegistry.java | 94 ++++ .../apache/qpid/security/DynamicSaslRegistrar.java | 74 +++ .../java/org/apache/qpid/security/JCAProvider.java | 44 ++ .../security/UsernamePasswordCallbackHandler.java | 60 ++ .../qpid/security/amqplain/AmqPlainSaslClient.java | 105 ++++ .../amqplain/AmqPlainSaslClientFactory.java | 62 +++ .../java/org/apache/qpid/transport/Binary.java | 129 +++++ .../java/org/apache/qpid/transport/Binding.java | 36 ++ .../java/org/apache/qpid/transport/Channel.java | 176 ++++++ .../org/apache/qpid/transport/ChannelDelegate.java | 54 ++ .../org/apache/qpid/transport/ClientDelegate.java | 40 ++ .../java/org/apache/qpid/transport/Connection.java | 186 +++++++ .../apache/qpid/transport/ConnectionDelegate.java | 287 ++++++++++ .../apache/qpid/transport/ConnectionException.java | 45 ++ .../main/java/org/apache/qpid/transport/Echo.java | 68 +++ .../main/java/org/apache/qpid/transport/Field.java | 83 +++ .../java/org/apache/qpid/transport/Future.java | 37 ++ .../java/org/apache/qpid/transport/Header.java | 92 +++ .../java/org/apache/qpid/transport/Method.java | 180 ++++++ .../apache/qpid/transport/ProtocolDelegate.java | 40 ++ .../org/apache/qpid/transport/ProtocolError.java | 83 +++ .../org/apache/qpid/transport/ProtocolEvent.java | 40 ++ .../org/apache/qpid/transport/ProtocolHeader.java | 116 ++++ .../qpid/transport/ProtocolVersionException.java | 52 ++ .../main/java/org/apache/qpid/transport/Range.java | 125 +++++ .../java/org/apache/qpid/transport/RangeSet.java | 147 +++++ .../java/org/apache/qpid/transport/Receiver.java | 38 ++ .../java/org/apache/qpid/transport/Result.java | 30 + .../java/org/apache/qpid/transport/Sender.java | 38 ++ .../java/org/apache/qpid/transport/Session.java | 575 +++++++++++++++++++ .../qpid/transport/SessionClosedException.java | 39 ++ .../org/apache/qpid/transport/SessionDelegate.java | 125 +++++ .../apache/qpid/transport/SessionException.java | 46 ++ .../main/java/org/apache/qpid/transport/Sink.java | 137 +++++ .../java/org/apache/qpid/transport/Struct.java | 142 +++++ .../apache/qpid/transport/TransportException.java | 46 ++ .../qpid/transport/codec/AbstractDecoder.java | 470 ++++++++++++++++ .../qpid/transport/codec/AbstractEncoder.java | 620 +++++++++++++++++++++ .../org/apache/qpid/transport/codec/BBDecoder.java | 96 ++++ .../org/apache/qpid/transport/codec/BBEncoder.java | 232 ++++++++ .../org/apache/qpid/transport/codec/Decoder.java | 68 +++ .../org/apache/qpid/transport/codec/Encodable.java | 37 ++ .../org/apache/qpid/transport/codec/Encoder.java | 66 +++ .../apache/qpid/transport/network/Assembler.java | 226 ++++++++ .../qpid/transport/network/ConnectionBinding.java | 60 ++ .../qpid/transport/network/Disassembler.java | 236 ++++++++ .../org/apache/qpid/transport/network/Frame.java | 151 +++++ .../qpid/transport/network/InputHandler.java | 204 +++++++ .../qpid/transport/network/NetworkDelegate.java | 42 ++ .../qpid/transport/network/NetworkEvent.java | 34 ++ .../transport/network/io/InputHandler_0_9.java | 109 ++++ .../qpid/transport/network/io/IoAcceptor.java | 81 +++ .../qpid/transport/network/io/IoReceiver.java | 129 +++++ .../apache/qpid/transport/network/io/IoSender.java | 291 ++++++++++ .../qpid/transport/network/io/IoTransport.java | 174 ++++++ .../qpid/transport/network/mina/MinaHandler.java | 274 +++++++++ .../qpid/transport/network/mina/MinaSender.java | 81 +++ .../qpid/transport/network/nio/NioHandler.java | 118 ++++ .../qpid/transport/network/nio/NioSender.java | 100 ++++ .../org/apache/qpid/transport/util/Functions.java | 91 +++ .../org/apache/qpid/transport/util/Logger.java | 130 +++++ .../apache/qpid/transport/util/SliceIterator.java | 59 ++ .../java/org/apache/qpid/url/BindingURLImpl.java | 2 +- .../src/main/java/org/apache/qpid/url/QpidURL.java | 2 +- .../main/java/org/apache/qpid/url/QpidURLImpl.java | 4 +- .../java/org/apache/qpid/util/NameUUIDGen.java | 59 ++ .../java/org/apache/qpid/util/RandomUUIDGen.java | 39 ++ .../java/org/apache/qpid/util/ReflectionUtils.java | 228 -------- .../apache/qpid/util/ReflectionUtilsException.java | 44 -- .../main/java/org/apache/qpid/util/Strings.java | 82 +++ .../main/java/org/apache/qpid/util/UUIDGen.java | 36 ++ .../src/main/java/org/apache/qpid/util/UUIDs.java | 59 ++ .../java/org/apache/qpidity/BrokerDetails.java | 138 ----- .../java/org/apache/qpidity/BrokerDetailsImpl.java | 264 --------- .../java/org/apache/qpidity/ConsoleOutput.java | 49 -- .../main/java/org/apache/qpidity/ErrorCode.java | 102 ---- .../java/org/apache/qpidity/ProtocolException.java | 36 -- .../main/java/org/apache/qpidity/QpidConfig.java | 90 --- .../java/org/apache/qpidity/QpidException.java | 58 -- .../java/org/apache/qpidity/SecurityHelper.java | 71 --- .../main/java/org/apache/qpidity/ToyBroker.java | 292 ---------- .../main/java/org/apache/qpidity/ToyClient.java | 134 ----- .../main/java/org/apache/qpidity/ToyExchange.java | 132 ----- .../main/java/org/apache/qpidity/api/Message.java | 126 ----- .../main/java/org/apache/qpidity/dtx/XidImpl.java | 250 --------- .../apache/qpidity/exchange/ExchangeDefaults.java | 51 -- .../qpidity/security/AMQPCallbackHandler.java | 28 - .../qpidity/security/CallbackHandlerRegistry.java | 94 ---- .../qpidity/security/DynamicSaslRegistrar.java | 74 --- .../org/apache/qpidity/security/JCAProvider.java | 44 -- .../security/UsernamePasswordCallbackHandler.java | 60 -- .../security/amqplain/AmqPlainSaslClient.java | 105 ---- .../amqplain/AmqPlainSaslClientFactory.java | 62 --- .../java/org/apache/qpidity/transport/Binding.java | 36 -- .../java/org/apache/qpidity/transport/Channel.java | 220 -------- .../apache/qpidity/transport/ChannelDelegate.java | 54 -- .../apache/qpidity/transport/ClientDelegate.java | 41 -- .../org/apache/qpidity/transport/Connection.java | 170 ------ .../qpidity/transport/ConnectionDelegate.java | 301 ---------- .../apache/qpidity/transport/ConnectionEvent.java | 56 -- .../java/org/apache/qpidity/transport/Data.java | 108 ---- .../java/org/apache/qpidity/transport/Echo.java | 87 --- .../java/org/apache/qpidity/transport/Field.java | 83 --- .../java/org/apache/qpidity/transport/Future.java | 37 -- .../java/org/apache/qpidity/transport/Header.java | 111 ---- .../java/org/apache/qpidity/transport/Method.java | 117 ---- .../apache/qpidity/transport/ProtocolDelegate.java | 44 -- .../apache/qpidity/transport/ProtocolError.java | 72 --- .../apache/qpidity/transport/ProtocolEvent.java | 36 -- .../apache/qpidity/transport/ProtocolHeader.java | 107 ---- .../java/org/apache/qpidity/transport/Range.java | 125 ----- .../org/apache/qpidity/transport/RangeSet.java | 142 ----- .../org/apache/qpidity/transport/Receiver.java | 38 -- .../java/org/apache/qpidity/transport/Result.java | 30 - .../java/org/apache/qpidity/transport/Sender.java | 36 -- .../java/org/apache/qpidity/transport/Session.java | 565 ------------------- .../apache/qpidity/transport/SessionDelegate.java | 129 ----- .../apache/qpidity/transport/SessionException.java | 46 -- .../java/org/apache/qpidity/transport/Struct.java | 142 ----- .../qpidity/transport/TransportConstants.java | 29 - .../qpidity/transport/TransportException.java | 46 -- .../qpidity/transport/codec/AbstractDecoder.java | 414 -------------- .../qpidity/transport/codec/AbstractEncoder.java | 589 -------------------- .../apache/qpidity/transport/codec/BBDecoder.java | 79 --- .../apache/qpidity/transport/codec/BBEncoder.java | 79 --- .../apache/qpidity/transport/codec/Decoder.java | 68 --- .../apache/qpidity/transport/codec/Encodable.java | 37 -- .../apache/qpidity/transport/codec/Encoder.java | 66 --- .../qpidity/transport/codec/FragmentDecoder.java | 112 ---- .../qpidity/transport/codec/SizeEncoder.java | 134 ----- .../org/apache/qpidity/transport/codec/Sizer.java | 76 --- .../apache/qpidity/transport/codec/Validator.java | 177 ------ .../qpidity/transport/network/Assembler.java | 202 ------- .../qpidity/transport/network/Disassembler.java | 222 -------- .../apache/qpidity/transport/network/Frame.java | 175 ------ .../qpidity/transport/network/InputHandler.java | 277 --------- .../qpidity/transport/network/NetworkDelegate.java | 42 -- .../qpidity/transport/network/NetworkEvent.java | 34 -- .../qpidity/transport/network/OutputHandler.java | 116 ---- .../qpidity/transport/network/io/IoHandler.java | 181 ------ .../qpidity/transport/network/io/IoSender.java | 111 ---- .../transport/network/mina/MinaHandler.java | 305 ---------- .../qpidity/transport/network/mina/MinaSender.java | 76 --- .../qpidity/transport/network/nio/NioHandler.java | 120 ---- .../qpidity/transport/network/nio/NioSender.java | 95 ---- .../apache/qpidity/transport/util/Functions.java | 91 --- .../org/apache/qpidity/transport/util/Logger.java | 125 ----- .../qpidity/transport/util/SliceIterator.java | 59 -- .../org/apache/qpid/transport/ConnectionTest.java | 121 ++++ .../org/apache/qpid/transport/RangeSetTest.java | 238 ++++++++ .../apache/qpidity/transport/ConnectionTest.java | 117 ---- .../org/apache/qpidity/transport/RangeSetTest.java | 238 -------- 193 files changed, 11001 insertions(+), 10111 deletions(-) create mode 100644 java/common/src/main/java/org/apache/qpid/BrokerDetails.java create mode 100644 java/common/src/main/java/org/apache/qpid/BrokerDetailsImpl.java create mode 100644 java/common/src/main/java/org/apache/qpid/ConsoleOutput.java create mode 100644 java/common/src/main/java/org/apache/qpid/ErrorCode.java create mode 100644 java/common/src/main/java/org/apache/qpid/QpidConfig.java create mode 100644 java/common/src/main/java/org/apache/qpid/QpidException.java create mode 100644 java/common/src/main/java/org/apache/qpid/SecurityHelper.java create mode 100644 java/common/src/main/java/org/apache/qpid/ToyBroker.java create mode 100644 java/common/src/main/java/org/apache/qpid/ToyClient.java create mode 100644 java/common/src/main/java/org/apache/qpid/ToyExchange.java create mode 100644 java/common/src/main/java/org/apache/qpid/api/Message.java create mode 100644 java/common/src/main/java/org/apache/qpid/dtx/XidImpl.java create mode 100644 java/common/src/main/java/org/apache/qpid/pool/ReadWriteJobQueue.java create mode 100644 java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java create mode 100644 java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java create mode 100644 java/common/src/main/java/org/apache/qpid/security/CallbackHandlerRegistry.java create mode 100644 java/common/src/main/java/org/apache/qpid/security/DynamicSaslRegistrar.java create mode 100644 java/common/src/main/java/org/apache/qpid/security/JCAProvider.java create mode 100644 java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java create mode 100644 java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClient.java create mode 100644 java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClientFactory.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Binary.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Binding.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Channel.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ChannelDelegate.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Connection.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ConnectionException.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Echo.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Field.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Future.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Header.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Method.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ProtocolDelegate.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ProtocolError.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ProtocolEvent.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ProtocolHeader.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/ProtocolVersionException.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Range.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/RangeSet.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Receiver.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Result.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Sender.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Session.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/SessionClosedException.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/SessionException.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Sink.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/Struct.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/TransportException.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/codec/BBDecoder.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/codec/Decoder.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/codec/Encodable.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/Frame.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/NetworkDelegate.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/NetworkEvent.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/util/Functions.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/util/Logger.java create mode 100644 java/common/src/main/java/org/apache/qpid/transport/util/SliceIterator.java create mode 100644 java/common/src/main/java/org/apache/qpid/util/NameUUIDGen.java create mode 100644 java/common/src/main/java/org/apache/qpid/util/RandomUUIDGen.java delete mode 100644 java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java delete mode 100644 java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java create mode 100644 java/common/src/main/java/org/apache/qpid/util/Strings.java create mode 100644 java/common/src/main/java/org/apache/qpid/util/UUIDGen.java create mode 100644 java/common/src/main/java/org/apache/qpid/util/UUIDs.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/BrokerDetails.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/BrokerDetailsImpl.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/ConsoleOutput.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/ErrorCode.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/ProtocolException.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/QpidConfig.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/QpidException.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/SecurityHelper.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/ToyBroker.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/ToyClient.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/ToyExchange.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/api/Message.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/exchange/ExchangeDefaults.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/security/AMQPCallbackHandler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/security/CallbackHandlerRegistry.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/security/DynamicSaslRegistrar.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/security/JCAProvider.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/security/UsernamePasswordCallbackHandler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClient.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClientFactory.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Binding.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Channel.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Connection.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/ConnectionEvent.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Data.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Echo.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Field.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Future.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Header.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Method.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/ProtocolError.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/ProtocolEvent.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/ProtocolHeader.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Range.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Receiver.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Result.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Sender.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Session.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/SessionException.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/Struct.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/TransportException.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractDecoder.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractEncoder.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/BBDecoder.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/BBEncoder.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/Decoder.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/Encodable.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/Encoder.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/FragmentDecoder.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/SizeEncoder.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/Sizer.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/codec/Validator.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/Assembler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/Disassembler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/Frame.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/InputHandler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/NetworkDelegate.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/NetworkEvent.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/OutputHandler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/io/IoHandler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/io/IoSender.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaHandler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaSender.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioHandler.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioSender.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/util/Functions.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/util/Logger.java delete mode 100644 java/common/src/main/java/org/apache/qpidity/transport/util/SliceIterator.java create mode 100644 java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java create mode 100644 java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java delete mode 100644 java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java delete mode 100644 java/common/src/test/java/org/apache/qpidity/transport/RangeSetTest.java (limited to 'java/common') diff --git a/java/common/Composite.tpl b/java/common/Composite.tpl index 46a45b0b91..283fa24641 100644 --- a/java/common/Composite.tpl +++ b/java/common/Composite.tpl @@ -1,28 +1,30 @@ -package org.apache.qpidity.transport; +package org.apache.qpid.transport; +import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.UUID; -import org.apache.qpidity.transport.codec.Decoder; -import org.apache.qpidity.transport.codec.Encodable; -import org.apache.qpidity.transport.codec.Encoder; -import org.apache.qpidity.transport.codec.Validator; +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encodable; +import org.apache.qpid.transport.codec.Encoder; -import org.apache.qpidity.transport.network.Frame; +import org.apache.qpid.transport.network.Frame; ${ from genutil import * cls = klass(type)["@name"] +segments = type["segments"] + if type.name in ("control", "command"): base = "Method" size = 0 pack = 2 - if type["segments"]: + if segments: payload = "true" else: payload = "false" @@ -80,12 +82,16 @@ if pack > 0: out(" private $(PACK_TYPES[pack]) packing_flags = 0;\n"); fields = get_fields(type) -params = get_parameters(fields) +params = get_parameters(type, fields) options = get_options(fields) for f in fields: if not f.empty: out(" private $(f.type) $(f.name);\n") + +if segments: + out(" private Header header;\n") + out(" private ByteBuffer body;\n") } ${ @@ -99,7 +105,11 @@ for f in fields: if f.option: continue out(" $(f.set)($(f.name));\n") -if options: +if segments: + out(" setHeader(header);\n") + out(" setBody(body);\n") + +if options or base == "Method": out(""" for (int i=0; i < _options.length; i++) { switch (_options[i]) { @@ -108,7 +118,11 @@ if options: for f in options: out(" case $(f.option): packing_flags |= $(f.flag_mask(pack)); break;\n") - out(""" case NO_OPTION: break; + if base == "Method": + out(""" case SYNC: this.setSync(true); break; + case BATCH: this.setBatch(true); break; +""") + out(""" case NONE: break; default: throw new IllegalArgumentException("invalid option: " + _options[i]); } } @@ -150,7 +164,6 @@ else: } public final $name $(f.set)($(f.type) value) { - $(f.check) ${ if not f.empty: out(" this.$(f.name) = value;") @@ -167,6 +180,44 @@ if pack > 0: return $(f.set)(value); } """) +} + +${ +if segments: + out(""" public final Header getHeader() { + return this.header; + } + + public final void setHeader(Header header) { + this.header = header; + } + + public final $name header(Header header) { + setHeader(header); + return this; + } + + public final ByteBuffer getBody() { + if (this.body == null) + { + return null; + } + else + { + return this.body.slice(); + } + } + + public final void setBody(ByteBuffer body) { + this.body = body; + } + + public final $name body(ByteBuffer body) + { + setBody(body); + return this; + } +""") } public void write(Encoder enc) diff --git a/java/common/Constant.tpl b/java/common/Constant.tpl index 695812ea75..7194a61dfc 100644 --- a/java/common/Constant.tpl +++ b/java/common/Constant.tpl @@ -1,4 +1,4 @@ -package org.apache.qpidity.transport; +package org.apache.qpid.transport; ${from genutil import *} diff --git a/java/common/Enum.tpl b/java/common/Enum.tpl index 337feb7065..2ec1d22522 100644 --- a/java/common/Enum.tpl +++ b/java/common/Enum.tpl @@ -1,4 +1,4 @@ -package org.apache.qpidity.transport; +package org.apache.qpid.transport; public enum $name { ${ diff --git a/java/common/Invoker.tpl b/java/common/Invoker.tpl index d9905c71a0..9158922df7 100644 --- a/java/common/Invoker.tpl +++ b/java/common/Invoker.tpl @@ -1,5 +1,6 @@ -package org.apache.qpidity.transport; +package org.apache.qpid.transport; +import java.nio.ByteBuffer; import java.util.List; import java.util.Map; import java.util.UUID; @@ -15,8 +16,8 @@ from genutil import * for c in composites: name = cname(c) fields = get_fields(c) - params = get_parameters(fields) - args = get_arguments(fields) + params = get_parameters(c, fields) + args = get_arguments(c, fields) result = c["result"] if result: if not result["@type"]: @@ -32,9 +33,9 @@ for c in composites: jclass = "" out(""" - public $jresult $(dromedary(name))($(", ".join(params))) { - $(jreturn)invoke(new $name($(", ".join(args)))$jclass); - } + public final $jresult $(dromedary(name))($(", ".join(params))) { + $(jreturn)invoke(new $name($(", ".join(args)))$jclass); + } """) } diff --git a/java/common/MethodDelegate.tpl b/java/common/MethodDelegate.tpl index e5ab1ae1e7..84fa0e43da 100644 --- a/java/common/MethodDelegate.tpl +++ b/java/common/MethodDelegate.tpl @@ -1,4 +1,4 @@ -package org.apache.qpidity.transport; +package org.apache.qpid.transport; public abstract class MethodDelegate { diff --git a/java/common/Option.tpl b/java/common/Option.tpl index 5fa2b95b9f..d45c004f6f 100644 --- a/java/common/Option.tpl +++ b/java/common/Option.tpl @@ -1,4 +1,4 @@ -package org.apache.qpidity.transport; +package org.apache.qpid.transport; public enum Option { @@ -15,5 +15,6 @@ for c in composites: if not options.has_key(option): options[option] = None out(" $option,\n")} - NO_OPTION + BATCH, + NONE } diff --git a/java/common/StructFactory.tpl b/java/common/StructFactory.tpl index b27621b1d2..f3dcbbd68a 100644 --- a/java/common/StructFactory.tpl +++ b/java/common/StructFactory.tpl @@ -1,4 +1,4 @@ -package org.apache.qpidity.transport; +package org.apache.qpid.transport; class StructFactory { diff --git a/java/common/Type.tpl b/java/common/Type.tpl index c869934538..c58e08a342 100644 --- a/java/common/Type.tpl +++ b/java/common/Type.tpl @@ -1,4 +1,4 @@ -package org.apache.qpidity.transport; +package org.apache.qpid.transport; ${from genutil import *} diff --git a/java/common/bin/qpid-run b/java/common/bin/qpid-run index c9e37b21a1..1de0048f48 100755 --- a/java/common/bin/qpid-run +++ b/java/common/bin/qpid-run @@ -37,19 +37,39 @@ die() { exit 1 } +OFF=0 +WARN=1 +INFO=2 + +if [ -z "$QPID_RUN_LOG" ]; then + QPID_RUN_LOG=$OFF +fi + +log() { + if [ "$1" -le "$QPID_RUN_LOG" ]; then + shift + echo "$@" + fi +} + if [ -z $AMQJ_LOGGING_LEVEL ]; then export AMQJ_LOGGING_LEVEL=info fi if [ -z "$QPID_HOME" ]; then - die "QPID_HOME must be set" + export QPID_HOME=$(dirname $(dirname $(readlink -f $0))) + export PATH=${PATH}:${QPID_HOME}/bin fi if [ -z "$QPID_WORK" ]; then - echo Setting QPID_WORK to $HOME as default + log $INFO Setting QPID_WORK to $HOME as default QPID_WORK=$HOME fi +if [ -z "$JAVA" ]; then + JAVA=java +fi + if $cygwin; then QPID_HOME=$(cygpath -w $QPID_HOME) QPID_WORK=$(cygpath -w $QPID_WORK) @@ -64,10 +84,10 @@ SYSTEM_PROPS="-Damqj.logging.level=$AMQJ_LOGGING_LEVEL -DQPID_HOME=$QPID_HOME -D #Using X character to avoid probs with empty strings if [ -n "$QPID_LOG_PREFIX" ]; then if [ "X$QPID_LOG_PREFIX" = "XPID" ]; then - echo Using pid in qpid log name prefix + log $INFO Using pid in qpid log name prefix LOG_PREFIX=" -Dlogprefix=$$" else - echo Using qpid logprefix property + log $INFO Using qpid logprefix property LOG_PREFIX=" -Dlogprefix=$QPID_LOG_PREFIX" fi SYSTEM_PROPS="${SYSTEM_PROPS} ${LOG_PREFIX}" @@ -75,16 +95,16 @@ fi if [ -n "$QPID_LOG_SUFFIX" ]; then if [ "X$QPID_LOG_SUFFIX" = "XPID" ]; then - echo Using pid in qpid log name suffix + log $INFO Using pid in qpid log name suffix LOG_SUFFIX=" -Dlogsuffix=$$" else - echo Using qpig logsuffix property + log $INFO Using qpig logsuffix property LOG_SUFFIX=" -Dlogsuffix=$QPID_LOG_SUFFIX" fi SYSTEM_PROPS="${SYSTEM_PROPS} ${LOG_SUFFIX}" fi -echo System Properties set to $SYSTEM_PROPS +log $INFO System Properties set to $SYSTEM_PROPS program=$(basename $0) sourced=${BASH_SOURCE[0]} @@ -109,26 +129,26 @@ unset CLASSPATH #Use QPID_CLASSPATH if set if [ -n "$QPID_CLASSPATH" ]; then export CLASSPATH=$QPID_CLASSPATH - echo "Using QPID_CLASSPATH" $QPID_CLASSPATH + log $INFO "Using QPID_CLASSPATH" $QPID_CLASSPATH else - echo "Warning: Qpid classpath not set. CLASSPATH must include qpid jars." + log $WARN "Warning: Qpid classpath not set. CLASSPATH must include qpid jars." fi #Use QPID_JAVA_GC if set if [ -n "$QPID_JAVA_GC" ]; then export JAVA_GC=$QPID_JAVA_GC - echo "Using QPID_JAVA_GC setting" $QPID_JAVA_GC + log $INFO "Using QPID_JAVA_GC setting" $QPID_JAVA_GC else - echo "Info: QPID_JAVA_GC not set. Defaulting to JAVA_GC" $JAVA_GC + log $INFO "Info: QPID_JAVA_GC not set. Defaulting to JAVA_GC" $JAVA_GC fi #Use QPID_JAVA_MEM if set if [ -n "$QPID_JAVA_MEM" ]; then export JAVA_MEM=$QPID_JAVA_MEM - echo "Using QPID_JAVA_MEM setting" $QPID_JAVA_MEM + log $INFO "Using QPID_JAVA_MEM setting" $QPID_JAVA_MEM else - echo "Info: QPID_JAVA_MEM not set. Defaulting to JAVA_MEM" $JAVA_MEM + log $INFO "Info: QPID_JAVA_MEM not set. Defaulting to JAVA_MEM" $JAVA_MEM fi declare -a RUN_ARGS JAVA_ARGS @@ -172,7 +192,7 @@ for arg in "${RUN_ARGS[@]}"; do ;; -run:jpda) #USAGE: adds debugging options to the java command, use -#USAGE: JDPA_TRANSPORT and JPDA_ADDRESS to customize the debugging +#USAGE: JPDA_TRANSPORT and JPDA_ADDRESS to customize the debugging #USAGE: behavior and use JPDA_OPTS to override it entirely if [ -z "$JPDA_OPTS" ]; then JPDA_OPTS="-Xdebug -Xrunjdwp:transport=${JPDA_TRANSPORT:-dt_socket},address=${JPDA_ADDRESS:-8000},server=y,suspend=n" diff --git a/java/common/codegen b/java/common/codegen index ab1ab1c542..6cd51565ea 100755 --- a/java/common/codegen +++ b/java/common/codegen @@ -7,7 +7,7 @@ from genutil import * out_dir = sys.argv[1] spec_file = sys.argv[2] tpl_dir = sys.argv[3] -pkg_dir = os.path.join(out_dir, "org/apache/qpidity/transport") +pkg_dir = os.path.join(out_dir, "org/apache/qpid/transport") if not os.path.exists(pkg_dir): os.makedirs(pkg_dir) diff --git a/java/common/genutil.py b/java/common/genutil.py index 9636a91cc3..f8f234548c 100644 --- a/java/common/genutil.py +++ b/java/common/genutil.py @@ -170,18 +170,15 @@ class Field: if self.type_node.name == "struct": self.read = "(%s) dec.readStruct(%s.TYPE)" % (tname, tname) self.write = "enc.writeStruct(%s.TYPE, check(struct).%s)" % (tname, self.name) - self.check = "" self.coder = "Struct" elif self.type_node.name == "domain": self.coder = camel(0, self.prim_type["@name"]) self.read = "%s.get(dec.read%s())" % (tname, self.coder) self.write = "enc.write%s(check(struct).%s.getValue())" % (self.coder, self.name) - self.check = "" else: self.coder = camel(0, self.type_node["@name"]) self.read = "dec.read%s()" % self.coder self.write = "enc.write%s(check(struct).%s)" % (self.coder, self.name) - self.check = "Validator.check%s(value);" % self.coder self.type = jtype(self.type_node) self.default = DEFAULTS.get(self.type, "null") self.has = camel(1, "has", self.name) @@ -206,7 +203,7 @@ def get_fields(nd): index += 1 return fields -def get_parameters(fields): +def get_parameters(type, fields): params = [] options = False for f in fields: @@ -214,11 +211,14 @@ def get_parameters(fields): options = True else: params.append("%s %s" % (f.type, f.name)) - if options: + if type["segments"]: + params.append("Header header") + params.append("ByteBuffer body") + if options or type.name in ("control", "command"): params.append("Option ... _options") return params -def get_arguments(fields): +def get_arguments(type, fields): args = [] options = False for f in fields: @@ -226,7 +226,10 @@ def get_arguments(fields): options = True else: args.append(f.name) - if options: + if type["segments"]: + args.append("header") + args.append("body") + if options or type.name in ("control", "command"): args.append("_options") return args diff --git a/java/common/pom.xml b/java/common/pom.xml index 714087d843..894ca26710 100644 --- a/java/common/pom.xml +++ b/java/common/pom.xml @@ -61,7 +61,7 @@ diff --git a/java/common/src/main/java/log4j.properties b/java/common/src/main/java/log4j.properties index 6d596d1d19..44f89dc805 100644 --- a/java/common/src/main/java/log4j.properties +++ b/java/common/src/main/java/log4j.properties @@ -19,9 +19,12 @@ log4j.rootLogger=${root.logging.level} +log4j.logger.qpid.protocol=${amqj.protocol.logging.level}, console +log4j.additivity.qpid.protocol=false log4j.logger.org.apache.qpid=${amqj.logging.level}, console log4j.additivity.org.apache.qpid=false + log4j.appender.console=org.apache.log4j.ConsoleAppender log4j.appender.console.Threshold=all log4j.appender.console.layout=org.apache.log4j.PatternLayout diff --git a/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java b/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java index bed80d5954..0c311b6645 100644 --- a/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java +++ b/java/common/src/main/java/org/apache/mina/common/FixedSizeByteBufferAllocator.java @@ -62,7 +62,6 @@ public class FixedSizeByteBufferAllocator implements ByteBufferAllocator private static final class FixedSizeByteBuffer extends ByteBuffer { private java.nio.ByteBuffer buf; - private int refCount = 1; private int mark = -1; @@ -70,36 +69,14 @@ public class FixedSizeByteBufferAllocator implements ByteBufferAllocator { this.buf = buf; buf.order( ByteOrder.BIG_ENDIAN ); - refCount = 1; } public synchronized void acquire() { - if( refCount <= 0 ) - { - throw new IllegalStateException( "Already released buffer." ); - } - - refCount ++; } public void release() { - synchronized( this ) - { - if( refCount <= 0 ) - { - refCount = 0; - throw new IllegalStateException( - "Already released buffer. You released the buffer too many times." ); - } - - refCount --; - if( refCount > 0) - { - return; - } - } } public java.nio.ByteBuffer buf() @@ -157,50 +134,12 @@ public class FixedSizeByteBufferAllocator implements ByteBufferAllocator { if( newCapacity > capacity() ) { - // Allocate a new buffer and transfer all settings to it. - int pos = position(); - int limit = limit(); - ByteOrder bo = order(); - - capacity0( newCapacity ); - buf.limit( limit ); - if( mark >= 0 ) - { - buf.position( mark ); - buf.mark(); - } - buf.position( pos ); - buf.order( bo ); + throw new IllegalArgumentException(); } return this; } - protected void capacity0( int requestedCapacity ) - { - int newCapacity = MINIMUM_CAPACITY; - while( newCapacity < requestedCapacity ) - { - newCapacity <<= 1; - } - - java.nio.ByteBuffer oldBuf = this.buf; - java.nio.ByteBuffer newBuf; - if( isDirect() ) - { - newBuf = java.nio.ByteBuffer.allocateDirect( newCapacity ); - } - else - { - newBuf = java.nio.ByteBuffer.allocate( newCapacity ); - } - - newBuf.clear(); - oldBuf.clear(); - newBuf.put( oldBuf ); - this.buf = newBuf; - } - public boolean isAutoExpand() diff --git a/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java b/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java index c515263317..4fd28c4eb5 100644 --- a/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java +++ b/java/common/src/main/java/org/apache/mina/common/support/DefaultIoFuture.java @@ -31,7 +31,6 @@ import java.util.Iterator; * A default implementation of {@link org.apache.mina.common.IoFuture}. * * @author The Apache Directory Project (mina-dev@directory.apache.org) - * @version $Rev: 440259 $, $Date: 2006-09-05 14:01:47 +0900 (화, 05 9월 2006) $ */ public class DefaultIoFuture implements IoFuture { diff --git a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java index f6f596da95..ef9420ba87 100644 --- a/java/common/src/main/java/org/apache/qpid/AMQChannelException.java +++ b/java/common/src/main/java/org/apache/qpid/AMQChannelException.java @@ -54,6 +54,6 @@ public class AMQChannelException extends AMQException public AMQFrame getCloseFrame(int channel) { MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor)); - return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode().getCode(), new AMQShortString(getMessage()),_classId,_methodId)); + return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), new AMQShortString(getMessage()),_classId,_methodId)); } } diff --git a/java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java b/java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java index 6cdd57d6f2..fa69f7f91b 100644 --- a/java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java +++ b/java/common/src/main/java/org/apache/qpid/AMQConnectionFailureException.java @@ -21,6 +21,10 @@ package org.apache.qpid; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; + import org.apache.qpid.protocol.AMQConstant; /** @@ -35,6 +39,8 @@ import org.apache.qpid.protocol.AMQConstant; */ public class AMQConnectionFailureException extends AMQException { + Collection _exceptions; + public AMQConnectionFailureException(String message, Throwable cause) { super(null, message, cause); @@ -44,4 +50,16 @@ public class AMQConnectionFailureException extends AMQException { super(errorCode, message, cause); } + + public AMQConnectionFailureException(String message, Collection exceptions) + { + // Blah, I hate ? but java won't let super() be anything other than the first thing, sorry... + super (null, message, exceptions.isEmpty() ? null : exceptions.iterator().next()); + this._exceptions = exceptions; + } + + public Collection getLinkedExceptions() + { + return _exceptions; + } } diff --git a/java/common/src/main/java/org/apache/qpid/BrokerDetails.java b/java/common/src/main/java/org/apache/qpid/BrokerDetails.java new file mode 100644 index 0000000000..63f67a7857 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/BrokerDetails.java @@ -0,0 +1,138 @@ +/* Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid; + +import java.util.Map; + +/** + * This interface represents a broker and provides the basic information + * required for opening a connection with a broker. + */ +public interface BrokerDetails +{ + /** + * Those are the supported protocols + */ + public static final String PROTOCOL_TCP = "tcp"; + public static final String PROTOCOL_TLS = "tls"; + + public static final String VIRTUAL_HOST = "virtualhost"; + public static final String CLIENT_ID = "client_id"; + public static final String USERNAME = "username"; + public static final String PASSWORD = "password"; + + /** + * Get the broker host name. + * + * @return The broker host name. + */ + public String getHost(); + + /** + * Get the broker port number. + * + * @return The broker port number. + */ + public int getPort(); + + /** + * Get the virtual host to connect to. + * + * @return The virtual host of this broker. + */ + public String getVirtualHost(); + + /** + * Get the user name. + * + * @return The user name + */ + public String getUserName(); + + /** + * Get the user password + * + * @return The user password + */ + public String getPassword(); + + /** + * Get the protocol used to connect to hise broker. + * + * @return the protocol used to connect to the broker. + */ + public String getProtocol(); + + /** + * Set the broker host name. + * + * @param host The broker host name. + */ + public void setHost(String host); + + /** + * Set the broker port number. + * + * @param port The broker port number. + */ + public void setPort(int port); + + /** + * Set the virtual host to connect to. + * + * @param virtualHost The virtual host of this broker. + */ + public void setVirtualHost(String virtualHost); + + /** + * Set the user name. + * + * @param userName The user name + */ + public void setUserName(String userName); + + /** + * Set the user password + * + * @param password The user password + */ + public void setPassword(String password); + + /** + * Set the protocol used to connect to hise broker. + * + * @param protocol the protocol used to connect to the broker. + */ + public void setProtocol(String protocol); + + /** + * Ex: keystore path + * + * @return the Properties associated with this connection. + */ + public Map getProperties(); + + /** + * Sets the properties associated with this connection + * + * @param props the new p[roperties. + */ + public void setProperties(Map props); + + public void setProperty(String key,String value); +} diff --git a/java/common/src/main/java/org/apache/qpid/BrokerDetailsImpl.java b/java/common/src/main/java/org/apache/qpid/BrokerDetailsImpl.java new file mode 100644 index 0000000000..201d43e21f --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/BrokerDetailsImpl.java @@ -0,0 +1,264 @@ +/* Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid; + +import java.util.HashMap; +import java.util.Map; + +/** + * Implements the interface BrokerDetails + */ +public class BrokerDetailsImpl implements BrokerDetails +{ + //--- Those are the default values + private final String DEFAULT_USERNAME = "guest"; + private final String DEFAULT_PASSWORD = "guest"; + private final String DEFAULT_VIRTUALHOST = ""; + + //---- The brker details + private String _host; + private int _port = 0; + private String _virtualHost; + private String _userName = DEFAULT_USERNAME; + private String _password = DEFAULT_PASSWORD; + private String _protocol; + private Map _props = new HashMap(); + ; + + //--- Constructors + + public BrokerDetailsImpl() + { + } + + /** + * Create a new broker details given all the reuqired information + * + * @param protocol The protocol used for this broker connection + * @param host The host name. + * @param port The port number. + * @param virtualHost The virtual host. + * @param userName The user name. + * @param password The user password. + */ + public BrokerDetailsImpl(String protocol, String host, int port, String virtualHost, String userName, + String password, Map props) + { + _protocol = protocol; + _host = host; + _port = port; + _virtualHost = virtualHost; + _userName = userName; + _password = password; + _props = props; + } + + /** + * Create a new broker details given the host name and the procol type, + * default values are used for the other details. + * + * @param protocol The protocol used for this broker connection + * @param host The host name. + */ + public BrokerDetailsImpl(String protocol, String host) + { + _protocol = protocol; + _host = host; + _virtualHost = DEFAULT_VIRTUALHOST; + _userName = DEFAULT_USERNAME; + _password = DEFAULT_PASSWORD; + } + + //--- API BrokerDetails + /** + * Get the user password + * + * @return The user password + */ + public String getPassword() + { + return _password; + } + + /** + * Get the broker host name. + * + * @return The broker host name. + */ + public String getHost() + { + return _host; + } + + /** + * Get the broker port number. + * + * @return The broker port number. + */ + public int getPort() + { + if (_port == 0) + { + if (getProtocol().equals(BrokerDetails.PROTOCOL_TCP)) + { + _port = 5672; + } + else if (getProtocol().equals(BrokerDetails.PROTOCOL_TLS)) + { + _port = 5555; + } + } + return _port; + } + + /** + * Get the virtual host to connect to. + * + * @return The virtual host of this broker. + */ + public String getVirtualHost() + { + return _virtualHost; + } + + /** + * Get the user name. + * + * @return The user name + */ + public String getUserName() + { + return _userName; + } + + /** + * Get the protocol used to connect to hise broker. + * + * @return the protocol used to connect to the broker. + */ + public String getProtocol() + { + return _protocol; + } + + /** + * Set the broker host name. + * + * @param host The broker host name. + */ + public void setHost(String host) + { + _host = host; + } + + /** + * Set the broker port number. + * + * @param port The broker port number. + */ + public void setPort(int port) + { + _port = port; + } + + /** + * Set the virtual host to connect to. + * + * @param virtualHost The virtual host of this broker. + */ + public void setVirtualHost(String virtualHost) + { + _virtualHost = virtualHost; + } + + /** + * Set the user name. + * + * @param userName The user name + */ + public void setUserName(String userName) + { + _userName = userName; + } + + /** + * Set the user password + * + * @param password The user password + */ + public void setPassword(String password) + { + _password = password; + } + + /** + * Set the protocol used to connect to hise broker. + * + * @param protocol the protocol used to connect to the broker. + */ + public void setProtocol(String protocol) + { + _protocol = protocol; + } + + /** + * Ex: keystore path + * + * @return the Properties associated with this connection. + */ + public Map getProperties() + { + return _props; + } + + /** + * Sets the properties associated with this connection + * + * @param props + */ + public void setProperties(Map props) + { + _props = props; + } + + public void setProperty(String key, String value) + { + _props.put(key, value); + } + + public String toString() + { + StringBuilder b = new StringBuilder(); + b.append("[username=" + _userName); + b.append(",password=" + _password); + b.append(",transport=" + _protocol); + b.append(",host=" + _host); + b.append(",port=" + getPort() + "]"); + b.append(" - Properties["); + if (_props != null) + { + for (String k : _props.keySet()) + { + b.append(k + "=" + _props.get(k) + ","); + } + } + b.append("]"); + + return b.toString(); + } +} diff --git a/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java b/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java new file mode 100644 index 0000000000..f17782ebf4 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/ConsoleOutput.java @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid; + +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.Sender; + +import static org.apache.qpid.transport.util.Functions.*; + + +/** + * ConsoleOutput + * + * @author Rafael H. Schloming + */ + +public class ConsoleOutput implements Sender +{ + + public void send(ByteBuffer buf) + { + System.out.println(str(buf)); + } + + public void flush() + { + // pass + } + + public void close() + { + System.out.println("CLOSED"); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/ErrorCode.java b/java/common/src/main/java/org/apache/qpid/ErrorCode.java new file mode 100644 index 0000000000..be1ad16dd5 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/ErrorCode.java @@ -0,0 +1,102 @@ +package org.apache.qpid; + +public enum ErrorCode +{ + //Qpid specific - for the time being + UNDEFINED(1,"undefined",true), + MESSAGE_REJECTED(2,"message_rejected",true), + CONNECTION_ERROR(3,"connection was closed",true), + UNSUPPORTED_PROTOCOL(4, "protocol version is unsupported", true), + + //This might change in the spec, the error class is not applicable + NO_ERROR(200,"reply-success",true), + + //From the spec + CONTENT_TOO_LARGE(311,"content-too-large",false), + NO_ROUTE(312,"no-route",false), + NO_CONSUMERS(313,"content-consumers",false), + CONNECTION_FORCED(320,"connection-forced",true), + INVALID_PATH(402,"invalid-path",true), + ACCESS_REFUSED(403,"access-refused",false), + NOT_FOUND(404,"not-found",false), + RESOURCE_LOCKED(405,"resource-locked",false), + PRE_CONDITION_FAILED(406,"precondition-failed",false), + + FRAME_ERROR(501,"frame_error",true), + SYNTAX_ERROR(502,"syntax_error",true), + COMMAND_INVALID(503,"command_invalid",true), + SESSION_ERROR(504,"sesion_error",true), + NOT_ALLOWED(530,"not_allowed",true), + NOT_IMPLEMENTED(540,"not_implemented",true), + INTERNAL_ERROR(541,"internal_error",true), + INVALID_ARGUMENT(542,"invalid_argument",true); + + private int _code; + private String _desc; + private boolean _hardError; + + private ErrorCode(int code,String desc,boolean hardError) + { + _code = code; + _desc= desc; + _hardError = hardError; + } + + public int getCode() + { + return _code; + } + + public String getDesc() + { + return _desc; + } + + private boolean isHardError() + { + return _hardError; + } + + public static ErrorCode get(int code) + { + switch(code) + { + case 200 : return NO_ERROR; + case 311 : return CONTENT_TOO_LARGE; + case 312 : return NO_ROUTE; + case 313 : return NO_CONSUMERS; + case 320 : return CONNECTION_FORCED; + case 402 : return INVALID_PATH; + case 403 : return ACCESS_REFUSED; + case 404 : return NOT_FOUND; + case 405 : return RESOURCE_LOCKED; + case 406 : return PRE_CONDITION_FAILED; + case 501 : return FRAME_ERROR; + case 502 : return SYNTAX_ERROR; + case 503 : return COMMAND_INVALID; + case 504 : return SESSION_ERROR; + case 530 : return NOT_ALLOWED; + case 540 : return NOT_IMPLEMENTED; + case 541 : return INTERNAL_ERROR; + case 542 : return INVALID_ARGUMENT; + + default : return UNDEFINED; + } + } + } + +/* + + + + The server could not complete the method because of an internal error. The server may require + intervention by an operator in order to resume normal operations. + + + + + + An invalid or illegal argument was passed to a method, and the operation could not proceed. + + +*/ \ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/QpidConfig.java b/java/common/src/main/java/org/apache/qpid/QpidConfig.java new file mode 100644 index 0000000000..e8d42fdf83 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/QpidConfig.java @@ -0,0 +1,90 @@ +package org.apache.qpid; + +/** + * API to configure the Security parameters of the client. + * The user can choose to pick the config from any source + * and set it using this class. + * + */ +public class QpidConfig +{ + private static QpidConfig _instance = new QpidConfig(); + + private SecurityMechanism[] securityMechanisms = + new SecurityMechanism[]{new SecurityMechanism("PLAIN","org.apache.qpid.security.UsernamePasswordCallbackHandler"), + new SecurityMechanism("CRAM_MD5","org.apache.qpid.security.UsernamePasswordCallbackHandler")}; + + private SaslClientFactory[] saslClientFactories = + new SaslClientFactory[]{new SaslClientFactory("AMQPLAIN","org.apache.qpid.security.amqplain.AmqPlainSaslClientFactory")}; + + private QpidConfig(){} + + public static QpidConfig get() + { + return _instance; + } + + public void setSecurityMechanisms(SecurityMechanism... securityMechanisms) + { + this.securityMechanisms = securityMechanisms; + } + + public SecurityMechanism[] getSecurityMechanisms() + { + return securityMechanisms; + } + + public void setSaslClientFactories(SaslClientFactory... saslClientFactories) + { + this.saslClientFactories = saslClientFactories; + } + + public SaslClientFactory[] getSaslClientFactories() + { + return saslClientFactories; + } + + public class SecurityMechanism + { + String type; + String handler; + + SecurityMechanism(String type,String handler) + { + this.type = type; + this.handler = handler; + } + + public String getHandler() + { + return handler; + } + + public String getType() + { + return type; + } + } + + public class SaslClientFactory + { + String type; + String factoryClass; + + SaslClientFactory(String type,String factoryClass) + { + this.type = type; + this.factoryClass = factoryClass; + } + + public String getFactoryClass() + { + return factoryClass; + } + + public String getType() + { + return type; + } + } +} diff --git a/java/common/src/main/java/org/apache/qpid/QpidException.java b/java/common/src/main/java/org/apache/qpid/QpidException.java new file mode 100644 index 0000000000..8503adaef8 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/QpidException.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; + +public class QpidException extends Exception +{ + /** + * AMQP error code + */ + private ErrorCode _errorCode; + + /** + * Constructor for a Qpid Exception. + *

This is the only provided constructor and the parameters have to be set to null when + * they are unknown. + * @param message A description of the reason of this exception . + * @param errorCode A string specifyin the error code of this exception. + * @param cause The linked Execption. * + * + */ + public QpidException(String message, ErrorCode errorCode, Throwable cause) + { + super(message, cause); + _errorCode = errorCode; + } + + /*hack to get rid of a compile error from a generated class + public QpidException(String message, String errorCode, Throwable cause) + { + + }*/ + + /** + * Get this execption error code. + * + * @return This exception error code. + */ + public ErrorCode getErrorCode() + { + return _errorCode; + } +} + diff --git a/java/common/src/main/java/org/apache/qpid/SecurityHelper.java b/java/common/src/main/java/org/apache/qpid/SecurityHelper.java new file mode 100644 index 0000000000..dda5a6506d --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/SecurityHelper.java @@ -0,0 +1,71 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid; + +import java.io.UnsupportedEncodingException; +import java.util.HashSet; +import java.util.List; +import java.util.StringTokenizer; + +import org.apache.qpid.security.AMQPCallbackHandler; +import org.apache.qpid.security.CallbackHandlerRegistry; + +public class SecurityHelper +{ + public static String chooseMechanism(List mechanisms) throws UnsupportedEncodingException + { + HashSet mechanismSet = new HashSet(); + for (Object m : mechanisms) + { + mechanismSet.add(m); + } + + String preferredMechanisms = CallbackHandlerRegistry.getInstance().getMechanisms(); + StringTokenizer prefTokenizer = new StringTokenizer(preferredMechanisms, " "); + while (prefTokenizer.hasMoreTokens()) + { + String mech = prefTokenizer.nextToken(); + if (mechanismSet.contains(mech)) + { + return mech; + } + } + return null; + } + + public static AMQPCallbackHandler createCallbackHandler(String mechanism, String username,String password) + throws QpidException + { + Class mechanismClass = CallbackHandlerRegistry.getInstance().getCallbackHandlerClass(mechanism); + try + { + Object instance = mechanismClass.newInstance(); + AMQPCallbackHandler cbh = (AMQPCallbackHandler) instance; + cbh.initialise(username,password); + return cbh; + } + catch (Exception e) + { + throw new QpidException("Unable to create callback handler: " + e,ErrorCode.UNDEFINED, e.getCause()); + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/ToyBroker.java b/java/common/src/main/java/org/apache/qpid/ToyBroker.java new file mode 100644 index 0000000000..83d434b20a --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/ToyBroker.java @@ -0,0 +1,197 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid; + +import org.apache.qpid.transport.*; +import org.apache.qpid.transport.network.mina.MinaHandler; + +import static org.apache.qpid.transport.util.Functions.str; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingQueue; + + +/** + * ToyBroker + * + * @author Rafael H. Schloming + */ + +class ToyBroker extends SessionDelegate +{ + + private ToyExchange exchange; + private Map consumers = new ConcurrentHashMap(); + + public ToyBroker(ToyExchange exchange) + { + this.exchange = exchange; + } + + public void messageAcquire(Session context, MessageAcquire struct) + { + System.out.println("\n==================> messageAcquire " ); + context.executionResult((int) struct.getId(), new Acquired(struct.getTransfers())); + } + + @Override public void queueDeclare(Session ssn, QueueDeclare qd) + { + exchange.createQueue(qd.getQueue()); + System.out.println("\n==================> declared queue: " + qd.getQueue() + "\n"); + } + + @Override public void exchangeBind(Session ssn, ExchangeBind qb) + { + exchange.bindQueue(qb.getExchange(), qb.getBindingKey(),qb.getQueue()); + System.out.println("\n==================> bound queue: " + qb.getQueue() + " with binding key " + qb.getBindingKey() + "\n"); + } + + @Override public void queueQuery(Session ssn, QueueQuery qq) + { + QueueQueryResult result = new QueueQueryResult().queue(qq.getQueue()); + ssn.executionResult((int) qq.getId(), result); + } + + @Override public void messageSubscribe(Session ssn, MessageSubscribe ms) + { + Consumer c = new Consumer(); + c._queueName = ms.getQueue(); + consumers.put(ms.getDestination(),c); + System.out.println("\n==================> message subscribe : " + ms.getDestination() + " queue: " + ms.getQueue() + "\n"); + } + + @Override public void messageFlow(Session ssn,MessageFlow struct) + { + Consumer c = consumers.get(struct.getDestination()); + c._credit = struct.getValue(); + System.out.println("\n==================> message flow : " + struct.getDestination() + " credit: " + struct.getValue() + "\n"); + } + + @Override public void messageFlush(Session ssn,MessageFlush struct) + { + System.out.println("\n==================> message flush for consumer : " + struct.getDestination() + "\n"); + checkAndSendMessagesToConsumer(ssn,struct.getDestination()); + } + + @Override public void messageTransfer(Session ssn, MessageTransfer xfr) + { + String dest = xfr.getDestination(); + System.out.println("received transfer " + dest); + Header header = xfr.getHeader(); + DeliveryProperties props = header.get(DeliveryProperties.class); + if (props != null) + { + System.out.println("received headers routing_key " + props.getRoutingKey()); + } + MessageProperties mp = header.get(MessageProperties.class); + System.out.println("MP: " + mp); + if (mp != null) + { + System.out.println(mp.getApplicationHeaders()); + } + + if (exchange.route(dest,props.getRoutingKey(),xfr)) + { + System.out.println("queued " + xfr); + dispatchMessages(ssn); + } + else + { + + if (props == null || !props.getDiscardUnroutable()) + { + RangeSet ranges = new RangeSet(); + ranges.add(xfr.getId()); + ssn.messageReject(ranges, MessageRejectCode.UNROUTABLE, + "no such destination"); + } + } + ssn.processed(xfr); + } + + private void transferMessageToPeer(Session ssn,String dest, MessageTransfer m) + { + System.out.println("\n==================> Transfering message to: " +dest + "\n"); + ssn.messageTransfer(m.getDestination(), MessageAcceptMode.EXPLICIT, + MessageAcquireMode.PRE_ACQUIRED, + m.getHeader(), m.getBody()); + } + + private void dispatchMessages(Session ssn) + { + for (String dest: consumers.keySet()) + { + checkAndSendMessagesToConsumer(ssn,dest); + } + } + + private void checkAndSendMessagesToConsumer(Session ssn,String dest) + { + Consumer c = consumers.get(dest); + LinkedBlockingQueue queue = exchange.getQueue(c._queueName); + MessageTransfer m = queue.poll(); + while (m != null && c._credit>0) + { + transferMessageToPeer(ssn,dest,m); + c._credit--; + m = queue.poll(); + } + } + + // ugly, but who cares :) + // assumes unit is always no of messages, not bytes + // assumes it's credit mode and not window + private class Consumer + { + long _credit; + String _queueName; + } + + public static final void main(String[] args) throws IOException + { + final ToyExchange exchange = new ToyExchange(); + ConnectionDelegate delegate = new ConnectionDelegate() + { + public SessionDelegate getSessionDelegate() + { + return new ToyBroker(exchange); + } + public void exception(Throwable t) + { + t.printStackTrace(); + } + public void closed() {} + }; + + //hack + delegate.setUsername("guest"); + delegate.setPassword("guest"); + + MinaHandler.accept("0.0.0.0", 5672, delegate); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/ToyClient.java b/java/common/src/main/java/org/apache/qpid/ToyClient.java new file mode 100644 index 0000000000..cb10859c9f --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/ToyClient.java @@ -0,0 +1,126 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid; + +import java.nio.*; +import java.util.*; + +import org.apache.qpid.transport.*; +import org.apache.qpid.transport.network.mina.MinaHandler; + + +/** + * ToyClient + * + * @author Rafael H. Schloming + */ + +class ToyClient extends SessionDelegate +{ + + @Override public void messageReject(Session ssn, MessageReject reject) + { + for (Range range : reject.getTransfers()) + { + for (long l = range.getLower(); l <= range.getUpper(); l++) + { + System.out.println("message rejected: " + + ssn.getCommand((int) l)); + } + } + } + + @Override public void messageTransfer(Session ssn, MessageTransfer xfr) + { + System.out.println("msg: " + xfr); + } + + public static final void main(String[] args) + { + Connection conn = MinaHandler.connect("0.0.0.0", 5672, + new ClientDelegate() + { + public SessionDelegate getSessionDelegate() + { + return new ToyClient(); + } + public void exception(Throwable t) + { + t.printStackTrace(); + } + public void closed() {} + }); + conn.send(new ProtocolHeader + (1, 0, 10)); + + Channel ch = conn.getChannel(0); + Session ssn = new Session("my-session".getBytes()); + ssn.attach(ch); + ssn.sessionAttach(ssn.getName()); + + ssn.queueDeclare("asdf", null, null); + ssn.sync(); + + Map nested = new LinkedHashMap(); + nested.put("list", Arrays.asList("one", "two", "three")); + Map map = new LinkedHashMap(); + + map.put("str", "this is a string"); + + map.put("+int", 3); + map.put("-int", -3); + map.put("maxint", Integer.MAX_VALUE); + map.put("minint", Integer.MIN_VALUE); + + map.put("+short", (short) 1); + map.put("-short", (short) -1); + map.put("maxshort", (short) Short.MAX_VALUE); + map.put("minshort", (short) Short.MIN_VALUE); + + map.put("float", (float) 3.3); + map.put("double", 4.9); + map.put("char", 'c'); + + map.put("table", nested); + map.put("list", Arrays.asList(1, 2, 3)); + map.put("binary", new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + + ssn.messageTransfer("asdf", MessageAcceptMode.EXPLICIT, + MessageAcquireMode.PRE_ACQUIRED, + new Header(new DeliveryProperties(), + new MessageProperties() + .setApplicationHeaders(map)), + "this is the data"); + + ssn.messageTransfer("fdsa", MessageAcceptMode.EXPLICIT, + MessageAcquireMode.PRE_ACQUIRED, + null, + "this should be rejected"); + ssn.sync(); + + Future future = ssn.queueQuery("asdf"); + System.out.println(future.get().getQueue()); + ssn.sync(); + ssn.close(); + conn.close(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/ToyExchange.java b/java/common/src/main/java/org/apache/qpid/ToyExchange.java new file mode 100644 index 0000000000..c638679596 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/ToyExchange.java @@ -0,0 +1,133 @@ +package org.apache.qpid; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.qpid.transport.MessageTransfer; + + +public class ToyExchange +{ + final static String DIRECT = "amq.direct"; + final static String TOPIC = "amq.topic"; + + private Map>> directEx = new HashMap>>(); + private Map>> topicEx = new HashMap>>(); + private Map> queues = new HashMap>(); + + public void createQueue(String name) + { + queues.put(name, new LinkedBlockingQueue()); + } + + public LinkedBlockingQueue getQueue(String name) + { + return queues.get(name); + } + + public void bindQueue(String type,String binding,String queueName) + { + LinkedBlockingQueue queue = queues.get(queueName); + binding = normalizeKey(binding); + if(DIRECT.equals(type)) + { + + if (directEx.containsKey(binding)) + { + List> list = directEx.get(binding); + list.add(queue); + } + else + { + List> list = new LinkedList>(); + list.add(queue); + directEx.put(binding,list); + } + } + else + { + if (topicEx.containsKey(binding)) + { + List> list = topicEx.get(binding); + list.add(queue); + } + else + { + List> list = new LinkedList>(); + list.add(queue); + topicEx.put(binding,list); + } + } + } + + public boolean route(String dest, String routingKey, MessageTransfer msg) + { + List> queues; + if(DIRECT.equals(dest)) + { + queues = directEx.get(routingKey); + } + else + { + queues = matchWildCard(routingKey); + } + if(queues != null && queues.size()>0) + { + System.out.println("Message stored in " + queues.size() + " queues"); + storeMessage(msg,queues); + return true; + } + else + { + System.out.println("Message unroutable " + msg); + return false; + } + } + + private String normalizeKey(String routingKey) + { + if(routingKey.indexOf(".*")>1) + { + return routingKey.substring(0,routingKey.indexOf(".*")); + } + else + { + return routingKey; + } + } + + private List> matchWildCard(String routingKey) + { + List> selected = new ArrayList>(); + + for(String key: topicEx.keySet()) + { + Pattern p = Pattern.compile(key); + Matcher m = p.matcher(routingKey); + if (m.find()) + { + for(LinkedBlockingQueue queue : topicEx.get(key)) + { + selected.add(queue); + } + } + } + + return selected; + } + + private void storeMessage(MessageTransfer msg,List> selected) + { + for(LinkedBlockingQueue queue : selected) + { + queue.offer(msg); + } + } + +} 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 new file mode 100644 index 0000000000..df6f279026 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/api/Message.java @@ -0,0 +1,126 @@ +package org.apache.qpid.api; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT 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 interface Message +{ + public Header getHeader(); + + public void setHeader(Header header); + + public MessageProperties getMessageProperties(); + + public DeliveryProperties getDeliveryProperties(); + + /** + * This will abstract the underlying message data. + * The Message implementation may not hold all message + * data in memory (especially in the case of large messages) + * + * The appendData function might write data to + *
    + *
  • Memory (Ex: ByteBuffer) + *
  • To Disk + *
  • To Socket (Stream) + *
+ * @param src - the data to append + */ + public void appendData(byte[] src) throws IOException; + + + /** + * This will abstract the underlying message data. + * The Message implementation may not hold all message + * data in memory (especially in the case of large messages) + * + * The appendData function might write data to + *
    + *
  • Memory (Ex: ByteBuffer) + *
  • To Disk + *
  • To Socket (Stream) + *
+ * @param src - the data to append + */ + public void appendData(ByteBuffer src) throws IOException; + + /** + * This will abstract the underlying message data. + * The Message implementation may not hold all message + * data in memory (especially in the case of large messages) + * + * The read function might copy data from + *
    + *
  • From memory (Ex: ByteBuffer) + *
  • From Disk + *
  • From Socket as and when it gets streamed + *
+ * @param target The target byte[] which the data gets copied to + */ + public void readData(byte[] target) throws IOException; + + /** + * * This will abstract the underlying message data. + * The Message implementation may not hold all message + * data in memory (especially in the case of large messages) + * + * The read function might copy data from + *
    + *
  • From memory (Ex: ByteBuffer) + *
  • From Disk + *
  • From Socket as and when it gets streamed + *
+ * + * @return A ByteBuffer containing data + * @throws IOException + */ + public ByteBuffer readData() throws IOException; + + /** + * This should clear the body of the message. + */ + public void clearData(); + + /** + * The provides access to the command Id assigned to the + * message transfer. + * This id is useful when you do + *
    + *
  • For message acquiring - If the transfer happend in no-acquire mode + * you could use this id to accquire it. + *
  • For releasing a message. You can use this id to release an acquired + * message + *
  • For Acknowledging a message - You need to pass this ID, in order to + * acknowledge the message + *
  • For Rejecting a message - You need to pass this ID, in order to reject + * the message. + *
+ * + * @return the message transfer id. + */ + public int getMessageTransferId(); + +} diff --git a/java/common/src/main/java/org/apache/qpid/common/ClientProperties.java b/java/common/src/main/java/org/apache/qpid/common/ClientProperties.java index 67f16e6a87..7371c12519 100644 --- a/java/common/src/main/java/org/apache/qpid/common/ClientProperties.java +++ b/java/common/src/main/java/org/apache/qpid/common/ClientProperties.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.common; +import org.apache.qpid.framing.AMQShortString; + /** * Specifies the available client property types that different clients can use to identify themselves with. * @@ -30,8 +32,21 @@ package org.apache.qpid.common; */ public enum ClientProperties { - instance, - product, - version, - platform + instance("instance"), + product("product"), + version("version"), + platform("platform"); + + private final AMQShortString _amqShortString; + + private ClientProperties(String name) + { + _amqShortString = new AMQShortString(name); + } + + + public AMQShortString toAMQShortString() + { + return _amqShortString; + } } diff --git a/java/common/src/main/java/org/apache/qpid/dtx/XidImpl.java b/java/common/src/main/java/org/apache/qpid/dtx/XidImpl.java new file mode 100644 index 0000000000..49effc2dae --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/dtx/XidImpl.java @@ -0,0 +1,250 @@ +/* Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.qpid.dtx; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.apache.qpid.QpidException; + +import javax.transaction.xa.Xid; + +import java.io.*; + +/** + * Implements javax.transaction.dtx.Xid + */ +public class XidImpl implements Xid +{ + /** + * this session's logger + */ + private static final Logger _logger = LoggerFactory.getLogger(XidImpl.class); + + /** + * the transaction branch identifier part of XID as an array of bytes + */ + private byte[] _branchQualifier; + + /** + * the format identifier part of the XID. + */ + private int _formatID; + + /** + * the global transaction identifier part of XID as an array of bytes. + */ + private byte[] _globalTransactionID; + + //--- Constructors + + /** + * Create new Xid. + * this is an empty constructor. + */ + public XidImpl() + { + + } + + /** + * Create a new XidImpl from an existing Xid. + *

Usefull for casting external Xids + * + * @param xid Foreign Xid. + */ + public XidImpl(Xid xid) + { + _branchQualifier = xid.getBranchQualifier(); + _formatID = xid.getFormatId(); + _globalTransactionID = xid.getGlobalTransactionId(); + } + + /** + * Create a new Xid. + * + * @param branchQualifier The transaction branch identifier part of XID as an array of bytes. + * @param format The format identifier part of the XID. + * @param globalTransactionID The global transaction identifier part of XID as an array of bytes. + */ + public XidImpl(byte[] branchQualifier, int format, byte[] globalTransactionID) + { + _branchQualifier = branchQualifier; + _formatID = format; + _globalTransactionID = globalTransactionID; + } + + /** + * Create a new Xid form its String form + * 4 1 1 g b + * +---+---+---+---+---+---+---+- -+---+---+- -+---+ + * | format_id | g | b | txn-id | br-id | + * +---+---+---+---+---+---+---+- -+---+---+- -+---+ + * 0 4 5 6 6+g 6+g+b + * format_id: an implementation specific format identifier + *

+ * gtrid_length: how many bytes of this form the transaction id + *

+ * bqual_length: how many bytes of this form the branch id + *

+ * data: a sequence of octets of at most 128 bytes containing the txn id and the + * branch id + *

+ * Note - The sum of the two lengths must equal the length of the data field. + * + * @param xid an XID STring Form + * @throws QpidException If the string does not represent a valid Xid + */ + public XidImpl(String xid) throws QpidException + { + if (_logger.isDebugEnabled()) + { + _logger.debug("converting string " + xid + " into XidImpl"); + } + try + { + DataInputStream input = new DataInputStream(new ByteArrayInputStream(xid.getBytes())); + _formatID = (int) input.readLong(); + int g = input.readByte(); + int b = input.readByte(); + _globalTransactionID = new byte[g]; + _branchQualifier = new byte[b]; + if (input.read(_globalTransactionID, 0, g) != g) + { + throw new QpidException("Cannot convert the string " + xid + " into an Xid", null, null); + } + if (input.read(_branchQualifier, 0, b) != b) + { + throw new QpidException("Cannot convert the string " + xid + " into an Xid", null, null); + } + } + catch (IOException e) + { + throw new QpidException("cannot convert the string " + xid + " into an Xid", null, e); + } + } + + //--- Xid interface implementation + + /** + * Format identifier. O means the OSI CCR format. + * + * @return Global transaction identifier. + */ + public byte[] getGlobalTransactionId() + { + return _globalTransactionID; + } + + /** + * Obtain the transaction branch identifier part of XID as an array of bytes. + * + * @return Branch identifier part of XID. + */ + public byte[] getBranchQualifier() + { + return _branchQualifier; + } + + /** + * Obtain the format identifier part of the XID. + * + * @return Format identifier. O means the OSI CCR format. + */ + public int getFormatId() + { + return _formatID; + } + + //--- Object operations + + /** + * Indicates whether some other Xid is "equal to" this one. + *

Two Xids are equal if and only if their three elementary parts are equal + * + * @param o the object to compare this XidImpl against. + * @return true if the XidImpl are equal, false otherwise. + */ + public boolean equals(Object o) + { + if (this == o) + { + return true; + } + if (o instanceof XidImpl) + { + XidImpl other = (XidImpl) o; + if (_formatID == other.getFormatId()) + { + if (_branchQualifier.length == other.getBranchQualifier().length) + { + for (int i = 0; i < _branchQualifier.length; i++) + { + if (_branchQualifier[i] != other.getBranchQualifier()[i]) + { + return false; + } + } + if (_globalTransactionID.length == other.getGlobalTransactionId().length) + { + for (int i = 0; i < _globalTransactionID.length; i++) + { + if (_globalTransactionID[i] != other.getGlobalTransactionId()[i]) + { + return false; + } + } + // everithing is equal + return true; + } + } + } + } + return false; + } + + //-- Static helper method + /** + * Convert an Xid into the AMQP String format. + * + * 4 1 1 g b + * +---+---+---+---+---+---+---+- -+---+---+- -+---+ + * | format_id | g | b | txn-id | br-id | + * +---+---+---+---+---+---+---+- -+---+---+- -+---+ + * 0 4 5 6 6+g 6+g+b + * format_id: an implementation specific format identifier + *

+ * gtrid_length: how many bytes of this form the transaction id + *

+ * bqual_length: how many bytes of this form the branch id + *

+ * data: a sequence of octets of at most 128 bytes containing the txn id and the + * branch id + *

+ * Note - The sum of the two lengths must equal the length of the data field. + * + * @param xid an Xid to convert. + * @return The String representation of this Xid + * @throws QpidException In case of problem when converting this Xid into a string. + */ + public static org.apache.qpid.transport.Xid convert(Xid xid) throws QpidException + { + return new org.apache.qpid.transport.Xid(xid.getFormatId(), + xid.getGlobalTransactionId(), + xid.getBranchQualifier()); + } +} diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java index 903b5bfa7a..a2fc3a03ef 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQDataBlock.java @@ -50,4 +50,14 @@ public abstract class AMQDataBlock implements EncodableAMQDataBlock return buffer; } + public java.nio.ByteBuffer toNioByteBuffer() + { + final java.nio.ByteBuffer buffer = java.nio.ByteBuffer.allocate((int) getSize()); + + ByteBuffer buf = ByteBuffer.wrap(buffer); + writePayload(buf); + buffer.flip(); + return buffer; + } + } diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java index a747aaeda7..a8e7f47db0 100644 --- a/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java +++ b/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java @@ -111,6 +111,8 @@ public final class AMQShortString implements CharSequence, Comparable> iterator() + { + if(_encodedForm != null) + { + return new FieldTableIterator(_encodedForm.duplicate().rewind(),(int)_encodedSize); + } + else + { + initMapIfNecessary(); + return _properties.entrySet().iterator(); + } + } + + public Object get(AMQShortString key) { @@ -1050,6 +1064,95 @@ public class FieldTable } } + private static final class FieldTableEntry implements Map.Entry + { + private final AMQTypedValue _value; + private final AMQShortString _key; + + public FieldTableEntry(final AMQShortString key, final AMQTypedValue value) + { + _key = key; + _value = value; + } + + public AMQShortString getKey() + { + return _key; + } + + public AMQTypedValue getValue() + { + return _value; + } + + public AMQTypedValue setValue(final AMQTypedValue value) + { + throw new UnsupportedOperationException(); + } + + public boolean equals(Object o) + { + if(o instanceof FieldTableEntry) + { + FieldTableEntry other = (FieldTableEntry) o; + return (_key == null ? other._key == null : _key.equals(other._key)) + && (_value == null ? other._value == null : _value.equals(other._value)); + } + else + { + return false; + } + } + + public int hashCode() + { + return (getKey()==null ? 0 : getKey().hashCode()) + ^ (getValue()==null ? 0 : getValue().hashCode()); + } + + } + + + private static final class FieldTableIterator implements Iterator> + { + + private final ByteBuffer _buffer; + private int _expectedRemaining; + + public FieldTableIterator(ByteBuffer buffer, int length) + { + _buffer = buffer; + _expectedRemaining = buffer.remaining() - length; + } + + public boolean hasNext() + { + return (_buffer.remaining() > _expectedRemaining); + } + + public Map.Entry next() + { + if(hasNext()) + { + final AMQShortString key = EncodingUtils.readAMQShortString(_buffer); + AMQTypedValue value = AMQTypedValue.readFromBuffer(_buffer); + return new FieldTableEntry(key, value); + } + else + { + return null; + } + } + + public void remove() + { + throw new UnsupportedOperationException(); + } + } + + + + public int hashCode() { initMapIfNecessary(); diff --git a/java/common/src/main/java/org/apache/qpid/pool/Job.java b/java/common/src/main/java/org/apache/qpid/pool/Job.java index b2a09ac592..00da005515 100644 --- a/java/common/src/main/java/org/apache/qpid/pool/Job.java +++ b/java/common/src/main/java/org/apache/qpid/pool/Job.java @@ -50,7 +50,7 @@ import org.apache.mina.common.IoSession; * * @todo For better re-usability could make the completion handler optional. Only run it when one is set. */ -public class Job implements Runnable +public class Job implements ReadWriteRunnable { /** The maximum number of events to process per run of the job. More events than this may be queued in the job. */ private final int _maxEvents; @@ -67,18 +67,22 @@ public class Job implements Runnable /** Holds the completion continuation, called upon completion of a run of the job. */ private final JobCompletionHandler _completionHandler; + private final boolean _readJob; + /** * Creates a new job that aggregates many continuations together. * * @param session The Mina session. * @param completionHandler The per job run, terminal continuation. * @param maxEvents The maximum number of aggregated continuations to process per run of the job. + * @param readJob */ - Job(IoSession session, JobCompletionHandler completionHandler, int maxEvents) + Job(IoSession session, JobCompletionHandler completionHandler, int maxEvents, final boolean readJob) { _session = session; _completionHandler = completionHandler; _maxEvents = maxEvents; + _readJob = readJob; } /** @@ -157,6 +161,22 @@ public class Job implements Runnable } } + public boolean isReadJob() + { + return _readJob; + } + + public boolean isRead() + { + return _readJob; + } + + public boolean isWrite() + { + return !_readJob; + } + + /** * Another interface for a continuation. * diff --git a/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java b/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java index 2912e54662..a080cc7e04 100644 --- a/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java +++ b/java/common/src/main/java/org/apache/qpid/pool/PoolingFilter.java @@ -60,24 +60,6 @@ import java.util.concurrent.ExecutorService; * {@link Job}, {@link Job.JobCompletionHandler} * * - * @todo This seems a bit bizarre. ReadWriteThreadModel creates seperate pooling filters for read and write events. - * The pooling filters themselves batch read and write events into jobs, but hand these jobs to a common thread - * pool for execution. So the same thread pool ends up handling read and write events, albeit with many threads - * so there is concurrency. But why go to the trouble of seperating out the read and write events in that case? - * Why not just batch them into jobs together? Perhaps its so that seperate thread pools could be used for these - * stages. - * - * @todo Why set an event limit of 10 on the Job? This also seems bizarre, as the job can have more than 10 events in - * it. Its just that it runs them 10 at a time, but the completion hander here checks if there are more to run - * and trips off another batch of 10 until they are all done. Why not just have a straight forward - * consumer/producer queue scenario without the batches of 10? So instead of having many jobs with batches of 10 - * in them, just have one queue of events and worker threads taking the next event. There will be coordination - * between worker threads and new events arriving on the job anyway, so the simpler scenario may have the same - * amount of contention. I can see that the batches of 10 is done, so that no job is allowed to hog the worker - * pool for too long. I'm not convinced this fairly complex scheme will actually add anything, and it might be - * better to encapsulate it under a Queue interface anyway, so that different queue implementations can easily - * be substituted in. - * * @todo The static helper methods are pointless. Could just call new. */ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCompletionHandler @@ -96,17 +78,20 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo private final int _maxEvents; + private final boolean _readFilter; + /** * Creates a named pooling filter, on the specified shared thread pool. * * @param refCountingPool The thread pool reference. * @param name The identifying name of the filter type. */ - public PoolingFilter(ReferenceCountingExecutorService refCountingPool, String name, int maxEvents) + public PoolingFilter(ReferenceCountingExecutorService refCountingPool, String name, int maxEvents, boolean readFilter) { _poolReference = refCountingPool; _name = name; _maxEvents = maxEvents; + _readFilter = readFilter; } /** @@ -167,7 +152,6 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo void fireAsynchEvent(Job job, Event event) { - // job.acquire(); //prevents this job being removed from _jobs job.add(event); final ExecutorService pool = _poolReference.getPool(); @@ -201,7 +185,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo */ public void createNewJobForSession(IoSession session) { - Job job = new Job(session, this, MAX_JOB_EVENTS); + Job job = new Job(session, this, MAX_JOB_EVENTS,_readFilter); session.setAttribute(_name, job); } @@ -433,7 +417,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo */ public AsynchReadPoolingFilter(ReferenceCountingExecutorService refCountingPool, String name) { - super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_read_events", MAX_JOB_EVENTS)); + super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_read_events", MAX_JOB_EVENTS),true); } /** @@ -476,7 +460,7 @@ public abstract class PoolingFilter extends IoFilterAdapter implements Job.JobCo */ public AsynchWritePoolingFilter(ReferenceCountingExecutorService refCountingPool, String name) { - super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_write_events", MAX_JOB_EVENTS)); + super(refCountingPool, name, Integer.getInteger("amqj.server.read_write_pool.max_write_events", MAX_JOB_EVENTS),false); } /** diff --git a/java/common/src/main/java/org/apache/qpid/pool/ReadWriteJobQueue.java b/java/common/src/main/java/org/apache/qpid/pool/ReadWriteJobQueue.java new file mode 100644 index 0000000000..8de0f93ce9 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/pool/ReadWriteJobQueue.java @@ -0,0 +1,432 @@ +package org.apache.qpid.pool; + +import java.util.AbstractQueue; +import java.util.Iterator; +import java.util.Collection; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.Condition; +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 ReadWriteJobQueue extends AbstractQueue implements BlockingQueue +{ + + private final AtomicInteger _count = new AtomicInteger(0); + + private final ReentrantLock _takeLock = new ReentrantLock(); + + private final Condition _notEmpty = _takeLock.newCondition(); + + private final ReentrantLock _putLock = new ReentrantLock(); + + private final ConcurrentLinkedQueue _readJobQueue = new ConcurrentLinkedQueue(); + + private final ConcurrentLinkedQueue _writeJobQueue = new ConcurrentLinkedQueue(); + + + private class ReadWriteJobIterator implements Iterator + { + + private boolean _onReads; + private Iterator _iter = _writeJobQueue.iterator(); + + public boolean hasNext() + { + if(!_iter.hasNext()) + { + if(_onReads) + { + _iter = _readJobQueue.iterator(); + _onReads = true; + return _iter.hasNext(); + } + else + { + return false; + } + } + else + { + return true; + } + } + + public Runnable next() + { + if(_iter.hasNext()) + { + return _iter.next(); + } + else + { + return null; + } + } + + public void remove() + { + _takeLock.lock(); + try + { + _iter.remove(); + _count.decrementAndGet(); + } + finally + { + _takeLock.unlock(); + } + } + } + + public Iterator iterator() + { + return new ReadWriteJobIterator(); + } + + public int size() + { + return _count.get(); + } + + public boolean offer(final Runnable runnable) + { + final ReadWriteRunnable job = (ReadWriteRunnable) runnable; + final ReentrantLock putLock = _putLock; + putLock.lock(); + try + { + if(job.isRead()) + { + _readJobQueue.offer(job); + } + else + { + _writeJobQueue.offer(job); + } + if(_count.getAndIncrement() == 0) + { + _takeLock.lock(); + try + { + _notEmpty.signal(); + } + finally + { + _takeLock.unlock(); + } + } + return true; + } + finally + { + putLock.unlock(); + } + } + + public void put(final Runnable runnable) throws InterruptedException + { + final ReadWriteRunnable job = (ReadWriteRunnable) runnable; + final ReentrantLock putLock = _putLock; + putLock.lock(); + + try + { + if(job.isRead()) + { + _readJobQueue.offer(job); + } + else + { + _writeJobQueue.offer(job); + } + if(_count.getAndIncrement() == 0) + { + _takeLock.lock(); + try + { + _notEmpty.signal(); + } + finally + { + _takeLock.unlock(); + } + } + + } + finally + { + putLock.unlock(); + } + } + + + + public boolean offer(final Runnable runnable, final long timeout, final TimeUnit unit) throws InterruptedException + { + final ReadWriteRunnable job = (ReadWriteRunnable) runnable; + final ReentrantLock putLock = _putLock; + putLock.lock(); + + try + { + if(job.isRead()) + { + _readJobQueue.offer(job); + } + else + { + _writeJobQueue.offer(job); + } + if(_count.getAndIncrement() == 0) + { + _takeLock.lock(); + try + { + _notEmpty.signal(); + } + finally + { + _takeLock.unlock(); + } + } + + return true; + } + finally + { + putLock.unlock(); + } + + } + + public Runnable take() throws InterruptedException + { + final ReentrantLock takeLock = _takeLock; + takeLock.lockInterruptibly(); + try + { + try + { + while (_count.get() == 0) + { + _notEmpty.await(); + } + } + catch (InterruptedException ie) + { + _notEmpty.signal(); + throw ie; + } + + ReadWriteRunnable job = _writeJobQueue.poll(); + if(job == null) + { + job = _readJobQueue.poll(); + } + int c = _count.getAndDecrement(); + if (c > 1) + { + _notEmpty.signal(); + } + return job; + } + finally + { + takeLock.unlock(); + } + + + } + + public Runnable poll(final long timeout, final TimeUnit unit) throws InterruptedException + { + final ReentrantLock takeLock = _takeLock; + final AtomicInteger count = _count; + long nanos = unit.toNanos(timeout); + takeLock.lockInterruptibly(); + ReadWriteRunnable job = null; + try + { + + for (;;) + { + if (count.get() > 0) + { + job = _writeJobQueue.poll(); + if(job == null) + { + job = _readJobQueue.poll(); + } + int c = count.getAndDecrement(); + if (c > 1) + { + _notEmpty.signal(); + } + break; + } + if (nanos <= 0) + { + return null; + } + try + { + nanos = _notEmpty.awaitNanos(nanos); + } + catch (InterruptedException ie) + { + _notEmpty.signal(); + throw ie; + } + } + } + finally + { + takeLock.unlock(); + } + + return job; + } + + public int remainingCapacity() + { + return Integer.MAX_VALUE; + } + + public int drainTo(final Collection c) + { + int total = 0; + + _putLock.lock(); + _takeLock.lock(); + try + { + ReadWriteRunnable job; + while((job = _writeJobQueue.peek())!= null) + { + c.add(job); + _writeJobQueue.poll(); + _count.decrementAndGet(); + total++; + } + + while((job = _readJobQueue.peek())!= null) + { + c.add(job); + _readJobQueue.poll(); + _count.decrementAndGet(); + total++; + } + + } + finally + { + _takeLock.unlock(); + _putLock.unlock(); + } + return total; + } + + public int drainTo(final Collection c, final int maxElements) + { + int total = 0; + + _putLock.lock(); + _takeLock.lock(); + try + { + ReadWriteRunnable job; + while(total<=maxElements && (job = _writeJobQueue.peek())!= null) + { + c.add(job); + _writeJobQueue.poll(); + _count.decrementAndGet(); + total++; + } + + while(total<=maxElements && (job = _readJobQueue.peek())!= null) + { + c.add(job); + _readJobQueue.poll(); + _count.decrementAndGet(); + total++; + } + + } + finally + { + _takeLock.unlock(); + _putLock.unlock(); + } + return total; + + } + + public Runnable poll() + { + final ReentrantLock takeLock = _takeLock; + takeLock.lock(); + try + { + if(_count.get() > 0) + { + ReadWriteRunnable job = _writeJobQueue.poll(); + if(job == null) + { + job = _readJobQueue.poll(); + } + _count.decrementAndGet(); + return job; + } + else + { + return null; + } + } + finally + { + takeLock.unlock(); + } + + } + + public Runnable peek() + { + final ReentrantLock takeLock = _takeLock; + takeLock.lock(); + try + { + ReadWriteRunnable job = _writeJobQueue.peek(); + if(job == null) + { + job = _readJobQueue.peek(); + } + return job; + } + finally + { + takeLock.unlock(); + } + } +} diff --git a/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java b/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java new file mode 100644 index 0000000000..ad04a923e1 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/pool/ReadWriteRunnable.java @@ -0,0 +1,27 @@ +package org.apache.qpid.pool; + +/* +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT 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 interface ReadWriteRunnable extends Runnable +{ + boolean isRead(); + boolean isWrite(); +} diff --git a/java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java b/java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java index 84c9e1f465..ce9c6ae4cb 100644 --- a/java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java +++ b/java/common/src/main/java/org/apache/qpid/pool/ReferenceCountingExecutorService.java @@ -22,6 +22,9 @@ package org.apache.qpid.pool; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.LinkedBlockingQueue; /** * ReferenceCountingExecutorService wraps an ExecutorService in order to provide shared reference to it. It counts @@ -84,6 +87,8 @@ public class ReferenceCountingExecutorService /** Holds the number of executor threads to create. */ private int _poolSize = Integer.getInteger("amqj.read_write_pool_size", DEFAULT_POOL_SIZE); + private final boolean _useBiasedPool = Boolean.getBoolean("org.apache.qpid.use_write_biased_pool"); + /** * Retrieves the singleton instance of this reference counter. * @@ -105,15 +110,28 @@ public class ReferenceCountingExecutorService * * @return An executor service. */ - ExecutorService acquireExecutorService() + public ExecutorService acquireExecutorService() { synchronized (_lock) { if (_refCount++ == 0) { - _pool = Executors.newFixedThreadPool(_poolSize); +// _pool = Executors.newFixedThreadPool(_poolSize); + + // Use a job queue that biases to writes + if(_useBiasedPool) + { + _pool = new ThreadPoolExecutor(_poolSize, _poolSize, + 0L, TimeUnit.MILLISECONDS, + new ReadWriteJobQueue()); + } + else + { + _pool = Executors.newFixedThreadPool(_poolSize); + } } + return _pool; } } @@ -122,7 +140,7 @@ public class ReferenceCountingExecutorService * Releases a reference to a shared executor service, decrementing the reference count. If the refence count falls * to zero, the executor service is shut down. */ - void releaseExecutorService() + public void releaseExecutorService() { synchronized (_lock) { diff --git a/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java b/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java index 59003225b7..b58e7d01dc 100644 --- a/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java +++ b/java/common/src/main/java/org/apache/qpid/protocol/AMQVersionAwareProtocolSession.java @@ -21,8 +21,12 @@ package org.apache.qpid.protocol; import org.apache.qpid.framing.*; +import org.apache.qpid.transport.Sender; import org.apache.qpid.AMQException; +import java.nio.ByteBuffer; + + /** * AMQVersionAwareProtocolSession is implemented by all AMQP session classes, that need to provide an awareness to * callers of the version of the AMQP protocol that they are able to work with. @@ -54,4 +58,7 @@ public interface AMQVersionAwareProtocolSession extends AMQProtocolWriter, Proto public void heartbeatBodyReceived(int channelId, HeartbeatBody body) throws AMQException; + public void setSender(Sender sender); + public void init(); + } diff --git a/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java b/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java new file mode 100644 index 0000000000..a3dad9acdc --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/security/AMQPCallbackHandler.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.security; + +import javax.security.auth.callback.CallbackHandler; + +public interface AMQPCallbackHandler extends CallbackHandler +{ + void initialise(String username,String password); +} diff --git a/java/common/src/main/java/org/apache/qpid/security/CallbackHandlerRegistry.java b/java/common/src/main/java/org/apache/qpid/security/CallbackHandlerRegistry.java new file mode 100644 index 0000000000..8c80a1b5b7 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/security/CallbackHandlerRegistry.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.security; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.QpidConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class CallbackHandlerRegistry +{ + private static final Logger _logger = LoggerFactory.getLogger(CallbackHandlerRegistry.class); + private static CallbackHandlerRegistry _instance = new CallbackHandlerRegistry(); + + private Map _mechanismToHandlerClassMap = new HashMap(); + + private StringBuilder _mechanisms; + + public static CallbackHandlerRegistry getInstance() + { + return _instance; + } + + public Class getCallbackHandlerClass(String mechanism) + { + return _mechanismToHandlerClassMap.get(mechanism); + } + + public String getMechanisms() + { + return _mechanisms.toString(); + } + + private CallbackHandlerRegistry() + { + // first we register any Sasl client factories + DynamicSaslRegistrar.registerSaslProviders(); + registerMechanisms(); + } + + private void registerMechanisms() + { + for (QpidConfig.SecurityMechanism securityMechanism: QpidConfig.get().getSecurityMechanisms() ) + { + Class clazz = null; + try + { + clazz = Class.forName(securityMechanism.getHandler()); + if (!AMQPCallbackHandler.class.isAssignableFrom(clazz)) + { + _logger.debug("SASL provider " + clazz + " does not implement " + AMQPCallbackHandler.class + + ". Skipping"); + continue; + } + _mechanismToHandlerClassMap.put(securityMechanism.getType(), clazz); + if (_mechanisms == null) + { + + _mechanisms = new StringBuilder(); + _mechanisms.append(securityMechanism.getType()); + } + else + { + _mechanisms.append(" " + securityMechanism.getType()); + } + } + catch (ClassNotFoundException ex) + { + _logger.debug("Unable to load class " + securityMechanism.getHandler() + ". Skipping that SASL provider"); + continue; + } + } + } +} diff --git a/java/common/src/main/java/org/apache/qpid/security/DynamicSaslRegistrar.java b/java/common/src/main/java/org/apache/qpid/security/DynamicSaslRegistrar.java new file mode 100644 index 0000000000..9f48ac96a3 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/security/DynamicSaslRegistrar.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.security; + +import java.security.Security; +import java.util.Map; +import java.util.TreeMap; + +import javax.security.sasl.SaslClientFactory; + +import org.apache.qpid.QpidConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DynamicSaslRegistrar +{ + private static final Logger _logger = LoggerFactory.getLogger(DynamicSaslRegistrar.class); + + public static void registerSaslProviders() + { + Map factories = registerSaslClientFactories(); + if (factories.size() > 0) + { + Security.addProvider(new JCAProvider(factories)); + _logger.debug("Dynamic SASL provider added as a security provider"); + } + } + + private static Map registerSaslClientFactories() + { + TreeMap factoriesToRegister = + new TreeMap(); + + for (QpidConfig.SaslClientFactory factory: QpidConfig.get().getSaslClientFactories()) + { + String className = factory.getFactoryClass(); + try + { + Class clazz = Class.forName(className); + if (!(SaslClientFactory.class.isAssignableFrom(clazz))) + { + _logger.debug("Class " + clazz + " does not implement " + SaslClientFactory.class + " - skipping"); + continue; + } + factoriesToRegister.put(factory.getType(), clazz); + } + catch (Exception ex) + { + _logger.debug("Error instantiating SaslClientFactory calss " + className + " - skipping"); + } + } + return factoriesToRegister; + } + + +} diff --git a/java/common/src/main/java/org/apache/qpid/security/JCAProvider.java b/java/common/src/main/java/org/apache/qpid/security/JCAProvider.java new file mode 100644 index 0000000000..033deb550c --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/security/JCAProvider.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.security; + +import java.security.Provider; +import java.security.Security; +import java.util.Map; + +public class JCAProvider extends Provider +{ + public JCAProvider(Map providerMap) + { + super("AMQSASLProvider", 1.0, "A JCA provider that registers all " + + "AMQ SASL providers that want to be registered"); + register(providerMap); + Security.addProvider(this); + } + + private void register(Map providerMap) + { + for (Map.Entry me :providerMap.entrySet()) + { + put("SaslClientFactory." + me.getKey(), me.getValue().getName()); + } + } +} \ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java b/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java new file mode 100644 index 0000000000..89a63abeab --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/security/UsernamePasswordCallbackHandler.java @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.security; + +import java.io.IOException; + +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.UnsupportedCallbackException; + +public class UsernamePasswordCallbackHandler implements AMQPCallbackHandler +{ + private String _username; + private String _password; + + public void initialise(String username,String password) + { + _username = username; + _password = password; + } + + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + for (int i = 0; i < callbacks.length; i++) + { + Callback cb = callbacks[i]; + if (cb instanceof NameCallback) + { + ((NameCallback)cb).setName(_username); + } + else if (cb instanceof PasswordCallback) + { + ((PasswordCallback)cb).setPassword((_password).toCharArray()); + } + else + { + throw new UnsupportedCallbackException(cb); + } + } + } +} diff --git a/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClient.java b/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClient.java new file mode 100644 index 0000000000..81acc66de4 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClient.java @@ -0,0 +1,105 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.security.amqplain; + +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.FieldTableFactory; + +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslException; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.PasswordCallback; +import javax.security.auth.callback.Callback; + +/** + * Implements the "AMQPlain" authentication protocol that uses FieldTables to send username and pwd. + * + */ +public class AmqPlainSaslClient implements SaslClient +{ + /** + * The name of this mechanism + */ + public static final String MECHANISM = "AMQPLAIN"; + + private CallbackHandler _cbh; + + public AmqPlainSaslClient(CallbackHandler cbh) + { + _cbh = cbh; + } + + public String getMechanismName() + { + return "AMQPLAIN"; + } + + public boolean hasInitialResponse() + { + return true; + } + + public byte[] evaluateChallenge(byte[] challenge) throws SaslException + { + // we do not care about the prompt or the default name + NameCallback nameCallback = new NameCallback("prompt", "defaultName"); + PasswordCallback pwdCallback = new PasswordCallback("prompt", false); + Callback[] callbacks = new Callback[]{nameCallback, pwdCallback}; + try + { + _cbh.handle(callbacks); + } + catch (Exception e) + { + throw new SaslException("Error handling SASL callbacks: " + e, e); + } + FieldTable table = FieldTableFactory.newFieldTable(); + table.setString("LOGIN", nameCallback.getName()); + table.setString("PASSWORD", new String(pwdCallback.getPassword())); + return table.getDataAsBytes(); + } + + public boolean isComplete() + { + return true; + } + + public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException + { + throw new SaslException("Not supported"); + } + + public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException + { + throw new SaslException("Not supported"); + } + + public Object getNegotiatedProperty(String propName) + { + return null; + } + + public void dispose() throws SaslException + { + _cbh = null; + } +} diff --git a/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClientFactory.java b/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClientFactory.java new file mode 100644 index 0000000000..6c66c87f4c --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/security/amqplain/AmqPlainSaslClientFactory.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.security.amqplain; + +import javax.security.sasl.SaslClientFactory; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslException; +import javax.security.sasl.Sasl; +import javax.security.auth.callback.CallbackHandler; +import java.util.Map; + +public class AmqPlainSaslClientFactory implements SaslClientFactory +{ + public SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol, String serverName, Map props, CallbackHandler cbh) throws SaslException + { + for (int i = 0; i < mechanisms.length; i++) + { + if (mechanisms[i].equals(AmqPlainSaslClient.MECHANISM)) + { + if (cbh == null) + { + throw new SaslException("CallbackHandler must not be null"); + } + return new AmqPlainSaslClient(cbh); + } + } + return null; + } + + public String[] getMechanismNames(Map props) + { + if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) || + props.containsKey(Sasl.POLICY_NODICTIONARY) || + props.containsKey(Sasl.POLICY_NOACTIVE)) + { + // returned array must be non null according to interface documentation + return new String[0]; + } + else + { + return new String[]{AmqPlainSaslClient.MECHANISM}; + } + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Binary.java b/java/common/src/main/java/org/apache/qpid/transport/Binary.java new file mode 100644 index 0000000000..e6dedc536f --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Binary.java @@ -0,0 +1,129 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +/** + * Binary + * + */ + +public final class Binary +{ + + private byte[] bytes; + private int offset; + private int size; + private int hash = 0; + + public Binary(byte[] bytes, int offset, int size) + { + if (offset + size > bytes.length) + { + throw new ArrayIndexOutOfBoundsException(); + } + + this.bytes = bytes; + this.offset = offset; + this.size = size; + } + + public Binary(byte[] bytes) + { + this(bytes, 0, bytes.length); + } + + public final byte[] array() + { + return bytes; + } + + public final int offset() + { + return offset; + } + + public final int size() + { + return size; + } + + public final Binary slice(int low, int high) + { + int sz; + + if (high < 0) + { + sz = size + high; + } + else + { + sz = high - low; + } + + if (sz < 0) + { + sz = 0; + } + + return new Binary(bytes, offset + low, sz); + } + + public final int hashCode() + { + if (hash == 0) + { + int hc = 0; + for (int i = 0; i < size; i++) + { + hc = 31*hc + (0xFF & bytes[offset + i]); + } + hash = hc; + } + + return hash; + } + + public final boolean equals(Object o) + { + if (!(o instanceof Binary)) + { + return false; + } + + Binary buf = (Binary) o; + if (this.size != buf.size) + { + return false; + } + + for (int i = 0; i < size; i++) + { + if (bytes[offset + i] != buf.bytes[buf.offset + i]) + { + return false; + } + } + + return true; + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Binding.java b/java/common/src/main/java/org/apache/qpid/transport/Binding.java new file mode 100644 index 0000000000..8418c42189 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Binding.java @@ -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. + * + */ +package org.apache.qpid.transport; + + +/** + * Binding + * + */ + +public interface Binding +{ + + E endpoint(Sender sender); + + Receiver receiver(E endpoint); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Channel.java b/java/common/src/main/java/org/apache/qpid/transport/Channel.java new file mode 100644 index 0000000000..d6b015930b --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Channel.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.transport; + +import org.apache.qpid.transport.network.Frame; +import org.apache.qpid.transport.util.Logger; + +import java.nio.ByteBuffer; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import static org.apache.qpid.transport.network.Frame.*; +import static org.apache.qpid.transport.util.Functions.*; + + +/** + * Channel + * + * @author Rafael H. Schloming + */ + +public class Channel extends Invoker + implements Receiver, ProtocolDelegate +{ + + private static final Logger log = Logger.get(Channel.class); + + final private Connection connection; + final private int channel; + final private MethodDelegate delegate; + final private SessionDelegate sessionDelegate; + // session may be null + private Session session; + + public Channel(Connection connection, int channel, SessionDelegate delegate) + { + this.connection = connection; + this.channel = channel; + this.delegate = new ChannelDelegate(); + this.sessionDelegate = delegate; + } + + public Connection getConnection() + { + return connection; + } + + public void received(ProtocolEvent event) + { + event.delegate(null, this); + } + + public void init(Void v, ProtocolHeader hdr) + { + connection.getConnectionDelegate().init(this, hdr); + } + + public void control(Void v, Method method) + { + switch (method.getEncodedTrack()) + { + case L1: + method.dispatch(this, connection.getConnectionDelegate()); + break; + case L2: + method.dispatch(this, delegate); + break; + case L3: + method.delegate(session, sessionDelegate); + break; + default: + throw new IllegalStateException + ("unknown track: " + method.getEncodedTrack()); + } + } + + public void command(Void v, Method method) + { + method.delegate(session, sessionDelegate); + } + + public void error(Void v, ProtocolError error) + { + throw new RuntimeException(error.getMessage()); + } + + public void exception(Throwable t) + { + session.exception(t); + } + + public void closed() + { + log.debug("channel closed: ", this); + if (session != null) + { + session.closed(); + } + connection.removeChannel(channel); + } + + public int getEncodedChannel() { + return channel; + } + + public Session getSession() + { + return session; + } + + void setSession(Session session) + { + this.session = session; + } + + void closeCode(ConnectionClose close) + { + if (session != null) + { + session.closeCode(close); + } + } + + private void emit(ProtocolEvent event) + { + event.setChannel(channel); + connection.send(event); + } + + public void method(Method m) + { + emit(m); + + if (!m.isBatch()) + { + connection.flush(); + } + } + + protected void invoke(Method m) + { + method(m); + } + + protected Future invoke(Method m, Class cls) + { + throw new UnsupportedOperationException(); + } + + public String toString() + { + return String.format("%s:%s", connection, channel); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ChannelDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ChannelDelegate.java new file mode 100644 index 0000000000..8475fbf174 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ChannelDelegate.java @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import java.util.UUID; + + +/** + * ChannelDelegate + * + * @author Rafael H. Schloming + */ + +class ChannelDelegate extends MethodDelegate +{ + + public @Override void sessionAttach(Channel channel, SessionAttach atch) + { + Session ssn = new Session(atch.getName()); + ssn.attach(channel); + ssn.sessionAttached(ssn.getName()); + } + + public @Override void sessionDetached(Channel channel, SessionDetached closed) + { + channel.closed(); + } + + public @Override void sessionDetach(Channel channel, SessionDetach dtc) + { + channel.getSession().closed(); + channel.sessionDetached(dtc.getName(), SessionDetachCode.NORMAL); + channel.closed(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java new file mode 100644 index 0000000000..bbdadfadb9 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ClientDelegate.java @@ -0,0 +1,40 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +/** + * ClientDelegate + * + */ + +public abstract class ClientDelegate extends ConnectionDelegate +{ + + public void init(Channel ch, ProtocolHeader hdr) + { + if (hdr.getMajor() != 0 && hdr.getMinor() != 10) + { + throw new ProtocolVersionException(hdr.getMajor(), hdr.getMinor()); + } + } + +} 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 new file mode 100644 index 0000000000..68b9b209bb --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Connection.java @@ -0,0 +1,186 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import org.apache.qpid.transport.util.Logger; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import java.nio.ByteBuffer; + + +/** + * Connection + * + * @author Rafael H. Schloming + * + * @todo the channels map should probably be replaced with something + * more efficient, e.g. an array or a map implementation that can use + * short instead of Short + */ + +public class Connection + implements Receiver, Sender +{ + + private static final Logger log = Logger.get(Connection.class); + + final private Sender sender; + final private ConnectionDelegate delegate; + private int channelMax = 1; + // want to make this final + private int _connectionId; + + final private Map channels = new HashMap(); + + public Connection(Sender sender, + ConnectionDelegate delegate) + { + this.sender = sender; + this.delegate = delegate; + } + + public void setConnectionId(int id) + { + _connectionId = id; + } + + public int getConnectionId() + { + return _connectionId; + } + + public ConnectionDelegate getConnectionDelegate() + { + return delegate; + } + + public void received(ProtocolEvent event) + { + log.debug("RECV: [%s] %s", this, event); + Channel channel = getChannel(event.getChannel()); + channel.received(event); + } + + public void send(ProtocolEvent event) + { + log.debug("SEND: [%s] %s", this, event); + sender.send(event); + } + + public void flush() + { + log.debug("FLUSH: [%s]", this); + sender.flush(); + } + + public int getChannelMax() + { + return channelMax; + } + + void setChannelMax(int max) + { + channelMax = max; + } + + public Channel getChannel() + { + synchronized (channels) + { + for (int i = 0; i < getChannelMax(); i++) + { + if (!channels.containsKey(i)) + { + return getChannel(i); + } + } + + throw new RuntimeException("no more channels available"); + } + } + + public Channel getChannel(int number) + { + synchronized (channels) + { + Channel channel = channels.get(number); + if (channel == null) + { + channel = new Channel(this, number, delegate.getSessionDelegate()); + channels.put(number, channel); + } + return channel; + } + } + + void removeChannel(int number) + { + synchronized (channels) + { + channels.remove(number); + } + } + + public void exception(Throwable t) + { + delegate.exception(t); + } + + void closeCode(ConnectionClose close) + { + synchronized (channels) + { + for (Channel ch : channels.values()) + { + ch.closeCode(close); + } + } + } + + public void closed() + { + log.debug("connection closed: %s", this); + synchronized (channels) + { + List values = new ArrayList(channels.values()); + for (Channel ch : values) + { + ch.closed(); + } + } + delegate.closed(); + } + + public void close() + { + sender.close(); + } + + public String toString() + { + return String.format("conn:%x", System.identityHashCode(this)); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java new file mode 100644 index 0000000000..2aa1db7b28 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ConnectionDelegate.java @@ -0,0 +1,287 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import org.apache.qpid.transport.util.Logger; + +import org.apache.qpid.SecurityHelper; +import org.apache.qpid.QpidException; + +import java.io.UnsupportedEncodingException; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; + +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + + +/** + * ConnectionDelegate + * + * @author Rafael H. Schloming + */ + +/** + * Currently only implemented client specific methods + * the server specific methods are dummy impls for testing + * + * the connectionClose is kind of different for both sides + */ +public abstract class ConnectionDelegate extends MethodDelegate +{ + + private static final Logger log = Logger.get(ConnectionDelegate.class); + + private String _username = "guest"; + private String _password = "guest";; + private String _mechanism; + private String _virtualHost; + private SaslClient saslClient; + private SaslServer saslServer; + private String _locale = "utf8"; + private int maxFrame = 64*1024; + private Condition _negotiationComplete; + private Lock _negotiationCompleteLock; + + public abstract SessionDelegate getSessionDelegate(); + + public abstract void exception(Throwable t); + + public abstract void closed(); + + public void setCondition(Lock negotiationCompleteLock,Condition negotiationComplete) + { + _negotiationComplete = negotiationComplete; + _negotiationCompleteLock = negotiationCompleteLock; + } + + public void init(Channel ch, ProtocolHeader hdr) + { + ch.getConnection().send(new ProtocolHeader (1, hdr.getMajor(), hdr.getMinor())); + List plain = new ArrayList(); + plain.add("PLAIN"); + List utf8 = new ArrayList(); + utf8.add("utf8"); + ch.connectionStart(null, plain, utf8); + } + + // ---------------------------------------------- + // Client side + //----------------------------------------------- + @Override public void connectionStart(Channel context, ConnectionStart struct) + { + String mechanism = null; + byte[] response = null; + try + { + mechanism = SecurityHelper.chooseMechanism(struct.getMechanisms()); + saslClient = Sasl.createSaslClient(new String[]{ mechanism },null, "AMQP", "localhost", null, + SecurityHelper.createCallbackHandler(mechanism,_username,_password )); + response = saslClient.evaluateChallenge(new byte[0]); + } + catch (UnsupportedEncodingException e) + { + // need error handling + } + catch (SaslException e) + { + // need error handling + } + catch (QpidException e) + { + // need error handling + } + + Map props = new HashMap(); + context.connectionStartOk(props, mechanism, response, _locale); + } + + @Override public void connectionSecure(Channel context, ConnectionSecure struct) + { + try + { + byte[] response = saslClient.evaluateChallenge(struct.getChallenge()); + context.connectionSecureOk(response); + } + catch (SaslException e) + { + // need error handling + } + } + + @Override public void connectionTune(Channel context, ConnectionTune struct) + { + context.getConnection().setChannelMax(struct.getChannelMax()); + context.connectionTuneOk(struct.getChannelMax(), struct.getMaxFrameSize(), struct.getHeartbeatMax()); + context.connectionOpen(_virtualHost, null, Option.INSIST); + } + + + @Override public void connectionOpenOk(Channel context, ConnectionOpenOk struct) + { + List knownHosts = struct.getKnownHosts(); + if(_negotiationCompleteLock != null) + { + _negotiationCompleteLock.lock(); + try + { + _negotiationComplete.signalAll(); + } + finally + { + _negotiationCompleteLock.unlock(); + } + } + } + + public void connectionRedirect(Channel context, ConnectionRedirect struct) + { + // not going to bother at the moment + } + + // ---------------------------------------------- + // Server side + //----------------------------------------------- + @Override public void connectionStartOk(Channel context, ConnectionStartOk struct) + { + //set the client side locale on the server side + _locale = struct.getLocale(); + _mechanism = struct.getMechanism(); + + //try + //{ + //saslServer = Sasl.createSaslServer(_mechanism, "AMQP", "ABC",null,SecurityHelper.createCallbackHandler(_mechanism,_username,_password)); + //byte[] challenge = saslServer.evaluateResponse(struct.getResponse().getBytes()); + byte[] challenge = null; + if ( challenge == null) + { + context.connectionTune(Integer.MAX_VALUE, maxFrame, 0, Integer.MAX_VALUE); + } + else + { + try + { + context.connectionSecure(challenge); + } + catch(Exception e) + { + + } + } + + + /*} + catch (SaslException e) + { + // need error handling + } + catch (QpidException e) + { + // need error handling + }*/ + } + + @Override public void connectionSecureOk(Channel context, ConnectionSecureOk struct) + { + try + { + saslServer = Sasl.createSaslServer(_mechanism, "AMQP", "ABC",new HashMap(),SecurityHelper.createCallbackHandler(_mechanism,_username,_password)); + byte[] challenge = saslServer.evaluateResponse(struct.getResponse()); + if ( challenge == null) + { + context.connectionTune(Integer.MAX_VALUE, maxFrame, 0, Integer.MAX_VALUE); + } + else + { + try + { + context.connectionSecure(challenge); + } + catch(Exception e) + { + + } + } + + + } + catch (SaslException e) + { + // need error handling + } + catch (QpidException e) + { + // need error handling + } + } + + + @Override public void connectionOpen(Channel context, ConnectionOpen struct) + { + List hosts = new ArrayList(); + hosts.add("amqp:1223243232325"); + context.connectionOpenOk(hosts); + } + + @Override public void connectionClose(Channel ch, ConnectionClose close) + { + ch.getConnection().closeCode(close); + ch.connectionCloseOk(); + } + + public String getPassword() + { + return _password; + } + + public void setPassword(String password) + { + _password = password; + } + + public String getUsername() + { + return _username; + } + + public void setUsername(String username) + { + _username = username; + } + + public String getVirtualHost() + { + return _virtualHost; + } + + public void setVirtualHost(String host) + { + _virtualHost = host; + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ConnectionException.java b/java/common/src/main/java/org/apache/qpid/transport/ConnectionException.java new file mode 100644 index 0000000000..c3239ef684 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ConnectionException.java @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +/** + * ConnectionException + * + */ + +public class ConnectionException extends RuntimeException +{ + + private ConnectionClose close; + + public ConnectionException(ConnectionClose close) + { + super(close.getReplyText()); + this.close = close; + } + + public ConnectionClose getClose() + { + return close; + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Echo.java b/java/common/src/main/java/org/apache/qpid/transport/Echo.java new file mode 100644 index 0000000000..b2be32331a --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Echo.java @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.network.ConnectionBinding; +import org.apache.qpid.transport.network.io.IoAcceptor; + + +/** + * Echo + * + */ + +public class Echo extends SessionDelegate +{ + + public void messageTransfer(Session ssn, MessageTransfer xfr) + { + ssn.invoke(xfr); + ssn.processed(xfr); + } + + public static final void main(String[] args) throws IOException + { + ConnectionDelegate delegate = new ConnectionDelegate() + { + public SessionDelegate getSessionDelegate() + { + return new Echo(); + } + public void exception(Throwable t) + { + t.printStackTrace(); + } + public void closed() {} + }; + + //hack + delegate.setUsername("guest"); + delegate.setPassword("guest"); + + IoAcceptor ioa = new IoAcceptor + ("0.0.0.0", 5672, new ConnectionBinding(delegate)); + ioa.start(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Field.java b/java/common/src/main/java/org/apache/qpid/transport/Field.java new file mode 100644 index 0000000000..bc6bf10041 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Field.java @@ -0,0 +1,83 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encoder; + + +/** + * Field + * + */ + +public abstract class Field +{ + + private final Class container; + private final Class type; + private final String name; + private final int index; + + Field(Class container, Class type, String name, int index) + { + this.container = container; + this.type = type; + this.name = name; + this.index = index; + } + + public final Class getContainer() + { + return container; + } + + public final Class getType() + { + return type; + } + + public final String getName() + { + return name; + } + + public final int getIndex() + { + return index; + } + + protected final C check(Object struct) + { + return container.cast(struct); + } + + public abstract boolean has(Object struct); + + public abstract void has(Object struct, boolean value); + + public abstract T get(Object struct); + + public abstract void read(Decoder dec, Object struct); + + public abstract void write(Encoder enc, Object struct); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Future.java b/java/common/src/main/java/org/apache/qpid/transport/Future.java new file mode 100644 index 0000000000..d8cde61af5 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Future.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.transport; + + +/** + * Future + * + * @author Rafael H. Schloming + */ + +public interface Future +{ + + T get(); + + boolean isDone(); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Header.java b/java/common/src/main/java/org/apache/qpid/transport/Header.java new file mode 100644 index 0000000000..9439e5e0de --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Header.java @@ -0,0 +1,92 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import org.apache.qpid.transport.network.Frame; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.LinkedHashMap; +import java.nio.ByteBuffer; + + +/** + * Header + * + * @author Rafael H. Schloming + */ + +public class Header { + + private final Struct[] structs; + + public Header(List structs) + { + this(structs.toArray(new Struct[structs.size()])); + } + + public Header(Struct ... structs) + { + this.structs = structs; + } + + public Struct[] getStructs() + { + return structs; + } + + + public T get(Class klass) + { + for (Struct st : structs) + { + if (klass.isInstance(st)) + { + return (T) st; + } + } + + return null; + } + + public String toString() + { + StringBuffer str = new StringBuffer(); + str.append(" Header("); + boolean first = true; + for (Struct s : structs) + { + if (first) + { + first = false; + } + else + { + str.append(", "); + } + str.append(s); + } + str.append(")"); + return str.toString(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Method.java b/java/common/src/main/java/org/apache/qpid/transport/Method.java new file mode 100644 index 0000000000..6b99f6d5d3 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Method.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.transport; + +import org.apache.qpid.transport.network.Frame; + +import java.nio.ByteBuffer; + +import static org.apache.qpid.transport.util.Functions.*; + +/** + * Method + * + * @author Rafael H. Schloming + */ + +public abstract class Method extends Struct implements ProtocolEvent +{ + + public static final Method create(int type) + { + // XXX: should generate separate factories for separate + // namespaces + return (Method) StructFactory.createInstruction(type); + } + + // XXX: command subclass? + private int id; + private int channel; + private boolean idSet = false; + private boolean sync = false; + private boolean batch = false; + + public final int getId() + { + return id; + } + + void setId(int id) + { + this.id = id; + this.idSet = true; + } + + public final int getChannel() + { + return channel; + } + + public final void setChannel(int channel) + { + this.channel = channel; + } + + public final boolean isSync() + { + return sync; + } + + final void setSync(boolean value) + { + this.sync = value; + } + + public final boolean isBatch() + { + return batch; + } + + final void setBatch(boolean value) + { + this.batch = value; + } + + public abstract boolean hasPayload(); + + public Header getHeader() + { + return null; + } + + public void setHeader(Header header) + { + throw new UnsupportedOperationException(); + } + + public ByteBuffer getBody() + { + return null; + } + + public void setBody(ByteBuffer body) + { + throw new UnsupportedOperationException(); + } + + public abstract byte getEncodedTrack(); + + public abstract void dispatch(C context, MethodDelegate delegate); + + public void delegate(C context, ProtocolDelegate delegate) + { + if (getEncodedTrack() == Frame.L4) + { + delegate.command(context, this); + } + else + { + delegate.control(context, this); + } + } + + public String toString() + { + StringBuilder str = new StringBuilder(); + + str.append("ch="); + str.append(channel); + + if (getEncodedTrack() == Frame.L4 && idSet) + { + str.append(" id="); + str.append(id); + } + + if (sync || batch) + { + str.append(" "); + str.append("["); + if (sync) + { + str.append("S"); + } + if (batch) + { + str.append("B"); + } + str.append("]"); + } + + str.append(" "); + str.append(super.toString()); + Header hdr = getHeader(); + if (hdr != null) + { + for (Struct st : hdr.getStructs()) + { + str.append("\n "); + str.append(st); + } + } + ByteBuffer body = getBody(); + if (body != null) + { + str.append("\n body="); + str.append(str(body, 64)); + } + + return str.toString(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ProtocolDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolDelegate.java new file mode 100644 index 0000000000..a90948fc1d --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolDelegate.java @@ -0,0 +1,40 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +/** + * ProtocolDelegate + * + */ + +public interface ProtocolDelegate +{ + + void init(C context, ProtocolHeader header); + + void control(C context, Method control); + + void command(C context, Method command); + + void error(C context, ProtocolError error); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ProtocolError.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolError.java new file mode 100644 index 0000000000..bd6ab81997 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolError.java @@ -0,0 +1,83 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import org.apache.qpid.transport.network.NetworkDelegate; +import org.apache.qpid.transport.network.NetworkEvent; + + +/** + * ProtocolError + * + * @author Rafael H. Schloming + */ + +public final class ProtocolError implements NetworkEvent, ProtocolEvent +{ + + private int channel; + private final byte track; + private final String format; + private final Object[] args; + + public ProtocolError(byte track, String format, Object ... args) + { + this.track = track; + this.format = format; + this.args = args; + } + + public int getChannel() + { + return channel; + } + + public void setChannel(int channel) + { + this.channel = channel; + } + + public byte getEncodedTrack() + { + return track; + } + + public String getMessage() + { + return String.format(format, args); + } + + public void delegate(C context, ProtocolDelegate delegate) + { + delegate.error(context, this); + } + + public void delegate(NetworkDelegate delegate) + { + delegate.error(this); + } + + public String toString() + { + return String.format("protocol error: %s", getMessage()); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ProtocolEvent.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolEvent.java new file mode 100644 index 0000000000..60234c1537 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolEvent.java @@ -0,0 +1,40 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +/** + * ProtocolEvent + * + */ + +public interface ProtocolEvent +{ + + int getChannel(); + + void setChannel(int channel); + + byte getEncodedTrack(); + + void delegate(C context, ProtocolDelegate delegate); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ProtocolHeader.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolHeader.java new file mode 100644 index 0000000000..fa0c1e9c63 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolHeader.java @@ -0,0 +1,116 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.network.NetworkDelegate; +import org.apache.qpid.transport.network.NetworkEvent; +import org.apache.qpid.transport.network.Frame; + + +/** + * ProtocolHeader + * + * @author Rafael H. Schloming + */ + +public final class ProtocolHeader implements NetworkEvent, ProtocolEvent +{ + + private static final byte[] AMQP = {'A', 'M', 'Q', 'P' }; + private static final byte CLASS = 1; + + final private byte instance; + final private byte major; + final private byte minor; + private int channel; + + public ProtocolHeader(byte instance, byte major, byte minor) + { + this.instance = instance; + this.major = major; + this.minor = minor; + } + + public ProtocolHeader(int instance, int major, int minor) + { + this((byte) instance, (byte) major, (byte) minor); + } + + public byte getInstance() + { + return instance; + } + + public byte getMajor() + { + return major; + } + + public byte getMinor() + { + return minor; + } + + public int getChannel() + { + return channel; + } + + public void setChannel(int channel) + { + this.channel = channel; + } + + public byte getEncodedTrack() + { + return Frame.L1; + } + + public ByteBuffer toByteBuffer() + { + ByteBuffer buf = ByteBuffer.allocate(8); + buf.put(AMQP); + buf.put(CLASS); + buf.put(instance); + buf.put(major); + buf.put(minor); + buf.flip(); + return buf; + } + + public void delegate(C context, ProtocolDelegate delegate) + { + delegate.init(context, this); + } + + public void delegate(NetworkDelegate delegate) + { + delegate.init(this); + } + + public String toString() + { + return String.format("AMQP.%d %d-%d", instance, major, minor); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/ProtocolVersionException.java b/java/common/src/main/java/org/apache/qpid/transport/ProtocolVersionException.java new file mode 100644 index 0000000000..2de0c169a5 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/ProtocolVersionException.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.transport; + + +/** + * ProtocolVersionException + * + */ + +public final class ProtocolVersionException extends TransportException +{ + + private final byte major; + private final byte minor; + + public ProtocolVersionException(byte major, byte minor) + { + super(String.format("version missmatch: %s-%s", major, minor)); + this.major = major; + this.minor = minor; + } + + public byte getMajor() + { + return this.major; + } + + public byte getMinor() + { + return this.minor; + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Range.java b/java/common/src/main/java/org/apache/qpid/transport/Range.java new file mode 100644 index 0000000000..f4335dc8a6 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Range.java @@ -0,0 +1,125 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import java.util.ArrayList; +import java.util.List; + +import static org.apache.qpid.util.Serial.*; + + +/** + * Range + * + * @author Rafael H. Schloming + */ + +public final class Range +{ + private final int lower; + private final int upper; + + public Range(int lower, int upper) + { + this.lower = lower; + this.upper = upper; + } + + public int getLower() + { + return lower; + } + + public int getUpper() + { + return upper; + } + + public boolean includes(int value) + { + return le(lower, value) && le(value, upper); + } + + public boolean includes(Range range) + { + return includes(range.lower) && includes(range.upper); + } + + public boolean intersects(Range range) + { + return (includes(range.lower) || includes(range.upper) || + range.includes(lower) || range.includes(upper)); + } + + public boolean touches(Range range) + { + return (intersects(range) || + includes(range.upper + 1) || includes(range.lower - 1) || + range.includes(upper + 1) || range.includes(lower - 1)); + } + + public Range span(Range range) + { + return new Range(min(lower, range.lower), max(upper, range.upper)); + } + + public List subtract(Range range) + { + List result = new ArrayList(); + + if (includes(range.lower) && le(lower, range.lower - 1)) + { + result.add(new Range(lower, range.lower - 1)); + } + + if (includes(range.upper) && le(range.upper + 1, upper)) + { + result.add(new Range(range.upper + 1, upper)); + } + + if (result.isEmpty() && !range.includes(this)) + { + result.add(this); + } + + return result; + } + + public Range intersect(Range range) + { + int l = max(lower, range.lower); + int r = min(upper, range.upper); + if (gt(l, r)) + { + return null; + } + else + { + return new Range(l, r); + } + } + + public String toString() + { + return "[" + lower + ", " + upper + "]"; + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java b/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java new file mode 100644 index 0000000000..9b2744ee8b --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/RangeSet.java @@ -0,0 +1,147 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import java.util.Iterator; +import java.util.ListIterator; +import java.util.LinkedList; + +import static org.apache.qpid.util.Serial.*; + +/** + * RangeSet + * + * @author Rafael H. Schloming + */ + +public final class RangeSet implements Iterable +{ + + private LinkedList ranges = new LinkedList(); + + public int size() + { + return ranges.size(); + } + + public Iterator iterator() + { + return ranges.iterator(); + } + + public Range getFirst() + { + return ranges.getFirst(); + } + + public boolean includes(Range range) + { + for (Range r : this) + { + if (r.includes(range)) + { + return true; + } + } + + return false; + } + + public boolean includes(int n) + { + for (Range r : this) + { + if (r.includes(n)) + { + return true; + } + } + + return false; + } + + public void add(Range range) + { + ListIterator it = ranges.listIterator(); + + while (it.hasNext()) + { + Range next = it.next(); + if (range.touches(next)) + { + it.remove(); + range = range.span(next); + } + else if (lt(range.getUpper(), next.getLower())) + { + it.previous(); + it.add(range); + return; + } + } + + it.add(range); + } + + public void add(int lower, int upper) + { + add(new Range(lower, upper)); + } + + public void add(int value) + { + add(value, value); + } + + public void clear() + { + ranges.clear(); + } + + public RangeSet copy() + { + RangeSet copy = new RangeSet(); + copy.ranges.addAll(ranges); + return copy; + } + + public String toString() + { + StringBuffer str = new StringBuffer(); + str.append("{"); + boolean first = true; + for (Range range : ranges) + { + if (first) + { + first = false; + } + else + { + str.append(", "); + } + str.append(range); + } + str.append("}"); + return str.toString(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Receiver.java b/java/common/src/main/java/org/apache/qpid/transport/Receiver.java new file mode 100644 index 0000000000..2a994580dc --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Receiver.java @@ -0,0 +1,38 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +/** + * Receiver + * + */ + +public interface Receiver +{ + + void received(T msg); + + void exception(Throwable t); + + void closed(); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Result.java b/java/common/src/main/java/org/apache/qpid/transport/Result.java new file mode 100644 index 0000000000..1116492a8d --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Result.java @@ -0,0 +1,30 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +/** + * Result + * + * @author Rafael H. Schloming + */ + +public abstract class Result extends Struct {} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Sender.java b/java/common/src/main/java/org/apache/qpid/transport/Sender.java new file mode 100644 index 0000000000..9a6f675d7f --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Sender.java @@ -0,0 +1,38 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +/** + * Sender + * + */ + +public interface Sender +{ + + void send(T msg); + + void flush(); + + void close(); + +} 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 new file mode 100644 index 0000000000..10ca6cfb0a --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Session.java @@ -0,0 +1,575 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + + +import org.apache.qpid.transport.network.Frame; + +import org.apache.qpid.transport.util.Logger; + +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import static org.apache.qpid.transport.Option.*; +import static org.apache.qpid.transport.util.Functions.*; +import static org.apache.qpid.util.Serial.*; +import static org.apache.qpid.util.Strings.*; + +/** + * Session + * + * @author Rafael H. Schloming + */ + +public class Session extends Invoker +{ + + private static final Logger log = Logger.get(Session.class); + + private static boolean ENABLE_REPLAY = false; + + static + { + String enableReplay = "enable_command_replay"; + try + { + ENABLE_REPLAY = new Boolean(System.getProperties().getProperty(enableReplay, "false")); + } + catch (Exception e) + { + ENABLE_REPLAY = false; + } + } + + private byte[] name; + private long timeout = 60000; + private boolean autoSync = false; + + // channel may be null + Channel channel; + + // incoming command count + int commandsIn = 0; + // completed incoming commands + private final Object processedLock = new Object(); + private RangeSet processed = new RangeSet(); + private int maxProcessed = commandsIn - 1; + private int syncPoint = maxProcessed; + + // outgoing command count + private int commandsOut = 0; + private Map commands = new HashMap(); + private int maxComplete = commandsOut - 1; + private boolean needSync = false; + + private AtomicBoolean closed = new AtomicBoolean(false); + + public Session(byte[] name) + { + this.name = name; + } + + public byte[] getName() + { + return name; + } + + public void setAutoSync(boolean value) + { + synchronized (commands) + { + this.autoSync = value; + } + } + + public Map getOutstandingCommands() + { + return commands; + } + + public int getCommandsOut() + { + return commandsOut; + } + + public int getCommandsIn() + { + return commandsIn; + } + + public int nextCommandId() + { + return commandsIn++; + } + + final void identify(Method cmd) + { + int id = nextCommandId(); + cmd.setId(id); + + if(log.isDebugEnabled()) + { + log.debug("ID: [%s] %s", this.channel, id); + } + + //if ((id % 65536) == 0) + if ((id & 0xff) == 0) + { + flushProcessed(TIMELY_REPLY); + } + } + + public void processed(Method command) + { + processed(command.getId()); + } + + public void processed(int command) + { + processed(new Range(command, command)); + } + + public void processed(int lower, int upper) + { + + processed(new Range(lower, upper)); + } + + public void processed(Range range) + { + log.debug("%s processed(%s)", this, range); + + boolean flush; + synchronized (processedLock) + { + processed.add(range); + Range first = processed.getFirst(); + int lower = first.getLower(); + int upper = first.getUpper(); + int old = maxProcessed; + if (le(lower, maxProcessed + 1)) + { + maxProcessed = max(maxProcessed, upper); + } + flush = lt(old, syncPoint) && ge(maxProcessed, syncPoint); + syncPoint = maxProcessed; + } + if (flush) + { + flushProcessed(); + } + } + + public void flushProcessed(Option ... options) + { + RangeSet copy; + synchronized (processedLock) + { + copy = processed.copy(); + } + sessionCompleted(copy, options); + } + + void knownComplete(RangeSet kc) + { + synchronized (processedLock) + { + RangeSet newProcessed = new RangeSet(); + for (Range pr : processed) + { + for (Range kr : kc) + { + for (Range r : pr.subtract(kr)) + { + newProcessed.add(r); + } + } + } + this.processed = newProcessed; + } + } + + void syncPoint() + { + int id = getCommandsIn() - 1; + log.debug("%s synced to %d", this, id); + boolean flush; + synchronized (processedLock) + { + syncPoint = id; + flush = ge(maxProcessed, syncPoint); + } + if (flush) + { + flushProcessed(); + } + } + + public void attach(Channel channel) + { + this.channel = channel; + channel.setSession(this); + } + + public Method getCommand(int id) + { + synchronized (commands) + { + return commands.get(id); + } + } + + boolean complete(int lower, int upper) + { + //avoid autoboxing + if(log.isDebugEnabled()) + { + log.debug("%s complete(%d, %d)", this, lower, upper); + } + synchronized (commands) + { + int old = maxComplete; + for (int id = max(maxComplete, lower); le(id, upper); id++) + { + commands.remove(id); + } + if (le(lower, maxComplete + 1)) + { + maxComplete = max(maxComplete, upper); + } + log.debug("%s commands remaining: %s", this, commands); + commands.notifyAll(); + return gt(maxComplete, old); + } + } + + public void invoke(Method m) + { + if (closed.get()) + { + List exc = getExceptions(); + if (!exc.isEmpty()) + { + throw new SessionException(exc); + } + else if (close != null) + { + throw new ConnectionException(close); + } + else + { + throw new SessionClosedException(); + } + } + + if (m.getEncodedTrack() == Frame.L4) + { + synchronized (commands) + { + int next = commandsOut++; + m.setId(next); + if (next == 0) + { + sessionCommandPoint(0, 0); + } + if (ENABLE_REPLAY) + { + commands.put(next, m); + } + if (autoSync) + { + m.setSync(true); + } + needSync = !m.isSync(); + channel.method(m); + if (autoSync) + { + sync(); + } + + // flush every 64K commands to avoid ambiguity on + // wraparound + if ((next % 65536) == 0) + { + sessionFlush(COMPLETED); + } + } + } + else + { + channel.method(m); + } + } + + public void sync() + { + sync(timeout); + } + + public void sync(long timeout) + { + log.debug("%s sync()", this); + synchronized (commands) + { + int point = commandsOut - 1; + + if (needSync && lt(maxComplete, point)) + { + executionSync(SYNC); + } + + long start = System.currentTimeMillis(); + long elapsed = 0; + while (!closed.get() && elapsed < timeout && lt(maxComplete, point)) + { + try { + log.debug("%s waiting for[%d]: %d, %s", this, point, + maxComplete, commands); + commands.wait(timeout - elapsed); + elapsed = System.currentTimeMillis() - start; + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + + if (lt(maxComplete, point)) + { + if (closed.get()) + { + throw new SessionException(getExceptions()); + } + else + { + throw new RuntimeException + (String.format + ("timed out waiting for sync: complete = %s, point = %s", maxComplete, point)); + } + } + } + } + + private Map> results = + new HashMap>(); + private List exceptions = + new ArrayList(); + + void result(int command, Struct result) + { + ResultFuture future; + synchronized (results) + { + future = results.remove(command); + } + future.set(result); + } + + void addException(ExecutionException exc) + { + synchronized (exceptions) + { + exceptions.add(exc); + } + } + + private ConnectionClose close = null; + + void closeCode(ConnectionClose close) + { + this.close = close; + } + + List getExceptions() + { + synchronized (exceptions) + { + return new ArrayList(exceptions); + } + } + + protected Future invoke(Method m, Class klass) + { + synchronized (commands) + { + int command = commandsOut; + ResultFuture future = new ResultFuture(klass); + synchronized (results) + { + results.put(command, future); + } + invoke(m); + return future; + } + } + + private class ResultFuture implements Future + { + + private final Class klass; + private T result; + + private ResultFuture(Class klass) + { + this.klass = klass; + } + + private void set(Struct result) + { + synchronized (this) + { + this.result = klass.cast(result); + notifyAll(); + } + } + + public T get(long timeout) + { + synchronized (this) + { + long start = System.currentTimeMillis(); + long elapsed = 0; + while (!closed.get() && timeout - elapsed > 0 && !isDone()) + { + try + { + log.debug("%s waiting for result: %s", Session.this, this); + wait(timeout - elapsed); + elapsed = System.currentTimeMillis() - start; + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + } + + if (isDone()) + { + return result; + } + else if (closed.get()) + { + throw new SessionException(getExceptions()); + } + else + { + return null; + } + } + + public T get() + { + return get(timeout); + } + + public boolean isDone() + { + return result != null; + } + + public String toString() + { + return String.format("Future(%s)", isDone() ? result : klass); + } + + } + + public final void messageTransfer(String destination, + MessageAcceptMode acceptMode, + MessageAcquireMode acquireMode, + Header header, + byte[] body, + Option ... _options) { + messageTransfer(destination, acceptMode, acquireMode, header, + ByteBuffer.wrap(body), _options); + } + + public final void messageTransfer(String destination, + MessageAcceptMode acceptMode, + MessageAcquireMode acquireMode, + Header header, + String body, + Option ... _options) { + messageTransfer(destination, acceptMode, acquireMode, header, + toUTF8(body), _options); + } + + public void close() + { + sessionRequestTimeout(0); + sessionDetach(name); + synchronized (commands) + { + long start = System.currentTimeMillis(); + long elapsed = 0; + try + { + while (!closed.get() && elapsed < timeout) + { + commands.wait(timeout - elapsed); + elapsed = System.currentTimeMillis() - start; + } + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + } + + public void exception(Throwable t) + { + log.error(t, "caught exception"); + } + + public void closed() + { + closed.set(true); + synchronized (commands) + { + commands.notifyAll(); + } + synchronized (results) + { + for (ResultFuture result : results.values()) + { + synchronized(result) + { + result.notifyAll(); + } + } + } + channel.setSession(null); + channel = null; + } + + public String toString() + { + return String.format("ssn:%s", str(name)); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/SessionClosedException.java b/java/common/src/main/java/org/apache/qpid/transport/SessionClosedException.java new file mode 100644 index 0000000000..d2c54cf339 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/SessionClosedException.java @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import java.util.Collections; + + +/** + * SessionClosedException + * + */ + +public class SessionClosedException extends SessionException +{ + + public SessionClosedException() + { + super(Collections.EMPTY_LIST); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java new file mode 100644 index 0000000000..b91763509c --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/SessionDelegate.java @@ -0,0 +1,125 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import org.apache.qpid.transport.network.Frame; + + +/** + * SessionDelegate + * + * @author Rafael H. Schloming + */ + +public abstract class SessionDelegate + extends MethodDelegate + implements ProtocolDelegate +{ + public void init(Session ssn, ProtocolHeader hdr) { } + + public void control(Session ssn, Method method) { + method.dispatch(ssn, this); + } + + public void command(Session ssn, Method method) { + ssn.identify(method); + method.dispatch(ssn, this); + if (!method.hasPayload()) + { + ssn.processed(method); + } + } + + public void error(Session ssn, ProtocolError error) { } + + @Override public void executionResult(Session ssn, ExecutionResult result) + { + ssn.result(result.getCommandId(), result.getValue()); + } + + @Override public void executionException(Session ssn, ExecutionException exc) + { + ssn.addException(exc); + } + + @Override public void sessionCompleted(Session ssn, SessionCompleted cmp) + { + RangeSet ranges = cmp.getCommands(); + RangeSet known = null; + if (cmp.getTimelyReply()) + { + known = new RangeSet(); + } + + if (ranges != null) + { + for (Range range : ranges) + { + boolean advanced = ssn.complete(range.getLower(), range.getUpper()); + if (advanced && known != null) + { + known.add(range); + } + } + } + + if (known != null) + { + ssn.sessionKnownCompleted(known); + } + } + + @Override public void sessionKnownCompleted(Session ssn, SessionKnownCompleted kcmp) + { + RangeSet kc = kcmp.getCommands(); + if (kc != null) + { + ssn.knownComplete(kc); + } + } + + @Override public void sessionFlush(Session ssn, SessionFlush flush) + { + if (flush.getCompleted()) + { + ssn.flushProcessed(); + } + if (flush.getConfirmed()) + { + ssn.flushProcessed(); + } + if (flush.getExpected()) + { + throw new Error("not implemented"); + } + } + + @Override public void sessionCommandPoint(Session ssn, SessionCommandPoint scp) + { + ssn.commandsIn = scp.getCommandId(); + } + + @Override public void executionSync(Session ssn, ExecutionSync sync) + { + ssn.syncPoint(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/SessionException.java b/java/common/src/main/java/org/apache/qpid/transport/SessionException.java new file mode 100644 index 0000000000..dc294b2206 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/SessionException.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.transport; + +import java.util.List; + +/** + * SessionException + * + */ + +public class SessionException extends RuntimeException +{ + + private List exceptions; + + public SessionException(List exceptions) + { + super(exceptions.isEmpty() ? "" : exceptions.toString()); + this.exceptions = exceptions; + } + + public List getExceptions() + { + return exceptions; + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Sink.java b/java/common/src/main/java/org/apache/qpid/transport/Sink.java new file mode 100644 index 0000000000..8653acedbe --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Sink.java @@ -0,0 +1,137 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import java.io.IOException; +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.network.ConnectionBinding; +import org.apache.qpid.transport.network.io.IoAcceptor; + +/** + * Sink + * + */ + +public class Sink extends SessionDelegate +{ + + private static final String FORMAT_HDR = "%-12s %-18s %-18s %-18s"; + private static final String FORMAT_ROW = "SSN#%-8X %-18s %-18s %-18s"; + + private long interval = 100000; + private long start = System.currentTimeMillis(); + private long count = 0; + private long bytes = 0; + private long interval_start = start; + private long bytes_start = bytes; + private long time = start; + private int id = System.identityHashCode(this); + + public Sink() + { + } + + private double msg_rate() + { + return 1000 * (double) count / (double) (time - start); + } + + private double byte_rate() + { + return (1000 * (double) bytes / (double) (time - start)) / (1024*1024); + } + + private double msg_interval_rate() + { + return 1000 * (double) interval / (double) (time - interval_start); + } + + private double byte_interval_rate() + { + return (1000 * (double) (bytes - bytes_start) / (double) (time - interval_start)) / (1024*1024); + } + + private String rates() + { + return String.format("%.2f/%.2f", msg_rate(), byte_rate()); + } + + private String interval_rates() + { + return String.format("%.2f/%.2f", msg_interval_rate(), byte_interval_rate()); + } + + private String counts() + { + return String.format("%d/%.2f", count, ((double) bytes)/(1024*1024)); + } + + public void messageTransfer(Session ssn, MessageTransfer xfr) + { + count++; + bytes += xfr.getBody().remaining(); + if ((count % interval) == 0) + { + time = System.currentTimeMillis(); + System.out.println + (String.format + (FORMAT_ROW, id, counts(), rates(), interval_rates())); + interval_start = time; + bytes_start = bytes; + } + ssn.processed(xfr); + } + + public static final void main(String[] args) throws IOException + { + ConnectionDelegate delegate = new ConnectionDelegate() + { + + public SessionDelegate getSessionDelegate() + { + return new Sink(); + } + + public void exception(Throwable t) + { + t.printStackTrace(); + } + + public void closed() {} + }; + + //hack + delegate.setUsername("guest"); + delegate.setPassword("guest"); + + IoAcceptor ioa = new IoAcceptor + ("0.0.0.0", 5672, new ConnectionBinding(delegate)); + System.out.println + (String.format + (FORMAT_HDR, "Session", "Count/MBytes", "Cumulative Rate", "Interval Rate")); + System.out.println + (String.format + (FORMAT_HDR, "-------", "------------", "---------------", "-------------")); + ioa.start(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/Struct.java b/java/common/src/main/java/org/apache/qpid/transport/Struct.java new file mode 100644 index 0000000000..22bd9f34ad --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/Struct.java @@ -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. + * + */ +package org.apache.qpid.transport; + +import java.util.List; +import java.util.Map; + +import org.apache.qpid.transport.codec.Decoder; +import org.apache.qpid.transport.codec.Encodable; +import org.apache.qpid.transport.codec.Encoder; + + +/** + * Struct + * + * @author Rafael H. Schloming + */ + +public abstract class Struct implements Encodable +{ + + public static Struct create(int type) + { + return StructFactory.create(type); + } + + boolean dirty = true; + + public boolean isDirty() + { + return dirty; + } + + public void setDirty(boolean dirty) + { + this.dirty = dirty; + } + + public abstract int getStructType(); + + public abstract int getSizeWidth(); + + public abstract int getPackWidth(); + + public final int getEncodedType() + { + int type = getStructType(); + if (type < 0) + { + throw new UnsupportedOperationException(); + } + return type; + } + + private final boolean isBit(Field f) + { + return f.getType().equals(Boolean.class); + } + + private final boolean packed() + { + return getPackWidth() > 0; + } + + private final boolean encoded(Field f) + { + return !packed() || !isBit(f) && f.has(this); + } + + private final int getFlagWidth() + { + return (getFields().size() + 7)/8; + } + + private final int getPaddWidth() + { + int pw = getPackWidth() - getFlagWidth(); + assert pw > 0; + return pw; + } + + private final int getFlagCount() + { + return 8*getPackWidth(); + } + + private final int getReservedFlagCount() + { + return getFlagCount() - getFields().size(); + } + + public abstract void read(Decoder dec); + + public abstract void write(Encoder enc); + + public abstract Map getFields(); + + public String toString() + { + StringBuilder str = new StringBuilder(); + str.append(getClass().getSimpleName()); + + str.append("("); + boolean first = true; + for (Map.Entry me : getFields().entrySet()) + { + if (first) + { + first = false; + } + else + { + str.append(", "); + } + str.append(me.getKey()); + str.append("="); + str.append(me.getValue()); + } + str.append(")"); + + return str.toString(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/TransportException.java b/java/common/src/main/java/org/apache/qpid/transport/TransportException.java new file mode 100644 index 0000000000..5ef15154fc --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/TransportException.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.transport; + + +/** + * TransportException + */ + +public class TransportException extends RuntimeException +{ + + public TransportException(String msg) + { + super(msg); + } + + public TransportException(String msg, Throwable cause) + { + super(msg, cause); + } + + public TransportException(Throwable cause) + { + super(cause); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java new file mode 100644 index 0000000000..a8a4997ae7 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractDecoder.java @@ -0,0 +1,470 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.codec; + +import java.io.UnsupportedEncodingException; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.transport.Binary; +import org.apache.qpid.transport.RangeSet; +import org.apache.qpid.transport.Struct; +import org.apache.qpid.transport.Type; + +import static org.apache.qpid.transport.util.Functions.*; + + +/** + * AbstractDecoder + * + * @author Rafael H. Schloming + */ + +abstract class AbstractDecoder implements Decoder +{ + + private final Map str8cache = new LinkedHashMap() + { + @Override protected boolean removeEldestEntry(Map.Entry me) + { + return size() > 4*1024; + } + }; + + protected abstract byte doGet(); + + protected abstract void doGet(byte[] bytes); + + protected byte get() + { + return doGet(); + } + + protected void get(byte[] bytes) + { + doGet(bytes); + } + + protected Binary get(int size) + { + byte[] bytes = new byte[size]; + get(bytes); + return new Binary(bytes); + } + + protected short uget() + { + return (short) (0xFF & get()); + } + + public short readUint8() + { + return uget(); + } + + public int readUint16() + { + int i = uget() << 8; + i |= uget(); + return i; + } + + public long readUint32() + { + long l = uget() << 24; + l |= uget() << 16; + l |= uget() << 8; + l |= uget(); + return l; + } + + public int readSequenceNo() + { + return (int) readUint32(); + } + + public long readUint64() + { + long l = 0; + for (int i = 0; i < 8; i++) + { + l |= ((long) (0xFF & get())) << (56 - i*8); + } + return l; + } + + public long readDatetime() + { + return readUint64(); + } + + private static final String decode(byte[] bytes, int offset, int length, String charset) + { + try + { + return new String(bytes, offset, length, charset); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + + private static final String decode(byte[] bytes, String charset) + { + return decode(bytes, 0, bytes.length, charset); + } + + public String readStr8() + { + short size = readUint8(); + Binary bin = get(size); + String str = str8cache.get(bin); + if (str == null) + { + str = decode(bin.array(), bin.offset(), bin.size(), "UTF-8"); + str8cache.put(bin, str); + } + return str; + } + + public String readStr16() + { + int size = readUint16(); + byte[] bytes = new byte[size]; + get(bytes); + return decode(bytes, "UTF-8"); + } + + public byte[] readVbin8() + { + int size = readUint8(); + byte[] bytes = new byte[size]; + get(bytes); + return bytes; + } + + public byte[] readVbin16() + { + int size = readUint16(); + byte[] bytes = new byte[size]; + get(bytes); + return bytes; + } + + public byte[] readVbin32() + { + int size = (int) readUint32(); + byte[] bytes = new byte[size]; + get(bytes); + return bytes; + } + + public RangeSet readSequenceSet() + { + int count = readUint16()/8; + if (count == 0) + { + return null; + } + else + { + RangeSet ranges = new RangeSet(); + for (int i = 0; i < count; i++) + { + ranges.add(readSequenceNo(), readSequenceNo()); + } + return ranges; + } + } + + public RangeSet readByteRanges() + { + throw new Error("not implemented"); + } + + public UUID readUuid() + { + long msb = readUint64(); + long lsb = readUint64(); + return new UUID(msb, lsb); + } + + public String readContent() + { + throw new Error("Deprecated"); + } + + public Struct readStruct(int type) + { + Struct st = Struct.create(type); + int width = st.getSizeWidth(); + if (width > 0) + { + long size = readSize(width); + if (size == 0) + { + return null; + } + } + if (type > 0) + { + int code = readUint16(); + assert code == type; + } + st.read(this); + return st; + } + + public Struct readStruct32() + { + long size = readUint32(); + if (size == 0) + { + return null; + } + else + { + int type = readUint16(); + Struct result = Struct.create(type); + result.read(this); + return result; + } + } + + public Map readMap() + { + long size = readUint32(); + + if (size == 0) + { + return null; + } + + long count = readUint32(); + + if (count == 0) + { + return Collections.EMPTY_MAP; + } + + Map result = new LinkedHashMap(); + for (int i = 0; i < count; i++) + { + String key = readStr8(); + byte code = get(); + Type t = getType(code); + Object value = read(t); + result.put(key, value); + } + + return result; + } + + public List readList() + { + long size = readUint32(); + + if (size == 0) + { + return null; + } + + long count = readUint32(); + + if (count == 0) + { + return Collections.EMPTY_LIST; + } + + List result = new ArrayList(); + for (int i = 0; i < count; i++) + { + byte code = get(); + Type t = getType(code); + Object value = read(t); + result.add(value); + } + return result; + } + + public List readArray() + { + long size = readUint32(); + + if (size == 0) + { + return null; + } + + byte code = get(); + Type t = getType(code); + long count = readUint32(); + + if (count == 0) + { + return Collections.EMPTY_LIST; + } + + List result = new ArrayList(); + for (int i = 0; i < count; i++) + { + Object value = read(t); + result.add(value); + } + return result; + } + + private Type getType(byte code) + { + Type type = Type.get(code); + if (type == null) + { + throw new IllegalArgumentException("unknown code: " + code); + } + else + { + return type; + } + } + + private long readSize(Type t) + { + if (t.fixed) + { + return t.width; + } + else + { + return readSize(t.width); + } + } + + private long readSize(int width) + { + switch (width) + { + case 1: + return readUint8(); + case 2: + return readUint16(); + case 4: + return readUint32(); + default: + throw new IllegalStateException("illegal width: " + width); + } + } + + private byte[] readBytes(Type t) + { + long size = readSize(t); + byte[] result = new byte[(int) size]; + get(result); + return result; + } + + private Object read(Type t) + { + switch (t) + { + case BIN8: + case UINT8: + return readUint8(); + case INT8: + return get(); + case CHAR: + return (char) get(); + case BOOLEAN: + return get() > 0; + + case BIN16: + case UINT16: + return readUint16(); + + case INT16: + return (short) readUint16(); + + case BIN32: + case UINT32: + return readUint32(); + + case CHAR_UTF32: + case INT32: + return (int) readUint32(); + + case FLOAT: + return Float.intBitsToFloat((int) readUint32()); + + case BIN64: + case UINT64: + case INT64: + case DATETIME: + return readUint64(); + + case DOUBLE: + return Double.longBitsToDouble(readUint64()); + + case UUID: + return readUuid(); + + case STR8: + return readStr8(); + + case STR16: + return readStr16(); + + case STR8_LATIN: + case STR8_UTF16: + case STR16_LATIN: + case STR16_UTF16: + // XXX: need to do character conversion + return new String(readBytes(t)); + + case MAP: + return readMap(); + case LIST: + return readList(); + case ARRAY: + return readArray(); + case STRUCT32: + return readStruct32(); + + case BIN40: + case DEC32: + case BIN72: + case DEC64: + // XXX: what types are we supposed to use here? + return readBytes(t); + + case VOID: + return null; + + default: + return readBytes(t); + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java new file mode 100644 index 0000000000..908d14a307 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/AbstractEncoder.java @@ -0,0 +1,620 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.codec; + +import java.io.UnsupportedEncodingException; + +import java.nio.ByteBuffer; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.transport.Range; +import org.apache.qpid.transport.RangeSet; +import org.apache.qpid.transport.Struct; +import org.apache.qpid.transport.Type; + +import static org.apache.qpid.transport.util.Functions.*; + + +/** + * AbstractEncoder + * + * @author Rafael H. Schloming + */ + +abstract class AbstractEncoder implements Encoder +{ + + private static Map,Type> ENCODINGS = new HashMap,Type>(); + static + { + ENCODINGS.put(Boolean.class, Type.BOOLEAN); + ENCODINGS.put(String.class, Type.STR16); + ENCODINGS.put(Long.class, Type.INT64); + ENCODINGS.put(Integer.class, Type.INT32); + ENCODINGS.put(Short.class, Type.INT16); + ENCODINGS.put(Byte.class, Type.INT8); + ENCODINGS.put(Map.class, Type.MAP); + ENCODINGS.put(List.class, Type.LIST); + ENCODINGS.put(Float.class, Type.FLOAT); + ENCODINGS.put(Double.class, Type.DOUBLE); + ENCODINGS.put(Character.class, Type.CHAR); + ENCODINGS.put(byte[].class, Type.VBIN32); + } + + private final Map str8cache = new LinkedHashMap() + { + @Override protected boolean removeEldestEntry(Map.Entry me) + { + return size() > 4*1024; + } + }; + + protected abstract void doPut(byte b); + + protected abstract void doPut(ByteBuffer src); + + protected void put(byte b) + { + doPut(b); + } + + protected void put(ByteBuffer src) + { + doPut(src); + } + + protected void put(byte[] bytes) + { + put(ByteBuffer.wrap(bytes)); + } + + protected abstract int beginSize8(); + protected abstract void endSize8(int pos); + + protected abstract int beginSize16(); + protected abstract void endSize16(int pos); + + protected abstract int beginSize32(); + protected abstract void endSize32(int pos); + + public void writeUint8(short b) + { + assert b < 0x100; + + put((byte) b); + } + + public void writeUint16(int s) + { + assert s < 0x10000; + + put(lsb(s >>> 8)); + put(lsb(s)); + } + + public void writeUint32(long i) + { + assert i < 0x100000000L; + + put(lsb(i >>> 24)); + put(lsb(i >>> 16)); + put(lsb(i >>> 8)); + put(lsb(i)); + } + + public void writeSequenceNo(int i) + { + writeUint32(i); + } + + public void writeUint64(long l) + { + for (int i = 0; i < 8; i++) + { + put(lsb(l >> (56 - i*8))); + } + } + + + public void writeDatetime(long l) + { + writeUint64(l); + } + + private static final byte[] encode(String s, String charset) + { + try + { + return s.getBytes(charset); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + + public void writeStr8(String s) + { + if (s == null) + { + s = ""; + } + + byte[] bytes = str8cache.get(s); + if (bytes == null) + { + bytes = encode(s, "UTF-8"); + str8cache.put(s, bytes); + } + writeUint8((short) bytes.length); + put(bytes); + } + + public void writeStr16(String s) + { + if (s == null) + { + s = ""; + } + + byte[] bytes = encode(s, "UTF-8"); + writeUint16(bytes.length); + put(bytes); + } + + public void writeVbin8(byte[] bytes) + { + if (bytes == null) { bytes = new byte[0]; } + if (bytes.length > 255) + { + throw new IllegalArgumentException("array too long: " + bytes.length); + } + writeUint8((short) bytes.length); + put(ByteBuffer.wrap(bytes)); + } + + public void writeVbin16(byte[] bytes) + { + if (bytes == null) { bytes = new byte[0]; } + writeUint16(bytes.length); + put(ByteBuffer.wrap(bytes)); + } + + public void writeVbin32(byte[] bytes) + { + if (bytes == null) { bytes = new byte[0]; } + writeUint32(bytes.length); + put(ByteBuffer.wrap(bytes)); + } + + public void writeSequenceSet(RangeSet ranges) + { + if (ranges == null) + { + writeUint16((short) 0); + } + else + { + writeUint16(ranges.size() * 8); + for (Range range : ranges) + { + writeSequenceNo(range.getLower()); + writeSequenceNo(range.getUpper()); + } + } + } + + public void writeByteRanges(RangeSet ranges) + { + throw new Error("not implemented"); + } + + public void writeUuid(UUID uuid) + { + long msb = 0; + long lsb = 0; + if (uuid != null) + { + msb = uuid.getMostSignificantBits(); + lsb = uuid.getLeastSignificantBits(); + } + writeUint64(msb); + writeUint64(lsb); + } + + public void writeStruct(int type, Struct s) + { + boolean empty = false; + if (s == null) + { + s = Struct.create(type); + empty = true; + } + + int width = s.getSizeWidth(); + int pos = -1; + if (width > 0) + { + pos = beginSize(width); + } + + if (type > 0) + { + writeUint16(type); + } + + s.write(this); + + if (width > 0) + { + endSize(width, pos); + } + } + + public void writeStruct32(Struct s) + { + if (s == null) + { + writeUint32(0); + } + else + { + int pos = beginSize32(); + writeUint16(s.getEncodedType()); + s.write(this); + endSize32(pos); + } + } + + private Type encoding(Object value) + { + if (value == null) + { + return Type.VOID; + } + + Class klass = value.getClass(); + Type type = resolve(klass); + + if (type == null) + { + throw new IllegalArgumentException + ("unable to resolve type: " + klass + ", " + value); + } + else + { + return type; + } + } + + static final Type resolve(Class klass) + { + Type type = ENCODINGS.get(klass); + if (type != null) + { + return type; + } + + Class sup = klass.getSuperclass(); + if (sup != null) + { + type = resolve(klass.getSuperclass()); + + if (type != null) + { + return type; + } + } + + for (Class iface : klass.getInterfaces()) + { + type = resolve(iface); + if (type != null) + { + return type; + } + } + + return null; + } + + public void writeMap(Map map) + { + int pos = beginSize32(); + if (map != null) + { + writeUint32(map.size()); + writeMapEntries(map); + } + endSize32(pos); + } + + protected void writeMapEntries(Map map) + { + for (Map.Entry entry : map.entrySet()) + { + String key = entry.getKey(); + Object value = entry.getValue(); + Type type = encoding(value); + writeStr8(key); + put(type.code); + write(type, value); + } + } + + public void writeList(List list) + { + int pos = beginSize32(); + if (list != null) + { + writeUint32(list.size()); + writeListEntries(list); + } + endSize32(pos); + } + + protected void writeListEntries(List list) + { + for (Object value : list) + { + Type type = encoding(value); + put(type.code); + write(type, value); + } + } + + public void writeArray(List array) + { + int pos = beginSize32(); + if (array != null) + { + writeArrayEntries(array); + } + endSize32(pos); + } + + protected void writeArrayEntries(List array) + { + Type type; + + if (array.isEmpty()) + { + return; + } + else + { + type = encoding(array.get(0)); + } + + put(type.code); + + writeUint32(array.size()); + + for (Object value : array) + { + write(type, value); + } + } + + private void writeSize(Type t, int size) + { + if (t.fixed) + { + if (size != t.width) + { + throw new IllegalArgumentException + ("size does not match fixed width " + t.width + ": " + + size); + } + } + else + { + writeSize(t.width, size); + } + } + + private void writeSize(int width, int size) + { + // XXX: should check lengths + switch (width) + { + case 1: + writeUint8((short) size); + break; + case 2: + writeUint16(size); + break; + case 4: + writeUint32(size); + break; + default: + throw new IllegalStateException("illegal width: " + width); + } + } + + private int beginSize(int width) + { + switch (width) + { + case 1: + return beginSize8(); + case 2: + return beginSize16(); + case 4: + return beginSize32(); + default: + throw new IllegalStateException("illegal width: " + width); + } + } + + private void endSize(int width, int pos) + { + switch (width) + { + case 1: + endSize8(pos); + break; + case 2: + endSize16(pos); + break; + case 4: + endSize32(pos); + break; + default: + throw new IllegalStateException("illegal width: " + width); + } + } + + private void writeBytes(Type t, byte[] bytes) + { + writeSize(t, bytes.length); + put(bytes); + } + + private T coerce(Class klass, Object value) + { + if (klass.isInstance(value)) + { + return klass.cast(value); + } + else + { + throw new IllegalArgumentException("" + value); + } + } + + private void write(Type t, Object value) + { + switch (t) + { + case BIN8: + case UINT8: + writeUint8(coerce(Short.class, value)); + break; + case INT8: + put(coerce(Byte.class, value)); + break; + case CHAR: + put((byte) ((char)coerce(Character.class, value))); + break; + case BOOLEAN: + if (coerce(Boolean.class, value)) + { + put((byte) 1); + } + else + { + put((byte) 0); + } + break; + + case BIN16: + case UINT16: + writeUint16(coerce(Integer.class, value)); + break; + + case INT16: + writeUint16(coerce(Short.class, value)); + break; + + case BIN32: + case UINT32: + writeUint32(coerce(Long.class, value)); + break; + + case CHAR_UTF32: + case INT32: + writeUint32(coerce(Integer.class, value)); + break; + + case FLOAT: + writeUint32(Float.floatToIntBits(coerce(Float.class, value))); + break; + + case BIN64: + case UINT64: + case INT64: + case DATETIME: + writeUint64(coerce(Long.class, value)); + break; + + case DOUBLE: + long bits = Double.doubleToLongBits(coerce(Double.class, value)); + writeUint64(bits); + break; + + case UUID: + writeUuid(coerce(UUID.class, value)); + break; + + case STR8: + writeStr8(coerce(String.class, value)); + break; + + case STR16: + writeStr16(coerce(String.class, value)); + break; + + case STR8_LATIN: + case STR8_UTF16: + case STR16_LATIN: + case STR16_UTF16: + // XXX: need to do character conversion + writeBytes(t, coerce(String.class, value).getBytes()); + break; + + case MAP: + writeMap((Map) coerce(Map.class, value)); + break; + case LIST: + writeList(coerce(List.class, value)); + break; + case ARRAY: + writeArray(coerce(List.class, value)); + break; + case STRUCT32: + writeStruct32(coerce(Struct.class, value)); + break; + + case BIN40: + case DEC32: + case BIN72: + case DEC64: + // XXX: what types are we supposed to use here? + writeBytes(t, coerce(byte[].class, value)); + break; + + case VOID: + break; + + default: + writeBytes(t, coerce(byte[].class, value)); + break; + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/BBDecoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/BBDecoder.java new file mode 100644 index 0000000000..dd634eb94a --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/BBDecoder.java @@ -0,0 +1,96 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.codec; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import org.apache.qpid.transport.Binary; + + +/** + * BBDecoder + * + * @author Rafael H. Schloming + */ + +public final class BBDecoder extends AbstractDecoder +{ + + private ByteBuffer in; + + public void init(ByteBuffer in) + { + this.in = in; + this.in.order(ByteOrder.BIG_ENDIAN); + } + + protected byte doGet() + { + return in.get(); + } + + protected void doGet(byte[] bytes) + { + in.get(bytes); + } + + protected Binary get(int size) + { + if (in.hasArray()) + { + byte[] bytes = in.array(); + Binary bin = new Binary(bytes, in.arrayOffset() + in.position(), size); + in.position(in.position() + size); + return bin; + } + else + { + return super.get(size); + } + } + + public boolean hasRemaining() + { + return in.hasRemaining(); + } + + public short readUint8() + { + return (short) (0xFF & in.get()); + } + + public int readUint16() + { + return 0xFFFF & in.getShort(); + } + + public long readUint32() + { + return 0xFFFFFFFFL & in.getInt(); + } + + public long readUint64() + { + return in.getLong(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.java new file mode 100644 index 0000000000..390de881ab --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/BBEncoder.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.transport.codec; + +import java.nio.BufferOverflowException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + + +/** + * BBEncoder + * + * @author Rafael H. Schloming + */ + +public final class BBEncoder extends AbstractEncoder +{ + + private ByteBuffer out; + private int segment; + + public BBEncoder(int capacity) { + out = ByteBuffer.allocate(capacity); + out.order(ByteOrder.BIG_ENDIAN); + segment = 0; + } + + public void init() + { + out.clear(); + segment = 0; + } + + public ByteBuffer segment() + { + int pos = out.position(); + out.position(segment); + ByteBuffer slice = out.slice(); + slice.limit(pos - segment); + out.position(pos); + segment = pos; + return slice; + } + + private void grow(int size) + { + ByteBuffer old = out; + int capacity = old.capacity(); + out = ByteBuffer.allocate(Math.max(capacity + size, 2*capacity)); + out.order(ByteOrder.BIG_ENDIAN); + out.put(old); + } + + protected void doPut(byte b) + { + try + { + out.put(b); + } + catch (BufferOverflowException e) + { + grow(1); + out.put(b); + } + } + + protected void doPut(ByteBuffer src) + { + try + { + out.put(src); + } + catch (BufferOverflowException e) + { + grow(src.remaining()); + out.put(src); + } + } + + protected void put(byte[] bytes) + { + try + { + out.put(bytes); + } + catch (BufferOverflowException e) + { + grow(bytes.length); + out.put(bytes); + } + } + + public void writeUint8(short b) + { + assert b < 0x100; + + try + { + out.put((byte) b); + } + catch (BufferOverflowException e) + { + grow(1); + out.put((byte) b); + } + } + + public void writeUint16(int s) + { + assert s < 0x10000; + + try + { + out.putShort((short) s); + } + catch (BufferOverflowException e) + { + grow(2); + out.putShort((short) s); + } + } + + public void writeUint32(long i) + { + assert i < 0x100000000L; + + try + { + out.putInt((int) i); + } + catch (BufferOverflowException e) + { + grow(4); + out.putInt((int) i); + } + } + + public void writeUint64(long l) + { + try + { + out.putLong(l); + } + catch (BufferOverflowException e) + { + grow(8); + out.putLong(l); + } + } + + public int beginSize8() + { + int pos = out.position(); + try + { + out.put((byte) 0); + } + catch (BufferOverflowException e) + { + grow(1); + out.put((byte) 0); + } + return pos; + } + + public void endSize8(int pos) + { + int cur = out.position(); + out.put(pos, (byte) (cur - pos - 1)); + } + + public int beginSize16() + { + int pos = out.position(); + try + { + out.putShort((short) 0); + } + catch (BufferOverflowException e) + { + grow(2); + out.putShort((short) 0); + } + return pos; + } + + public void endSize16(int pos) + { + int cur = out.position(); + out.putShort(pos, (short) (cur - pos - 2)); + } + + public int beginSize32() + { + int pos = out.position(); + try + { + out.putInt(0); + } + catch (BufferOverflowException e) + { + grow(4); + out.putInt(0); + } + return pos; + } + + public void endSize32(int pos) + { + int cur = out.position(); + out.putInt(pos, (cur - pos - 4)); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/Decoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/Decoder.java new file mode 100644 index 0000000000..50e787ccb2 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/Decoder.java @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.codec; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.transport.RangeSet; +import org.apache.qpid.transport.Struct; + + +/** + * Decoder + * + * @author Rafael H. Schloming + */ + +public interface Decoder +{ + + boolean hasRemaining(); + + short readUint8(); + int readUint16(); + long readUint32(); + long readUint64(); + + long readDatetime(); + UUID readUuid(); + + int readSequenceNo(); + RangeSet readSequenceSet(); // XXX + RangeSet readByteRanges(); // XXX + + String readStr8(); + String readStr16(); + + byte[] readVbin8(); + byte[] readVbin16(); + byte[] readVbin32(); + + Struct readStruct32(); + Map readMap(); + List readList(); + List readArray(); + + Struct readStruct(int type); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/Encodable.java b/java/common/src/main/java/org/apache/qpid/transport/codec/Encodable.java new file mode 100644 index 0000000000..2aefafd19c --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/Encodable.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.transport.codec; + + +/** + * Encodable + * + * @author Rafael H. Schloming + */ + +public interface Encodable +{ + + void write(Encoder enc); + + void read(Decoder dec); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java b/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java new file mode 100644 index 0000000000..2d8d13e80a --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/codec/Encoder.java @@ -0,0 +1,66 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.codec; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.transport.RangeSet; +import org.apache.qpid.transport.Struct; + + +/** + * Encoder + * + * @author Rafael H. Schloming + */ + +public interface Encoder +{ + + void writeUint8(short b); + void writeUint16(int s); + void writeUint32(long i); + void writeUint64(long l); + + void writeDatetime(long l); + void writeUuid(UUID uuid); + + void writeSequenceNo(int s); + void writeSequenceSet(RangeSet ranges); // XXX + void writeByteRanges(RangeSet ranges); // XXX + + void writeStr8(String s); + void writeStr16(String s); + + void writeVbin8(byte[] bytes); + void writeVbin16(byte[] bytes); + void writeVbin32(byte[] bytes); + + void writeStruct32(Struct s); + void writeMap(Map map); + void writeList(List list); + void writeArray(List array); + + void writeStruct(int type, Struct s); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java new file mode 100644 index 0000000000..33d552b91e --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/Assembler.java @@ -0,0 +1,226 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.network; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.transport.codec.Decoder; + +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.Method; +import org.apache.qpid.transport.ProtocolError; +import org.apache.qpid.transport.ProtocolEvent; +import org.apache.qpid.transport.ProtocolHeader; +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.SegmentType; +import org.apache.qpid.transport.Struct; + + +/** + * Assembler + * + */ + +public class Assembler implements Receiver, NetworkDelegate +{ + + private final Receiver receiver; + private final Map> segments; + private final Method[] incomplete; + private final ThreadLocal decoder = new ThreadLocal() + { + public BBDecoder initialValue() + { + return new BBDecoder(); + } + }; + + public Assembler(Receiver receiver) + { + this.receiver = receiver; + segments = new HashMap>(); + incomplete = new Method[64*1024]; + } + + private int segmentKey(Frame frame) + { + return (frame.getTrack() + 1) * frame.getChannel(); + } + + private List getSegment(Frame frame) + { + return segments.get(segmentKey(frame)); + } + + private void setSegment(Frame frame, List segment) + { + int key = segmentKey(frame); + if (segments.containsKey(key)) + { + error(new ProtocolError(Frame.L2, "segment in progress: %s", + frame)); + } + segments.put(segmentKey(frame), segment); + } + + private void clearSegment(Frame frame) + { + segments.remove(segmentKey(frame)); + } + + private void emit(int channel, ProtocolEvent event) + { + event.setChannel(channel); + receiver.received(event); + } + + public void received(NetworkEvent event) + { + event.delegate(this); + } + + public void exception(Throwable t) + { + this.receiver.exception(t); + } + + public void closed() + { + this.receiver.closed(); + } + + public void init(ProtocolHeader header) + { + emit(0, header); + } + + public void error(ProtocolError error) + { + emit(0, error); + } + + public void frame(Frame frame) + { + ByteBuffer segment; + if (frame.isFirstFrame() && frame.isLastFrame()) + { + segment = frame.getBody(); + assemble(frame, segment); + } + else + { + List frames; + if (frame.isFirstFrame()) + { + frames = new ArrayList(); + setSegment(frame, frames); + } + else + { + frames = getSegment(frame); + } + + frames.add(frame); + + if (frame.isLastFrame()) + { + clearSegment(frame); + + int size = 0; + for (Frame f : frames) + { + size += f.getSize(); + } + segment = ByteBuffer.allocate(size); + for (Frame f : frames) + { + segment.put(f.getBody()); + } + segment.flip(); + assemble(frame, segment); + } + } + + } + + private void assemble(Frame frame, ByteBuffer segment) + { + BBDecoder dec = decoder.get(); + dec.init(segment); + + int channel = frame.getChannel(); + Method command; + + switch (frame.getType()) + { + case CONTROL: + int controlType = dec.readUint16(); + Method control = Method.create(controlType); + control.read(dec); + emit(channel, control); + break; + case COMMAND: + int commandType = dec.readUint16(); + // read in the session header, right now we don't use it + dec.readUint16(); + command = Method.create(commandType); + command.read(dec); + if (command.hasPayload()) + { + incomplete[channel] = command; + } + else + { + emit(channel, command); + } + break; + case HEADER: + command = incomplete[channel]; + List structs = new ArrayList(2); + while (dec.hasRemaining()) + { + structs.add(dec.readStruct32()); + } + command.setHeader(new Header(structs)); + if (frame.isLastSegment()) + { + incomplete[channel] = null; + emit(channel, command); + } + break; + case BODY: + command = incomplete[channel]; + command.setBody(segment); + incomplete[channel] = null; + emit(channel, command); + break; + default: + throw new IllegalStateException("unknown frame type: " + frame.getType()); + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java b/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.java new file mode 100644 index 0000000000..6886cb3a5a --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/ConnectionBinding.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.transport.network; + +import java.nio.ByteBuffer; + +import org.apache.qpid.transport.Binding; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.ConnectionDelegate; +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.Sender; + +/** + * ConnectionBinding + * + */ + +public class ConnectionBinding implements Binding +{ + + private static final int MAX_FRAME_SIZE = 64 * 1024 - 1; + + private final ConnectionDelegate delegate; + + public ConnectionBinding(ConnectionDelegate delegate) + { + this.delegate = delegate; + } + + public Connection endpoint(Sender sender) + { + // XXX: hardcoded max-frame + return new Connection + (new Disassembler(sender, MAX_FRAME_SIZE), delegate); + } + + public Receiver receiver(Connection conn) + { + return new InputHandler(new Assembler(conn)); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java b/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java new file mode 100644 index 0000000000..bb7d2506e3 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/Disassembler.java @@ -0,0 +1,236 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.network; + +import org.apache.qpid.transport.codec.BBEncoder; + +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.Method; +import org.apache.qpid.transport.ProtocolDelegate; +import org.apache.qpid.transport.ProtocolError; +import org.apache.qpid.transport.ProtocolEvent; +import org.apache.qpid.transport.ProtocolHeader; +import org.apache.qpid.transport.SegmentType; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.Struct; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import static org.apache.qpid.transport.network.Frame.*; + +import static java.lang.Math.*; + + +/** + * Disassembler + * + */ + +public final class Disassembler implements Sender, + ProtocolDelegate +{ + + private final Sender sender; + private final int maxPayload; + private final ByteBuffer header; + private final Object sendlock = new Object(); + private final ThreadLocal encoder = new ThreadLocal() + { + public BBEncoder initialValue() + { + return new BBEncoder(4*1024); + } + }; + + public Disassembler(Sender sender, int maxFrame) + { + if (maxFrame <= HEADER_SIZE || maxFrame >= 64*1024) + { + throw new IllegalArgumentException + ("maxFrame must be > HEADER_SIZE and < 64K: " + maxFrame); + } + this.sender = sender; + this.maxPayload = maxFrame - HEADER_SIZE; + this.header = ByteBuffer.allocate(HEADER_SIZE); + this.header.order(ByteOrder.BIG_ENDIAN); + + } + + public void send(ProtocolEvent event) + { + event.delegate(null, this); + } + + public void flush() + { + synchronized (sendlock) + { + sender.flush(); + } + } + + public void close() + { + synchronized (sendlock) + { + sender.close(); + } + } + + private final void frame(byte flags, byte type, byte track, int channel, int size, ByteBuffer buf) + { + synchronized (sendlock) + { + header.put(0, flags); + header.put(1, type); + header.putShort(2, (short) (size + HEADER_SIZE)); + header.put(5, track); + header.putShort(6, (short) channel); + + header.rewind(); + + sender.send(header); + + int limit = buf.limit(); + buf.limit(buf.position() + size); + sender.send(buf); + buf.limit(limit); + } + } + + private void fragment(byte flags, SegmentType type, ProtocolEvent event, + ByteBuffer buf) + { + byte typeb = (byte) type.getValue(); + byte track = event.getEncodedTrack() == Frame.L4 ? (byte) 1 : (byte) 0; + + int remaining = buf.remaining(); + boolean first = true; + while (true) + { + int size = min(maxPayload, remaining); + remaining -= size; + + byte newflags = flags; + if (first) + { + newflags |= FIRST_FRAME; + first = false; + } + if (remaining == 0) + { + newflags |= LAST_FRAME; + } + + frame(newflags, typeb, track, event.getChannel(), size, buf); + + if (remaining == 0) + { + break; + } + } + } + + public void init(Void v, ProtocolHeader header) + { + synchronized (sendlock) + { + sender.send(header.toByteBuffer()); + sender.flush(); + } + } + + public void control(Void v, Method method) + { + method(method, SegmentType.CONTROL); + } + + public void command(Void v, Method method) + { + method(method, SegmentType.COMMAND); + } + + private ByteBuffer copy(ByteBuffer src) + { + ByteBuffer buf = ByteBuffer.allocate(src.remaining()); + buf.put(src); + buf.flip(); + return buf; + } + + private void method(Method method, SegmentType type) + { + BBEncoder enc = encoder.get(); + enc.init(); + enc.writeUint16(method.getEncodedType()); + if (type == SegmentType.COMMAND) + { + if (method.isSync()) + { + enc.writeUint16(0x0101); + } + else + { + enc.writeUint16(0x0100); + } + } + method.write(enc); + ByteBuffer methodSeg = enc.segment(); + + byte flags = FIRST_SEG; + + boolean payload = method.hasPayload(); + if (!payload) + { + flags |= LAST_SEG; + } + + ByteBuffer headerSeg = null; + if (payload) + { + final Header hdr = method.getHeader(); + final Struct[] structs = hdr.getStructs(); + + for (Struct st : structs) + { + enc.writeStruct32(st); + } + headerSeg = enc.segment(); + } + + synchronized (sendlock) + { + fragment(flags, type, method, methodSeg); + if (payload) + { + fragment((byte) 0x0, SegmentType.HEADER, method, headerSeg); + fragment(LAST_SEG, SegmentType.BODY, method, method.getBody()); + } + } + } + + public void error(Void v, ProtocolError error) + { + throw new IllegalArgumentException("" + error); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/Frame.java b/java/common/src/main/java/org/apache/qpid/transport/network/Frame.java new file mode 100644 index 0000000000..849355276e --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/Frame.java @@ -0,0 +1,151 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.network; + +import org.apache.qpid.transport.SegmentType; +import org.apache.qpid.transport.util.SliceIterator; + +import java.nio.ByteBuffer; + +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; + +import static org.apache.qpid.transport.util.Functions.*; + + +/** + * Frame + * + * @author Rafael H. Schloming + */ + +public final class Frame implements NetworkEvent +{ + public static final int HEADER_SIZE = 12; + + // XXX: enums? + public static final byte L1 = 0; + public static final byte L2 = 1; + public static final byte L3 = 2; + public static final byte L4 = 3; + + public static final byte RESERVED = 0x0; + + public static final byte VERSION = 0x0; + + public static final byte FIRST_SEG = 0x8; + public static final byte LAST_SEG = 0x4; + public static final byte FIRST_FRAME = 0x2; + public static final byte LAST_FRAME = 0x1; + + final private byte flags; + final private SegmentType type; + final private byte track; + final private int channel; + final private ByteBuffer body; + + public Frame(byte flags, SegmentType type, byte track, int channel, + ByteBuffer body) + { + this.flags = flags; + this.type = type; + this.track = track; + this.channel = channel; + this.body = body; + } + + public ByteBuffer getBody() + { + return body.slice(); + } + + public byte getFlags() + { + return flags; + } + + public int getChannel() + { + return channel; + } + + public int getSize() + { + return body.remaining(); + } + + public SegmentType getType() + { + return type; + } + + public byte getTrack() + { + return track; + } + + private boolean flag(byte mask) + { + return (flags & mask) != 0; + } + + public boolean isFirstSegment() + { + return flag(FIRST_SEG); + } + + public boolean isLastSegment() + { + return flag(LAST_SEG); + } + + public boolean isFirstFrame() + { + return flag(FIRST_FRAME); + } + + public boolean isLastFrame() + { + return flag(LAST_FRAME); + } + + public void delegate(NetworkDelegate delegate) + { + delegate.frame(this); + } + + public String toString() + { + StringBuilder str = new StringBuilder(); + + str.append(String.format + ("[%05d %05d %1d %s %d%d%d%d] ", getChannel(), getSize(), + getTrack(), getType(), + isFirstSegment() ? 1 : 0, isLastSegment() ? 1 : 0, + isFirstFrame() ? 1 : 0, isLastFrame() ? 1 : 0)); + + str.append(str(body)); + + return str.toString(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.java new file mode 100644 index 0000000000..408c95e075 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/InputHandler.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.transport.network; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import org.apache.qpid.transport.ProtocolError; +import org.apache.qpid.transport.ProtocolHeader; +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.SegmentType; + +import static org.apache.qpid.transport.util.Functions.*; + +import static org.apache.qpid.transport.network.InputHandler.State.*; + + +/** + * InputHandler + * + * @author Rafael H. Schloming + */ + +public final class InputHandler implements Receiver +{ + + public enum State + { + PROTO_HDR, + FRAME_HDR, + FRAME_BODY, + ERROR; + } + + private final Receiver receiver; + private State state; + private ByteBuffer input = null; + private int needed; + + private byte flags; + private SegmentType type; + private byte track; + private int channel; + + public InputHandler(Receiver receiver, State state) + { + this.receiver = receiver; + this.state = state; + + switch (state) + { + case PROTO_HDR: + needed = 8; + break; + case FRAME_HDR: + needed = Frame.HEADER_SIZE; + break; + } + } + + public InputHandler(Receiver receiver) + { + this(receiver, PROTO_HDR); + } + + private void error(String fmt, Object ... args) + { + receiver.received(new ProtocolError(Frame.L1, fmt, args)); + } + + public void received(ByteBuffer buf) + { + int limit = buf.limit(); + int remaining = buf.remaining(); + while (remaining > 0) + { + if (remaining >= needed) + { + int consumed = needed; + int pos = buf.position(); + if (input == null) + { + buf.limit(pos + needed); + input = buf; + state = next(pos); + buf.limit(limit); + buf.position(pos + consumed); + } + else + { + buf.limit(pos + needed); + input.put(buf); + buf.limit(limit); + input.flip(); + state = next(0); + } + + remaining -= consumed; + input = null; + } + else + { + if (input == null) + { + input = ByteBuffer.allocate(needed); + } + input.put(buf); + needed -= remaining; + remaining = 0; + } + } + } + + private State next(int pos) + { + input.order(ByteOrder.BIG_ENDIAN); + + switch (state) { + case PROTO_HDR: + if (input.get(pos) != 'A' && + input.get(pos + 1) != 'M' && + input.get(pos + 2) != 'Q' && + input.get(pos + 3) != 'P') + { + error("bad protocol header: %s", str(input)); + return ERROR; + } + + byte instance = input.get(pos + 5); + byte major = input.get(pos + 6); + byte minor = input.get(pos + 7); + receiver.received(new ProtocolHeader(instance, major, minor)); + needed = Frame.HEADER_SIZE; + return FRAME_HDR; + case FRAME_HDR: + flags = input.get(pos); + type = SegmentType.get(input.get(pos + 1)); + int size = (0xFFFF & input.getShort(pos + 2)); + size -= Frame.HEADER_SIZE; + if (size < 0 || size > (64*1024 - 12)) + { + error("bad frame size: %d", size); + return ERROR; + } + byte b = input.get(pos + 5); + if ((b & 0xF0) != 0) { + error("non-zero reserved bits in upper nibble of " + + "frame header byte 5: '%x'", b); + return ERROR; + } else { + track = (byte) (b & 0xF); + } + channel = (0xFFFF & input.getShort(pos + 6)); + if (size == 0) + { + Frame frame = new Frame(flags, type, track, channel, ByteBuffer.allocate(0)); + receiver.received(frame); + needed = Frame.HEADER_SIZE; + return FRAME_HDR; + } + else + { + needed = size; + return FRAME_BODY; + } + case FRAME_BODY: + Frame frame = new Frame(flags, type, track, channel, input.slice()); + receiver.received(frame); + needed = Frame.HEADER_SIZE; + return FRAME_HDR; + default: + throw new IllegalStateException(); + } + } + + public void exception(Throwable t) + { + receiver.exception(t); + } + + public void closed() + { + receiver.closed(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkDelegate.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkDelegate.java new file mode 100644 index 0000000000..fbdfe6e84c --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkDelegate.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.transport.network; + +import org.apache.qpid.transport.ProtocolError; +import org.apache.qpid.transport.ProtocolHeader; + + +/** + * NetworkDelegate + * + * @author Rafael H. Schloming + */ + +public interface NetworkDelegate +{ + + void init(ProtocolHeader header); + + void frame(Frame frame); + + void error(ProtocolError error); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/NetworkEvent.java b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkEvent.java new file mode 100644 index 0000000000..91314cd4ad --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/NetworkEvent.java @@ -0,0 +1,34 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.network; + + +/** + * NetworkEvent + * + */ + +public interface NetworkEvent +{ + + void delegate(NetworkDelegate delegate); + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java new file mode 100644 index 0000000000..b63020913b --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/InputHandler_0_9.java @@ -0,0 +1,109 @@ +package org.apache.qpid.transport.network.io; + +import java.nio.ByteBuffer; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQFrameDecodingException; +import org.apache.qpid.framing.AMQMethodBody; +import org.apache.qpid.framing.AMQMethodBodyFactory; +import org.apache.qpid.framing.BodyFactory; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.ContentBodyFactory; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.ContentHeaderBodyFactory; +import org.apache.qpid.framing.HeartbeatBody; +import org.apache.qpid.framing.HeartbeatBodyFactory; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; +import org.apache.qpid.transport.Receiver; + +public class InputHandler_0_9 implements Receiver +{ + + private AMQVersionAwareProtocolSession _session; + private MethodRegistry _registry; + private BodyFactory bodyFactory; + private static final BodyFactory[] _bodiesSupported = new BodyFactory[Byte.MAX_VALUE]; + + static + { + _bodiesSupported[ContentHeaderBody.TYPE] = ContentHeaderBodyFactory.getInstance(); + _bodiesSupported[ContentBody.TYPE] = ContentBodyFactory.getInstance(); + _bodiesSupported[HeartbeatBody.TYPE] = new HeartbeatBodyFactory(); + } + + public InputHandler_0_9(AMQVersionAwareProtocolSession session) + { + _session = session; + _registry = _session.getMethodRegistry(); + } + + public void closed() + { + // AS FIXME: implement + } + + public void exception(Throwable t) + { + // TODO: propogate exception to things + t.printStackTrace(); + } + + public void received(ByteBuffer buf) + { + org.apache.mina.common.ByteBuffer in = org.apache.mina.common.ByteBuffer.wrap(buf); + try + { + final byte type = in.get(); + if (type == AMQMethodBody.TYPE) + { + bodyFactory = new AMQMethodBodyFactory(_session); + } + else + { + bodyFactory = _bodiesSupported[type]; + } + + if (bodyFactory == null) + { + throw new AMQFrameDecodingException(null, "Unsupported frame type: " + type, null); + } + + final int channel = in.getUnsignedShort(); + final long bodySize = in.getUnsignedInt(); + + // bodySize can be zero + if ((channel < 0) || (bodySize < 0)) + { + throw new AMQFrameDecodingException(null, "Undecodable frame: type = " + type + " channel = " + channel + + " bodySize = " + bodySize, null); + } + + AMQFrame frame = new AMQFrame(in, channel, bodySize, bodyFactory); + + byte marker = in.get(); + if ((marker & 0xFF) != 0xCE) + { + throw new AMQFrameDecodingException(null, "End of frame marker not found. Read " + marker + " length=" + bodySize + + " type=" + type, null); + } + + try + { + frame.getBodyFrame().handle(frame.getChannel(), _session); + } + catch (AMQException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + catch (AMQFrameDecodingException e) + { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.java new file mode 100644 index 0000000000..c4559ae6b4 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoAcceptor.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.transport.network.io; + +import org.apache.qpid.transport.Binding; +import org.apache.qpid.transport.TransportException; + +import java.io.IOException; + +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketAddress; + +import java.nio.ByteBuffer; + + +/** + * IoAcceptor + * + */ + +public class IoAcceptor extends Thread +{ + + + private ServerSocket socket; + private Binding binding; + + public IoAcceptor(SocketAddress address, Binding binding) + throws IOException + { + socket = new ServerSocket(); + socket.setReuseAddress(true); + socket.bind(address); + this.binding = binding; + + setName(String.format("IoAcceptor - %s", socket.getInetAddress())); + } + + public IoAcceptor(String host, int port, Binding binding) + throws IOException + { + this(new InetSocketAddress(host, port), binding); + } + + public void run() + { + while (true) + { + try + { + Socket sock = socket.accept(); + IoTransport transport = new IoTransport(sock, binding); + } + catch (IOException e) + { + throw new TransportException(e); + } + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java new file mode 100644 index 0000000000..d6d1df573c --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoReceiver.java @@ -0,0 +1,129 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.network.io; + +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.TransportException; +import org.apache.qpid.transport.util.Logger; + +import java.io.InputStream; +import java.io.IOException; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * IoReceiver + * + */ + +final class IoReceiver extends Thread +{ + + private static final Logger log = Logger.get(IoReceiver.class); + + private final IoTransport transport; + private final Receiver receiver; + private final int bufferSize; + private final Socket socket; + private final long timeout; + private final AtomicBoolean closed = new AtomicBoolean(false); + + public IoReceiver(IoTransport transport, Receiver receiver, + int bufferSize, long timeout) + { + this.transport = transport; + this.receiver = receiver; + this.bufferSize = bufferSize; + this.socket = transport.getSocket(); + this.timeout = timeout; + + setDaemon(true); + setName(String.format("IoReceiver - %s", socket.getRemoteSocketAddress())); + start(); + } + + void close() + { + if (!closed.getAndSet(true)) + { + try + { + socket.shutdownInput(); + if (Thread.currentThread() != this) + { + join(timeout); + if (isAlive()) + { + throw new TransportException("join timed out"); + } + } + } + catch (InterruptedException e) + { + throw new TransportException(e); + } + catch (IOException e) + { + throw new TransportException(e); + } + } + } + + public void run() + { + final int threshold = bufferSize / 2; + + // I set the read buffer size simillar to SO_RCVBUF + // Haven't tested with a lower value to see if it's better or worse + byte[] buffer = new byte[bufferSize]; + try + { + InputStream in = socket.getInputStream(); + int read = 0; + int offset = 0; + while ((read = in.read(buffer, offset, bufferSize-offset)) != -1) + { + if (read > 0) + { + ByteBuffer b = ByteBuffer.wrap(buffer,offset,read); + receiver.received(b); + offset+=read; + if (offset > threshold) + { + offset = 0; + buffer = new byte[bufferSize]; + } + } + } + } + catch (Throwable t) + { + receiver.exception(t); + } + finally + { + receiver.closed(); + transport.getSender().close(); + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java new file mode 100644 index 0000000000..ef892744ab --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoSender.java @@ -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. + */ +package org.apache.qpid.transport.network.io; + +import java.io.IOException; +import java.io.OutputStream; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.TransportException; +import org.apache.qpid.transport.util.Logger; + +import static org.apache.qpid.transport.util.Functions.*; + + +public final class IoSender extends Thread implements Sender +{ + + private static final Logger log = Logger.get(IoSender.class); + + // by starting here, we ensure that we always test the wraparound + // case, we should probably make this configurable somehow so that + // we can test other cases as well + private final static int START = Integer.MAX_VALUE - 10; + + private final IoTransport transport; + private final long timeout; + private final Socket socket; + private final OutputStream out; + + private final byte[] buffer; + private volatile int head = START; + private volatile int tail = START; + private volatile boolean idle = true; + private final Object notFull = new Object(); + private final Object notEmpty = new Object(); + private final AtomicBoolean closed = new AtomicBoolean(false); + + private volatile Throwable exception = null; + + + public IoSender(IoTransport transport, int bufferSize, long timeout) + { + this.transport = transport; + this.socket = transport.getSocket(); + this.buffer = new byte[pof2(bufferSize)]; // buffer size must be a power of 2 + this.timeout = timeout; + + try + { + out = socket.getOutputStream(); + } + catch (IOException e) + { + throw new TransportException("Error getting output stream for socket", e); + } + + setDaemon(true); + setName(String.format("IoSender - %s", socket.getRemoteSocketAddress())); + start(); + } + + private static final int pof2(int n) + { + int result = 1; + while (result < n) + { + result *= 2; + } + return result; + } + + private static final int mod(int n, int m) + { + int r = n % m; + return r < 0 ? m + r : r; + } + + public void send(ByteBuffer buf) + { + if (closed.get()) + { + throw new TransportException("sender is closed", exception); + } + + final int size = buffer.length; + int remaining = buf.remaining(); + + while (remaining > 0) + { + final int hd = head; + final int tl = tail; + + if (hd - tl >= size) + { + flush(); + synchronized (notFull) + { + long start = System.currentTimeMillis(); + long elapsed = 0; + while (!closed.get() && head - tail >= size && elapsed < timeout) + { + try + { + notFull.wait(timeout - elapsed); + } + catch (InterruptedException e) + { + // pass + } + elapsed += System.currentTimeMillis() - start; + } + + if (closed.get()) + { + throw new TransportException("sender is closed", exception); + } + + if (head - tail >= size) + { + throw new TransportException(String.format("write timed out: %s, %s", head, tail)); + } + } + continue; + } + + final int hd_idx = mod(hd, size); + final int tl_idx = mod(tl, size); + final int length; + + if (tl_idx > hd_idx) + { + length = Math.min(tl_idx - hd_idx, remaining); + } + else + { + length = Math.min(size - hd_idx, remaining); + } + + buf.get(buffer, hd_idx, length); + head += length; + remaining -= length; + } + } + + public void flush() + { + if (idle) + { + synchronized (notEmpty) + { + notEmpty.notify(); + } + } + } + + public void close() + { + close(true); + } + + void close(boolean reportException) + { + if (!closed.getAndSet(true)) + { + synchronized (notEmpty) + { + notEmpty.notify(); + } + + try + { + if (Thread.currentThread() != this) + { + join(timeout); + if (isAlive()) + { + throw new TransportException("join timed out"); + } + } + transport.getReceiver().close(); + socket.close(); + } + catch (InterruptedException e) + { + throw new TransportException(e); + } + catch (IOException e) + { + throw new TransportException(e); + } + + if (reportException && exception != null) + { + throw new TransportException(exception); + } + } + } + + public void run() + { + final int size = buffer.length; + + while (true) + { + final int hd = head; + final int tl = tail; + + if (hd == tl) + { + if (closed.get()) + { + break; + } + + idle = true; + + synchronized (notEmpty) + { + while (head == tail && !closed.get()) + { + try + { + notEmpty.wait(); + } + catch (InterruptedException e) + { + // pass + } + } + } + + idle = false; + + continue; + } + + final int hd_idx = mod(hd, size); + final int tl_idx = mod(tl, size); + + final int length; + if (tl_idx < hd_idx) + { + length = hd_idx - tl_idx; + } + else + { + length = size - tl_idx; + } + + try + { + out.write(buffer, tl_idx, length); + } + catch (IOException e) + { + log.error(e, "error in write thread"); + exception = e; + close(false); + break; + } + tail += length; + if (head - tl >= size) + { + synchronized (notFull) + { + notFull.notify(); + } + } + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.java new file mode 100644 index 0000000000..70fd8a3c06 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/io/IoTransport.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.transport.network.io; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketException; +import java.nio.ByteBuffer; + +import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; +import org.apache.qpid.transport.Binding; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.ConnectionDelegate; +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.TransportException; +import org.apache.qpid.transport.network.Assembler; +import org.apache.qpid.transport.network.ConnectionBinding; +import org.apache.qpid.transport.network.Disassembler; +import org.apache.qpid.transport.network.InputHandler; +import org.apache.qpid.transport.util.Logger; + +/** + * This class provides a socket based transport using the java.io + * classes. + * + * The following params are configurable via JVM arguments + * TCP_NO_DELAY - amqj.tcpNoDelay + * SO_RCVBUF - amqj.receiveBufferSize + * SO_SNDBUF - amqj.sendBufferSize + */ +public final class IoTransport +{ + + static + { + org.apache.mina.common.ByteBuffer.setAllocator + (new org.apache.mina.common.SimpleByteBufferAllocator()); + org.apache.mina.common.ByteBuffer.setUseDirectBuffers + (Boolean.getBoolean("amqj.enableDirectBuffers")); + } + + private static final Logger log = Logger.get(IoTransport.class); + + private static int DEFAULT_READ_WRITE_BUFFER_SIZE = 64 * 1024; + private static int readBufferSize = Integer.getInteger + ("amqj.receiveBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE); + private static int writeBufferSize = Integer.getInteger + ("amqj.sendBufferSize", DEFAULT_READ_WRITE_BUFFER_SIZE); + + private Socket socket; + private IoSender sender; + private E endpoint; + private IoReceiver receiver; + private long timeout = 60000; + + IoTransport(Socket socket, Binding binding) + { + this.socket = socket; + this.sender = new IoSender(this, 2*writeBufferSize, timeout); + this.endpoint = binding.endpoint(sender); + this.receiver = new IoReceiver(this, binding.receiver(endpoint), + 2*readBufferSize, timeout); + } + + IoSender getSender() + { + return sender; + } + + IoReceiver getReceiver() + { + return receiver; + } + + Socket getSocket() + { + return socket; + } + + public static final E connect(String host, int port, + Binding binding) + { + Socket socket = createSocket(host, port); + IoTransport transport = new IoTransport(socket, binding); + return transport.endpoint; + } + + public static final Connection connect(String host, int port, + ConnectionDelegate delegate) + { + return connect(host, port, new ConnectionBinding(delegate)); + } + + public static void connect_0_9(AMQVersionAwareProtocolSession session, String host, int port) + { + connect(host, port, new Binding_0_9(session)); + } + + private static class Binding_0_9 + implements Binding + { + + private AMQVersionAwareProtocolSession session; + + Binding_0_9(AMQVersionAwareProtocolSession session) + { + this.session = session; + } + + public AMQVersionAwareProtocolSession endpoint(Sender sender) + { + session.setSender(sender); + return session; + } + + public Receiver receiver(AMQVersionAwareProtocolSession ssn) + { + return new InputHandler_0_9(ssn); + } + + } + + private static Socket createSocket(String host, int port) + { + try + { + InetAddress address = InetAddress.getByName(host); + Socket socket = new Socket(); + socket.setReuseAddress(true); + socket.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay")); + + log.debug("default-SO_RCVBUF : %s", socket.getReceiveBufferSize()); + log.debug("default-SO_SNDBUF : %s", socket.getSendBufferSize()); + + socket.setSendBufferSize(writeBufferSize); + socket.setReceiveBufferSize(readBufferSize); + + log.debug("new-SO_RCVBUF : %s", socket.getReceiveBufferSize()); + log.debug("new-SO_SNDBUF : %s", socket.getSendBufferSize()); + + socket.connect(new InetSocketAddress(address, port)); + return socket; + } + catch (SocketException e) + { + throw new TransportException("Error connecting to broker", e); + } + catch (IOException e) + { + throw new TransportException("Error connecting to broker", e); + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java new file mode 100644 index 0000000000..f8dbec3c3d --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaHandler.java @@ -0,0 +1,274 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.network.mina; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; + +import org.apache.mina.common.*; + +import org.apache.mina.transport.socket.nio.SocketAcceptor; +import org.apache.mina.transport.socket.nio.SocketSessionConfig; +import org.apache.mina.transport.socket.nio.SocketConnector; +import org.apache.mina.filter.ReadThrottleFilterBuilder; +import org.apache.mina.filter.WriteBufferLimitFilterBuilder; +import org.apache.mina.filter.executor.ExecutorFilter; + +import org.apache.qpid.transport.Binding; +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.ConnectionDelegate; +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.ConnectionBinding; + +import org.apache.qpid.transport.util.Logger; + +import org.apache.qpid.transport.network.Assembler; +import org.apache.qpid.transport.network.Disassembler; +import org.apache.qpid.transport.network.InputHandler; + +import static org.apache.qpid.transport.util.Functions.*; + +/** + * MinaHandler + * + * @author Rafael H. Schloming + */ +//RA making this public until we sort out the package issues +public class MinaHandler implements IoHandler +{ + /** Default buffer size for pending messages reads */ + private static final String DEFAULT_READ_BUFFER_LIMIT = "262144"; + /** Default buffer size for pending messages writes */ + private static final String DEFAULT_WRITE_BUFFER_LIMIT = "262144"; + private static final int MAX_RCVBUF = 64*1024; + + private static final Logger log = Logger.get(MinaHandler.class); + + static + { + ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); + ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers")); + } + + private final Binding binding; + + private MinaHandler(Binding binding) + { + this.binding = binding; + } + + public void messageReceived(IoSession ssn, Object obj) + { + Attachment attachment = (Attachment) ssn.getAttachment(); + ByteBuffer buf = (ByteBuffer) obj; + try + { + attachment.receiver.received(buf.buf()); + } + catch (Throwable t) + { + log.error(t, "exception handling buffer %s", str(buf.buf())); + throw new RuntimeException(t); + } + } + + public void messageSent(IoSession ssn, Object obj) + { + // do nothing + } + + public void exceptionCaught(IoSession ssn, Throwable e) + { + Attachment attachment = (Attachment) ssn.getAttachment(); + attachment.receiver.exception(e); + } + + /** + * Invoked by MINA when a MINA session for a new connection is created. This method sets up the filter chain on the + * session, which filters the events handled by this handler. The filter chain consists of, handing off events + * to an optional protectio + * + * @param session The MINA session. + * @throws Exception Any underlying exceptions are allowed to fall through to MINA. + */ + public void sessionCreated(IoSession session) throws Exception + { + log.debug("Protocol session created for session " + System.identityHashCode(session)); + + if (Boolean.getBoolean("protectio")) + { + try + { + //Add IO Protection Filters + IoFilterChain chain = session.getFilterChain(); + + session.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter()); + + ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); + readfilter.setMaximumConnectionBufferSize( + Integer.parseInt(System.getProperty("qpid.read.buffer.limit", DEFAULT_READ_BUFFER_LIMIT))); + readfilter.attach(chain); + + WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); + writefilter.setMaximumConnectionBufferSize( + Integer.parseInt(System.getProperty("qpid.write.buffer.limit", DEFAULT_WRITE_BUFFER_LIMIT))); + writefilter.attach(chain); + session.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); + + log.info("Using IO Read/Write Filter Protection"); + } + catch (Exception e) + { + log.error("Unable to attach IO Read/Write Filter Protection :" + e.getMessage()); + } + } + } + + public void sessionOpened(final IoSession ssn) + { + log.debug("opened: %s", this); + E endpoint = binding.endpoint(new MinaSender(ssn)); + Attachment attachment = + new Attachment(endpoint, binding.receiver(endpoint)); + + // We need to synchronize and notify here because the MINA + // connect future returns the session prior to the attachment + // being set. This is arguably a bug in MINA. + synchronized (ssn) + { + ssn.setAttachment(attachment); + ssn.notifyAll(); + } + } + + public void sessionClosed(IoSession ssn) + { + log.debug("closed: %s", ssn); + Attachment attachment = (Attachment) ssn.getAttachment(); + attachment.receiver.closed(); + ssn.setAttachment(null); + } + + public void sessionIdle(IoSession ssn, IdleStatus status) + { + // do nothing + } + + private static class Attachment + { + + E endpoint; + Receiver receiver; + + Attachment(E endpoint, Receiver receiver) + { + this.endpoint = endpoint; + this.receiver = receiver; + } + } + + public static final void accept(String host, int port, + Binding binding) + throws IOException + { + accept(new InetSocketAddress(host, port), binding); + } + + public static final void accept(SocketAddress address, + Binding binding) + throws IOException + { + IoAcceptor acceptor = new SocketAcceptor(); + acceptor.bind(address, new MinaHandler(binding)); + } + + public static final E connect(String host, int port, + Binding binding) + { + return connect(new InetSocketAddress(host, port), binding); + } + + public static final E connect(SocketAddress address, + Binding binding) + { + MinaHandler handler = new MinaHandler(binding); + SocketConnector connector = new SocketConnector(); + IoServiceConfig acceptorConfig = connector.getDefaultConfig(); + acceptorConfig.setThreadModel(ThreadModel.MANUAL); + SocketSessionConfig scfg = (SocketSessionConfig) acceptorConfig.getSessionConfig(); + scfg.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay")); + Integer sendBufferSize = Integer.getInteger("amqj.sendBufferSize"); + if (sendBufferSize != null && sendBufferSize > 0) + { + scfg.setSendBufferSize(sendBufferSize); + } + Integer receiveBufferSize = Integer.getInteger("amqj.receiveBufferSize"); + if (receiveBufferSize != null && receiveBufferSize > 0) + { + scfg.setReceiveBufferSize(receiveBufferSize); + } + else if (scfg.getReceiveBufferSize() > MAX_RCVBUF) + { + scfg.setReceiveBufferSize(MAX_RCVBUF); + } + connector.setWorkerTimeout(0); + ConnectFuture cf = connector.connect(address, handler); + cf.join(); + IoSession ssn = cf.getSession(); + + // We need to synchronize and wait here because the MINA + // connect future returns the session prior to the attachment + // being set. This is arguably a bug in MINA. + synchronized (ssn) + { + while (ssn.getAttachment() == null) + { + try + { + ssn.wait(); + } + catch (InterruptedException e) + { + throw new RuntimeException(e); + } + } + } + + Attachment attachment = (Attachment) ssn.getAttachment(); + return attachment.endpoint; + } + + public static final void accept(String host, int port, + ConnectionDelegate delegate) + throws IOException + { + accept(host, port, new ConnectionBinding(delegate)); + } + + public static final Connection connect(String host, int port, + ConnectionDelegate delegate) + { + return connect(host, port, new ConnectionBinding(delegate)); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.java new file mode 100644 index 0000000000..69d4061e0c --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/mina/MinaSender.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.transport.network.mina; + +import org.apache.mina.common.ByteBuffer; +import org.apache.mina.common.CloseFuture; +import org.apache.mina.common.IoSession; +import org.apache.mina.common.WriteFuture; + +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.TransportException; + + +/** + * MinaSender + */ + +public class MinaSender implements Sender +{ + private static final int TIMEOUT = 2 * 60 * 1000; + + private final IoSession session; + private WriteFuture lastWrite = null; + + public MinaSender(IoSession session) + { + this.session = session; + } + + public void send(java.nio.ByteBuffer buf) + { + if (session.isClosing()) + { + throw new TransportException("attempted to write to a closed socket"); + } + + synchronized (this) + { + lastWrite = session.write(ByteBuffer.wrap(buf)); + } + } + + public void flush() + { + // pass + } + + public synchronized void close() + { + // MINA will sometimes throw away in-progress writes when you + // ask it to close + synchronized (this) + { + if (lastWrite != null) + { + lastWrite.join(); + } + } + CloseFuture closed = session.close(); + closed.join(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java new file mode 100644 index 0000000000..51e41b26f7 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioHandler.java @@ -0,0 +1,118 @@ +package org.apache.qpid.transport.network.nio; + +import java.io.EOFException; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.qpid.transport.Connection; +import org.apache.qpid.transport.ConnectionDelegate; +import org.apache.qpid.transport.Receiver; +import org.apache.qpid.transport.network.Assembler; +import org.apache.qpid.transport.network.Disassembler; +import org.apache.qpid.transport.network.InputHandler; + +public class NioHandler implements Runnable +{ + private Receiver _receiver; + private SocketChannel _ch; + private ByteBuffer _readBuf; + private static Map _handlers = new ConcurrentHashMap(); + private AtomicInteger _count = new AtomicInteger(); + + private NioHandler(){} + + public static final Connection connect(String host, int port, + ConnectionDelegate delegate) + { + NioHandler handler = new NioHandler(); + return handler.connectInternal(host,port,delegate); + } + + private Connection connectInternal(String host, int port, + ConnectionDelegate delegate) + { + try + { + SocketAddress address = new InetSocketAddress(host,port); + _ch = SocketChannel.open(); + _ch.socket().setReuseAddress(true); + _ch.configureBlocking(true); + _ch.socket().setTcpNoDelay(true); + if (address != null) + { + _ch.socket().connect(address); + } + while (_ch.isConnectionPending()) + { + + } + + } + catch (SocketException e) + { + + e.printStackTrace(); + } + catch (IOException e) + { + e.printStackTrace(); + } + + NioSender sender = new NioSender(_ch); + Connection con = new Connection + (new Disassembler(sender, 64*1024 - 1), delegate); + + con.setConnectionId(_count.incrementAndGet()); + _handlers.put(con.getConnectionId(),sender); + + _receiver = new InputHandler(new Assembler(con), InputHandler.State.FRAME_HDR); + + Thread t = new Thread(this); + t.start(); + + return con; + } + + public void run() + { + _readBuf = ByteBuffer.allocate(512); + long read = 0; + while(_ch.isConnected() && _ch.isOpen()) + { + try + { + read = _ch.read(_readBuf); + if (read > 0) + { + _readBuf.flip(); + ByteBuffer b = ByteBuffer.allocate(_readBuf.remaining()); + b.put(_readBuf); + b.flip(); + _readBuf.clear(); + _receiver.received(b); + } + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + //throw new EOFException("The underlying socket/channel has closed"); + } + + public static void startBatchingFrames(int connectionId) + { + NioSender sender = _handlers.get(connectionId); + sender.setStartBatching(); + } + + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java new file mode 100644 index 0000000000..33e888cc56 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/network/nio/NioSender.java @@ -0,0 +1,100 @@ +package org.apache.qpid.transport.network.nio; + +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; + +import org.apache.qpid.transport.Sender; + +public class NioSender implements Sender +{ + private final Object lock = new Object(); + private SocketChannel _ch; + private boolean _batch = false; + private ByteBuffer _batcher; + + public NioSender(SocketChannel ch) + { + this._ch = ch; + } + + public void send(java.nio.ByteBuffer buf) + { + if (_batch) + { + //System.out.println(_batcher.position() + " , " + buf.remaining() + " , " + buf.position() + ","+_batcher.capacity()); + if (_batcher.position() + buf.remaining() >= _batcher.capacity()) + { + _batcher.flip(); + write(_batcher); + _batcher.clear(); + if (buf.remaining() > _batcher.capacity()) + { + write(buf); + } + else + { + _batcher.put(buf); + } + } + else + { + _batcher.put(buf); + } + } + else + { + write(buf); + } + } + + public void flush() + { + // pass + } + + private void write(java.nio.ByteBuffer buf) + { + synchronized (lock) + { + if( _ch.isConnected() && _ch.isOpen()) + { + try + { + _ch.write(buf); + } + catch(Exception e) + { + e.fillInStackTrace(); + } + } + else + { + throw new RuntimeException("Trying to write on a closed socket"); + } + + } + } + + public void setStartBatching() + { + _batch = true; + _batcher = ByteBuffer.allocate(1024); + } + + public void close() + { + // MINA will sometimes throw away in-progress writes when you + // ask it to close + synchronized (lock) + { + try + { + _ch.close(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + } +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/util/Functions.java b/java/common/src/main/java/org/apache/qpid/transport/util/Functions.java new file mode 100644 index 0000000000..2c6984e302 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/util/Functions.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.transport.util; + +import java.nio.ByteBuffer; + +import static java.lang.Math.*; + + +/** + * Functions + * + * @author Rafael H. Schloming + */ + +public class Functions +{ + + public static final byte lsb(int i) + { + return (byte) (0xFF & i); + } + + public static final byte lsb(long l) + { + return (byte) (0xFF & l); + } + + public static final String str(ByteBuffer buf) + { + return str(buf, buf.remaining()); + } + + public static final String str(ByteBuffer buf, int limit) + { + StringBuilder str = new StringBuilder(); + str.append('"'); + + for (int i = 0; i < min(buf.remaining(), limit); i++) + { + byte c = buf.get(buf.position() + i); + + if (c > 31 && c < 127 && c != '\\') + { + str.append((char)c); + } + else + { + str.append(String.format("\\x%02x", c)); + } + } + + str.append('"'); + + if (limit < buf.remaining()) + { + str.append("..."); + } + + return str.toString(); + } + + public static final String str(byte[] bytes) + { + return str(ByteBuffer.wrap(bytes)); + } + + public static final String str(byte[] bytes, int limit) + { + return str(ByteBuffer.wrap(bytes), limit); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/util/Logger.java b/java/common/src/main/java/org/apache/qpid/transport/util/Logger.java new file mode 100644 index 0000000000..8c4818df92 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/util/Logger.java @@ -0,0 +1,130 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport.util; + +import org.slf4j.LoggerFactory; + +/** + * Logger + * + */ + +public final class Logger +{ + + public static final Logger get(Class klass) + { + return new Logger(LoggerFactory.getLogger(klass)); + } + + private final org.slf4j.Logger log; + + private Logger(org.slf4j.Logger log) + { + this.log = log; + } + + public boolean isDebugEnabled() + { + return log.isDebugEnabled(); + } + + public void debug(String message, Object ... args) + { + if (log.isDebugEnabled()) + { + log.debug(String.format(message, args)); + } + } + + public void debug(Throwable t, String message, Object ... args) + { + if (log.isDebugEnabled()) + { + log.debug(String.format(message, args), t); + } + } + + public void error(String message, Object ... args) + { + if (log.isErrorEnabled()) + { + log.error(String.format(message, args)); + } + } + + public void error(Throwable t, String message, Object ... args) + { + if (log.isErrorEnabled()) + { + log.error(String.format(message, args), t); + } + } + + public void warn(String message, Object ... args) + { + if (log.isWarnEnabled()) + { + log.warn(String.format(message, args)); + } + } + + public void warn(Throwable t, String message, Object ... args) + { + if (log.isWarnEnabled()) + { + log.warn(String.format(message, args), t); + } + } + + public void info(String message, Object ... args) + { + if (log.isInfoEnabled()) + { + log.info(String.format(message, args)); + } + } + + public void info(Throwable t, String message, Object ... args) + { + if (log.isInfoEnabled()) + { + log.info(String.format(message, args), t); + } + } + + public void trace(String message, Object ... args) + { + if (log.isTraceEnabled()) + { + log.trace(String.format(message, args)); + } + } + + public void trace(Throwable t, String message, Object ... args) + { + if (log.isTraceEnabled()) + { + log.trace(String.format(message, args), t); + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/transport/util/SliceIterator.java b/java/common/src/main/java/org/apache/qpid/transport/util/SliceIterator.java new file mode 100644 index 0000000000..3db29847b2 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/transport/util/SliceIterator.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.transport.util; + +import java.nio.ByteBuffer; + +import java.util.Iterator; + + +/** + * SliceIterator + * + * @author Rafael H. Schloming + */ + +public class SliceIterator implements Iterator +{ + + final private Iterator iterator; + + public SliceIterator(Iterator iterator) + { + this.iterator = iterator; + } + + public boolean hasNext() + { + return iterator.hasNext(); + } + + public ByteBuffer next() + { + return iterator.next().slice(); + } + + public void remove() + { + throw new UnsupportedOperationException(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java b/java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java index 2cf035f601..f12fb2cff2 100644 --- a/java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java +++ b/java/common/src/main/java/org/apache/qpid/url/BindingURLImpl.java @@ -17,7 +17,7 @@ */ package org.apache.qpid.url; -import org.apache.qpidity.exchange.ExchangeDefaults; +import org.apache.qpid.exchange.ExchangeDefaults; import org.slf4j.LoggerFactory; import org.slf4j.Logger; diff --git a/java/common/src/main/java/org/apache/qpid/url/QpidURL.java b/java/common/src/main/java/org/apache/qpid/url/QpidURL.java index 1d94b31de2..5ab4425323 100644 --- a/java/common/src/main/java/org/apache/qpid/url/QpidURL.java +++ b/java/common/src/main/java/org/apache/qpid/url/QpidURL.java @@ -17,7 +17,7 @@ */ package org.apache.qpid.url; -import org.apache.qpidity.BrokerDetails; +import org.apache.qpid.BrokerDetails; import java.util.List; diff --git a/java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java b/java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java index b4a55e2bf4..f92934db7f 100644 --- a/java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java +++ b/java/common/src/main/java/org/apache/qpid/url/QpidURLImpl.java @@ -17,8 +17,8 @@ */ package org.apache.qpid.url; -import org.apache.qpidity.BrokerDetails; -import org.apache.qpidity.BrokerDetailsImpl; +import org.apache.qpid.BrokerDetails; +import org.apache.qpid.BrokerDetailsImpl; import java.net.MalformedURLException; import java.util.ArrayList; diff --git a/java/common/src/main/java/org/apache/qpid/util/NameUUIDGen.java b/java/common/src/main/java/org/apache/qpid/util/NameUUIDGen.java new file mode 100644 index 0000000000..e764c8536b --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/util/NameUUIDGen.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.util; + +import java.nio.ByteBuffer; +import java.util.UUID; + + +/** + * NameUUIDGen + * + */ + +public final class NameUUIDGen implements UUIDGen +{ + + private static final int WIDTH = 8; + + final private byte[] seed; + final private ByteBuffer seedBuf; + private long counter; + + public NameUUIDGen() + { + String namespace = UUID.randomUUID().toString(); + this.seed = new byte[namespace.length() + WIDTH]; + for (int i = WIDTH; i < seed.length; i++) + { + seed[i] = (byte) namespace.charAt(i - WIDTH); + } + this.seedBuf = ByteBuffer.wrap(seed); + this.counter = 0; + } + + public UUID generate() + { + seedBuf.putLong(0, counter++); + return UUID.nameUUIDFromBytes(seed); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/util/RandomUUIDGen.java b/java/common/src/main/java/org/apache/qpid/util/RandomUUIDGen.java new file mode 100644 index 0000000000..60b402a105 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/util/RandomUUIDGen.java @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.util; + +import java.util.UUID; + + +/** + * RandomUUIDGen + * + */ + +public final class RandomUUIDGen implements UUIDGen +{ + + public UUID generate() + { + return UUID.randomUUID(); + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java b/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java deleted file mode 100644 index 28fb2e0c8a..0000000000 --- a/java/common/src/main/java/org/apache/qpid/util/ReflectionUtils.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.util; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - * Provides helper methods for operating on classes and methods using reflection. Reflection methods tend to return - * a lot of checked exception so writing code to use them can be tedious and harder to read, especially when such errors - * are not expected to occur. This class always works with {@link ReflectionUtilsException}, which is a runtime exception, - * to wrap the checked exceptions raised by the standard Java reflection methods. Code using it does not normally - * expect these errors to occur, usually does not have a recovery mechanism for them when they do, but is cleaner, - * quicker to write and easier to read in the majority of cases. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Look up Classes by name. - *
Instantiate Classes by no-arg constructor. - *
- */ -public class ReflectionUtils -{ - /** - * Gets the Class object for a named class. - * - * @param className The class to get the Class object for. - * - * @return The Class object for the named class. - */ - public static Class forName(String className) - { - try - { - return Class.forName(className); - } - catch (ClassNotFoundException e) - { - throw new ReflectionUtilsException("ClassNotFoundException whilst finding class.", e); - } - } - - /** - * Creates an instance of a Class, instantiated through its no-args constructor. - * - * @param cls The Class to instantiate. - * @param The Class type. - * - * @return An instance of the class. - */ - public static T newInstance(Class cls) - { - try - { - return cls.newInstance(); - } - catch (InstantiationException e) - { - throw new ReflectionUtilsException("InstantiationException whilst instantiating class.", e); - } - catch (IllegalAccessException e) - { - throw new ReflectionUtilsException("IllegalAccessException whilst instantiating class.", e); - } - } - - /** - * Calls a named method on an object with a specified set of parameters, any Java access modifier are overridden. - * - * @param o The object to call. - * @param method The method name to call. - * @param params The parameters to pass. - * @param paramClasses The argument types. - * - * @return The return value from the method call. - */ - public static Object callMethodOverridingIllegalAccess(Object o, String method, Object[] params, Class[] paramClasses) - { - // Get the objects class. - Class cls = o.getClass(); - - // Get the classes of the parameters. - /*Class[] paramClasses = new Class[params.length]; - - for (int i = 0; i < params.length; i++) - { - paramClasses[i] = params[i].getClass(); - }*/ - - try - { - // Try to find the matching method on the class. - Method m = cls.getDeclaredMethod(method, paramClasses); - - // Make it accessible. - m.setAccessible(true); - - // Invoke it with the parameters. - return m.invoke(o, params); - } - catch (NoSuchMethodException e) - { - throw new ReflectionUtilsException("NoSuchMethodException.", e); - } - catch (IllegalAccessException e) - { - throw new ReflectionUtilsException("IllegalAccessException.", e); - } - catch (InvocationTargetException e) - { - throw new ReflectionUtilsException("InvocationTargetException", e); - } - } - - /** - * Calls a named method on an object with a specified set of parameters. - * - * @param o The object to call. - * @param method The method name to call. - * @param params The parameters to pass. - * - * @return The return value from the method call. - */ - public static Object callMethod(Object o, String method, Object[] params) - { - // Get the objects class. - Class cls = o.getClass(); - - // Get the classes of the parameters. - Class[] paramClasses = new Class[params.length]; - - for (int i = 0; i < params.length; i++) - { - paramClasses[i] = params[i].getClass(); - } - - try - { - // Try to find the matching method on the class. - Method m = cls.getMethod(method, paramClasses); - - // Invoke it with the parameters. - return m.invoke(o, params); - } - catch (NoSuchMethodException e) - { - throw new ReflectionUtilsException("NoSuchMethodException.", e); - } - catch (IllegalAccessException e) - { - throw new ReflectionUtilsException("IllegalAccessException", e); - } - catch (InvocationTargetException e) - { - throw new ReflectionUtilsException("InvocationTargetException", e); - } - } - - /** - * Calls a constuctor witht the specified arguments. - * - * @param constructor The constructor. - * @param args The arguments. - * @param The Class type. - * - * @return An instance of the class that the constructor is for. - */ - public static T newInstance(Constructor constructor, Object[] args) - { - try - { - return constructor.newInstance(args); - } - catch (InstantiationException e) - { - throw new ReflectionUtilsException("InstantiationException", e); - } - catch (IllegalAccessException e) - { - throw new ReflectionUtilsException("IllegalAccessException", e); - } - catch (InvocationTargetException e) - { - throw new ReflectionUtilsException("InvocationTargetException", e); - } - } - - /** - * Gets the constructor of a class that takes the specified set of arguments if any matches. If no matching - * constructor is found then a runtime exception is raised. - * - * @param cls The class to get a constructor from. - * @param args The arguments to match. - * @param The class type. - * - * @return The constructor. - */ - public static Constructor getConstructor(Class cls, Class[] args) - { - try - { - return cls.getConstructor(args); - } - catch (NoSuchMethodException e) - { - throw new ReflectionUtilsException("NoSuchMethodException", e); - } - } -} diff --git a/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java b/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java deleted file mode 100644 index c2862a755b..0000000000 --- a/java/common/src/main/java/org/apache/qpid/util/ReflectionUtilsException.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.util; - -/** - * Wraps a checked exception that occurs when {@link ReflectionUtils} encounters checked exceptions using standard - * Java reflection methods. - * - *

- *
CRC Card
Responsibilities Collaborations - *
Wrap a checked reflection exception. - *
- */ -public class ReflectionUtilsException extends RuntimeException -{ - /** - * Creates a runtime reflection exception, from a checked one. - * - * @param message The message. - * @param cause The causing exception. - */ - public ReflectionUtilsException(String message, Throwable cause) - { - super(message, cause); - } -} diff --git a/java/common/src/main/java/org/apache/qpid/util/Strings.java b/java/common/src/main/java/org/apache/qpid/util/Strings.java new file mode 100644 index 0000000000..4b199bafe6 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/util/Strings.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.util; + +import java.io.UnsupportedEncodingException; + + +/** + * Strings + * + */ + +public final class Strings +{ + + private static final byte[] EMPTY = new byte[0]; + + private static final ThreadLocal charbuf = new ThreadLocal() + { + public char[] initialValue() + { + return new char[4096]; + } + }; + + public static final byte[] toUTF8(String str) + { + if (str == null) + { + return EMPTY; + } + else + { + final int size = str.length(); + char[] chars = charbuf.get(); + if (size > chars.length) + { + chars = new char[Math.max(size, 2*chars.length)]; + charbuf.set(chars); + } + + str.getChars(0, size, chars, 0); + final byte[] bytes = new byte[size]; + for (int i = 0; i < size; i++) + { + if (chars[i] > 127) + { + try + { + return str.getBytes("UTF-8"); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } + } + + bytes[i] = (byte) chars[i]; + } + return bytes; + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpid/util/UUIDGen.java b/java/common/src/main/java/org/apache/qpid/util/UUIDGen.java new file mode 100644 index 0000000000..3cfe5afdac --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/util/UUIDGen.java @@ -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. + * + */ +package org.apache.qpid.util; + + +import java.util.UUID; + +/** + * UUIDGen + * + */ + +public interface UUIDGen +{ + + public UUID generate(); + +} diff --git a/java/common/src/main/java/org/apache/qpid/util/UUIDs.java b/java/common/src/main/java/org/apache/qpid/util/UUIDs.java new file mode 100644 index 0000000000..4bf6b7f0a2 --- /dev/null +++ b/java/common/src/main/java/org/apache/qpid/util/UUIDs.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.util; + + +/** + * UUIDs + * + */ + +public final class UUIDs +{ + + public static final UUIDGen newGenerator() + { + return newGenerator(System.getProperty("qpid.uuid.generator", + NameUUIDGen.class.getName())); + } + + public static UUIDGen newGenerator(String name) + { + try + { + Class cls = Class.forName(name); + return (UUIDGen) cls.newInstance(); + } + catch (InstantiationException e) + { + throw new RuntimeException(e); + } + catch (IllegalAccessException e) + { + throw new RuntimeException(e); + } + catch (ClassNotFoundException e) + { + throw new RuntimeException(e); + } + } + +} diff --git a/java/common/src/main/java/org/apache/qpidity/BrokerDetails.java b/java/common/src/main/java/org/apache/qpidity/BrokerDetails.java deleted file mode 100644 index 29a4f5a9c0..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/BrokerDetails.java +++ /dev/null @@ -1,138 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity; - -import java.util.Map; - -/** - * This interface represents a broker and provides the basic information - * required for opening a connection with a broker. - */ -public interface BrokerDetails -{ - /** - * Those are the supported protocols - */ - public static final String PROTOCOL_TCP = "tcp"; - public static final String PROTOCOL_TLS = "tls"; - - public static final String VIRTUAL_HOST = "virtualhost"; - public static final String CLIENT_ID = "client_id"; - public static final String USERNAME = "username"; - public static final String PASSWORD = "password"; - - /** - * Get the broker host name. - * - * @return The broker host name. - */ - public String getHost(); - - /** - * Get the broker port number. - * - * @return The broker port number. - */ - public int getPort(); - - /** - * Get the virtual host to connect to. - * - * @return The virtual host of this broker. - */ - public String getVirtualHost(); - - /** - * Get the user name. - * - * @return The user name - */ - public String getUserName(); - - /** - * Get the user password - * - * @return The user password - */ - public String getPassword(); - - /** - * Get the protocol used to connect to hise broker. - * - * @return the protocol used to connect to the broker. - */ - public String getProtocol(); - - /** - * Set the broker host name. - * - * @param host The broker host name. - */ - public void setHost(String host); - - /** - * Set the broker port number. - * - * @param port The broker port number. - */ - public void setPort(int port); - - /** - * Set the virtual host to connect to. - * - * @param virtualHost The virtual host of this broker. - */ - public void setVirtualHost(String virtualHost); - - /** - * Set the user name. - * - * @param userName The user name - */ - public void setUserName(String userName); - - /** - * Set the user password - * - * @param password The user password - */ - public void setPassword(String password); - - /** - * Set the protocol used to connect to hise broker. - * - * @param protocol the protocol used to connect to the broker. - */ - public void setProtocol(String protocol); - - /** - * Ex: keystore path - * - * @return the Properties associated with this connection. - */ - public Map getProperties(); - - /** - * Sets the properties associated with this connection - * - * @param props the new p[roperties. - */ - public void setProperties(Map props); - - public void setProperty(String key,String value); -} diff --git a/java/common/src/main/java/org/apache/qpidity/BrokerDetailsImpl.java b/java/common/src/main/java/org/apache/qpidity/BrokerDetailsImpl.java deleted file mode 100644 index 6de6055f1c..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/BrokerDetailsImpl.java +++ /dev/null @@ -1,264 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity; - -import java.util.HashMap; -import java.util.Map; - -/** - * Implements the interface BrokerDetails - */ -public class BrokerDetailsImpl implements BrokerDetails -{ - //--- Those are the default values - private final String DEFAULT_USERNAME = "guest"; - private final String DEFAULT_PASSWORD = "guest"; - private final String DEFAULT_VIRTUALHOST = ""; - - //---- The brker details - private String _host; - private int _port = 0; - private String _virtualHost; - private String _userName = DEFAULT_USERNAME; - private String _password = DEFAULT_PASSWORD; - private String _protocol; - private Map _props = new HashMap(); - ; - - //--- Constructors - - public BrokerDetailsImpl() - { - } - - /** - * Create a new broker details given all the reuqired information - * - * @param protocol The protocol used for this broker connection - * @param host The host name. - * @param port The port number. - * @param virtualHost The virtual host. - * @param userName The user name. - * @param password The user password. - */ - public BrokerDetailsImpl(String protocol, String host, int port, String virtualHost, String userName, - String password, Map props) - { - _protocol = protocol; - _host = host; - _port = port; - _virtualHost = virtualHost; - _userName = userName; - _password = password; - _props = props; - } - - /** - * Create a new broker details given the host name and the procol type, - * default values are used for the other details. - * - * @param protocol The protocol used for this broker connection - * @param host The host name. - */ - public BrokerDetailsImpl(String protocol, String host) - { - _protocol = protocol; - _host = host; - _virtualHost = DEFAULT_VIRTUALHOST; - _userName = DEFAULT_USERNAME; - _password = DEFAULT_PASSWORD; - } - - //--- API BrokerDetails - /** - * Get the user password - * - * @return The user password - */ - public String getPassword() - { - return _password; - } - - /** - * Get the broker host name. - * - * @return The broker host name. - */ - public String getHost() - { - return _host; - } - - /** - * Get the broker port number. - * - * @return The broker port number. - */ - public int getPort() - { - if (_port == 0) - { - if (getProtocol().equals(BrokerDetails.PROTOCOL_TCP)) - { - _port = 5672; - } - else if (getProtocol().equals(BrokerDetails.PROTOCOL_TLS)) - { - _port = 5555; - } - } - return _port; - } - - /** - * Get the virtual host to connect to. - * - * @return The virtual host of this broker. - */ - public String getVirtualHost() - { - return _virtualHost; - } - - /** - * Get the user name. - * - * @return The user name - */ - public String getUserName() - { - return _userName; - } - - /** - * Get the protocol used to connect to hise broker. - * - * @return the protocol used to connect to the broker. - */ - public String getProtocol() - { - return _protocol; - } - - /** - * Set the broker host name. - * - * @param host The broker host name. - */ - public void setHost(String host) - { - _host = host; - } - - /** - * Set the broker port number. - * - * @param port The broker port number. - */ - public void setPort(int port) - { - _port = port; - } - - /** - * Set the virtual host to connect to. - * - * @param virtualHost The virtual host of this broker. - */ - public void setVirtualHost(String virtualHost) - { - _virtualHost = virtualHost; - } - - /** - * Set the user name. - * - * @param userName The user name - */ - public void setUserName(String userName) - { - _userName = userName; - } - - /** - * Set the user password - * - * @param password The user password - */ - public void setPassword(String password) - { - _password = password; - } - - /** - * Set the protocol used to connect to hise broker. - * - * @param protocol the protocol used to connect to the broker. - */ - public void setProtocol(String protocol) - { - _protocol = protocol; - } - - /** - * Ex: keystore path - * - * @return the Properties associated with this connection. - */ - public Map getProperties() - { - return _props; - } - - /** - * Sets the properties associated with this connection - * - * @param props - */ - public void setProperties(Map props) - { - _props = props; - } - - public void setProperty(String key, String value) - { - _props.put(key, value); - } - - public String toString() - { - StringBuilder b = new StringBuilder(); - b.append("[username=" + _userName); - b.append(",password=" + _password); - b.append(",transport=" + _protocol); - b.append(",host=" + _host); - b.append(",port=" + getPort() + "]"); - b.append(" - Properties["); - if (_props != null) - { - for (String k : _props.keySet()) - { - b.append(k + "=" + _props.get(k) + ","); - } - } - b.append("]"); - - return b.toString(); - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/ConsoleOutput.java b/java/common/src/main/java/org/apache/qpidity/ConsoleOutput.java deleted file mode 100644 index 4e05aa574c..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/ConsoleOutput.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity; - -import java.nio.ByteBuffer; - -import org.apache.qpidity.transport.Sender; - -import static org.apache.qpidity.transport.util.Functions.*; - - -/** - * ConsoleOutput - * - * @author Rafael H. Schloming - */ - -public class ConsoleOutput implements Sender -{ - - public void send(ByteBuffer buf) - { - System.out.println(str(buf)); - } - - public void close() - { - System.out.println("CLOSED"); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/ErrorCode.java b/java/common/src/main/java/org/apache/qpidity/ErrorCode.java deleted file mode 100644 index 4b18c46d16..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/ErrorCode.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.apache.qpidity; - -public enum ErrorCode -{ - //Qpid specific - for the time being - UNDEFINED(1,"undefined",true), - MESSAGE_REJECTED(2,"message_rejected",true), - CONNECTION_ERROR(3,"connection was closed",true), - UNSUPPORTED_PROTOCOL(4, "protocol version is unsupported", true), - - //This might change in the spec, the error class is not applicable - NO_ERROR(200,"reply-success",true), - - //From the spec - CONTENT_TOO_LARGE(311,"content-too-large",false), - NO_ROUTE(312,"no-route",false), - NO_CONSUMERS(313,"content-consumers",false), - CONNECTION_FORCED(320,"connection-forced",true), - INVALID_PATH(402,"invalid-path",true), - ACCESS_REFUSED(403,"access-refused",false), - NOT_FOUND(404,"not-found",false), - RESOURCE_LOCKED(405,"resource-locked",false), - PRE_CONDITION_FAILED(406,"precondition-failed",false), - - FRAME_ERROR(501,"frame_error",true), - SYNTAX_ERROR(502,"syntax_error",true), - COMMAND_INVALID(503,"command_invalid",true), - SESSION_ERROR(504,"sesion_error",true), - NOT_ALLOWED(530,"not_allowed",true), - NOT_IMPLEMENTED(540,"not_implemented",true), - INTERNAL_ERROR(541,"internal_error",true), - INVALID_ARGUMENT(542,"invalid_argument",true); - - private int _code; - private String _desc; - private boolean _hardError; - - private ErrorCode(int code,String desc,boolean hardError) - { - _code = code; - _desc= desc; - _hardError = hardError; - } - - public int getCode() - { - return _code; - } - - public String getDesc() - { - return _desc; - } - - private boolean isHardError() - { - return _hardError; - } - - public static ErrorCode get(int code) - { - switch(code) - { - case 200 : return NO_ERROR; - case 311 : return CONTENT_TOO_LARGE; - case 312 : return NO_ROUTE; - case 313 : return NO_CONSUMERS; - case 320 : return CONNECTION_FORCED; - case 402 : return INVALID_PATH; - case 403 : return ACCESS_REFUSED; - case 404 : return NOT_FOUND; - case 405 : return RESOURCE_LOCKED; - case 406 : return PRE_CONDITION_FAILED; - case 501 : return FRAME_ERROR; - case 502 : return SYNTAX_ERROR; - case 503 : return COMMAND_INVALID; - case 504 : return SESSION_ERROR; - case 530 : return NOT_ALLOWED; - case 540 : return NOT_IMPLEMENTED; - case 541 : return INTERNAL_ERROR; - case 542 : return INVALID_ARGUMENT; - - default : return UNDEFINED; - } - } - } - -/* - - - - The server could not complete the method because of an internal error. The server may require - intervention by an operator in order to resume normal operations. - - - - - - An invalid or illegal argument was passed to a method, and the operation could not proceed. - - -*/ \ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpidity/ProtocolException.java b/java/common/src/main/java/org/apache/qpidity/ProtocolException.java deleted file mode 100644 index 596143a1b9..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/ProtocolException.java +++ /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. - */ - -package org.apache.qpidity; - -public class ProtocolException extends QpidException -{ - /** - * Constructor for a Ptotocol Exception. - *

This is the only provided constructor and the parameters have to be set to null when - * they are unknown. - * @param message A description of the reason of this exception. - * @param errorCode A string specifyin the error code of this exception. - * @param cause The linked Execption. - * - */ - public ProtocolException(String message, ErrorCode errorCode, Throwable cause) - { - super(message, errorCode, cause); - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/QpidConfig.java b/java/common/src/main/java/org/apache/qpidity/QpidConfig.java deleted file mode 100644 index b5aad12f10..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/QpidConfig.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.apache.qpidity; - -/** - * API to configure the Security parameters of the client. - * The user can choose to pick the config from any source - * and set it using this class. - * - */ -public class QpidConfig -{ - private static QpidConfig _instance = new QpidConfig(); - - private SecurityMechanism[] securityMechanisms = - new SecurityMechanism[]{new SecurityMechanism("PLAIN","org.apache.qpidity.security.UsernamePasswordCallbackHandler"), - new SecurityMechanism("CRAM_MD5","org.apache.qpidity.security.UsernamePasswordCallbackHandler")}; - - private SaslClientFactory[] saslClientFactories = - new SaslClientFactory[]{new SaslClientFactory("AMQPLAIN","org.apache.qpidity.security.amqplain.AmqPlainSaslClientFactory")}; - - private QpidConfig(){} - - public static QpidConfig get() - { - return _instance; - } - - public void setSecurityMechanisms(SecurityMechanism... securityMechanisms) - { - this.securityMechanisms = securityMechanisms; - } - - public SecurityMechanism[] getSecurityMechanisms() - { - return securityMechanisms; - } - - public void setSaslClientFactories(SaslClientFactory... saslClientFactories) - { - this.saslClientFactories = saslClientFactories; - } - - public SaslClientFactory[] getSaslClientFactories() - { - return saslClientFactories; - } - - public class SecurityMechanism - { - String type; - String handler; - - SecurityMechanism(String type,String handler) - { - this.type = type; - this.handler = handler; - } - - public String getHandler() - { - return handler; - } - - public String getType() - { - return type; - } - } - - public class SaslClientFactory - { - String type; - String factoryClass; - - SaslClientFactory(String type,String factoryClass) - { - this.type = type; - this.factoryClass = factoryClass; - } - - public String getFactoryClass() - { - return factoryClass; - } - - public String getType() - { - return type; - } - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/QpidException.java b/java/common/src/main/java/org/apache/qpidity/QpidException.java deleted file mode 100644 index 81e9145282..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/QpidException.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.qpidity; - -public class QpidException extends Exception -{ - /** - * AMQP error code - */ - private ErrorCode _errorCode; - - /** - * Constructor for a Qpid Exception. - *

This is the only provided constructor and the parameters have to be set to null when - * they are unknown. - * @param message A description of the reason of this exception . - * @param errorCode A string specifyin the error code of this exception. - * @param cause The linked Execption. * - * - */ - public QpidException(String message, ErrorCode errorCode, Throwable cause) - { - super(message, cause); - _errorCode = errorCode; - } - - /*hack to get rid of a compile error from a generated class - public QpidException(String message, String errorCode, Throwable cause) - { - - }*/ - - /** - * Get this execption error code. - * - * @return This exception error code. - */ - public ErrorCode getErrorCode() - { - return _errorCode; - } -} - diff --git a/java/common/src/main/java/org/apache/qpidity/SecurityHelper.java b/java/common/src/main/java/org/apache/qpidity/SecurityHelper.java deleted file mode 100644 index a72997813a..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/SecurityHelper.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.qpidity; - -import java.io.UnsupportedEncodingException; -import java.util.HashSet; -import java.util.List; -import java.util.StringTokenizer; - -import org.apache.qpidity.security.AMQPCallbackHandler; -import org.apache.qpidity.security.CallbackHandlerRegistry; - -public class SecurityHelper -{ - public static String chooseMechanism(List mechanisms) throws UnsupportedEncodingException - { - HashSet mechanismSet = new HashSet(); - for (Object m : mechanisms) - { - mechanismSet.add(m); - } - - String preferredMechanisms = CallbackHandlerRegistry.getInstance().getMechanisms(); - StringTokenizer prefTokenizer = new StringTokenizer(preferredMechanisms, " "); - while (prefTokenizer.hasMoreTokens()) - { - String mech = prefTokenizer.nextToken(); - if (mechanismSet.contains(mech)) - { - return mech; - } - } - return null; - } - - public static AMQPCallbackHandler createCallbackHandler(String mechanism, String username,String password) - throws QpidException - { - Class mechanismClass = CallbackHandlerRegistry.getInstance().getCallbackHandlerClass(mechanism); - try - { - Object instance = mechanismClass.newInstance(); - AMQPCallbackHandler cbh = (AMQPCallbackHandler) instance; - cbh.initialise(username,password); - return cbh; - } - catch (Exception e) - { - throw new QpidException("Unable to create callback handler: " + e,ErrorCode.UNDEFINED, e.getCause()); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/ToyBroker.java b/java/common/src/main/java/org/apache/qpidity/ToyBroker.java deleted file mode 100644 index 5f9917e30a..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/ToyBroker.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity; - -import org.apache.qpidity.transport.*; -import org.apache.qpidity.transport.network.mina.MinaHandler; - -import static org.apache.qpidity.transport.util.Functions.str; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.LinkedBlockingQueue; - - -/** - * ToyBroker - * - * @author Rafael H. Schloming - */ - -class ToyBroker extends SessionDelegate -{ - - private ToyExchange exchange; - private MessageTransfer xfr = null; - private DeliveryProperties props = null; - private Header header = null; - private List body = null; - private Map consumers = new ConcurrentHashMap(); - - public ToyBroker(ToyExchange exchange) - { - this.exchange = exchange; - } - - public void messageAcquire(Session context, MessageAcquire struct) - { - System.out.println("\n==================> messageAcquire " ); - context.executionResult((int) struct.getId(), new Acquired(struct.getTransfers())); - } - - @Override public void queueDeclare(Session ssn, QueueDeclare qd) - { - exchange.createQueue(qd.getQueue()); - System.out.println("\n==================> declared queue: " + qd.getQueue() + "\n"); - } - - @Override public void exchangeBind(Session ssn, ExchangeBind qb) - { - exchange.bindQueue(qb.getExchange(), qb.getBindingKey(),qb.getQueue()); - System.out.println("\n==================> bound queue: " + qb.getQueue() + " with binding key " + qb.getBindingKey() + "\n"); - } - - @Override public void queueQuery(Session ssn, QueueQuery qq) - { - QueueQueryResult result = new QueueQueryResult().queue(qq.getQueue()); - ssn.executionResult((int) qq.getId(), result); - } - - @Override public void messageSubscribe(Session ssn, MessageSubscribe ms) - { - Consumer c = new Consumer(); - c._queueName = ms.getQueue(); - consumers.put(ms.getDestination(),c); - System.out.println("\n==================> message subscribe : " + ms.getDestination() + " queue: " + ms.getQueue() + "\n"); - } - - @Override public void messageFlow(Session ssn,MessageFlow struct) - { - Consumer c = consumers.get(struct.getDestination()); - c._credit = struct.getValue(); - System.out.println("\n==================> message flow : " + struct.getDestination() + " credit: " + struct.getValue() + "\n"); - } - - @Override public void messageFlush(Session ssn,MessageFlush struct) - { - System.out.println("\n==================> message flush for consumer : " + struct.getDestination() + "\n"); - checkAndSendMessagesToConsumer(ssn,struct.getDestination()); - } - - @Override public void messageTransfer(Session ssn, MessageTransfer xfr) - { - this.xfr = xfr; - body = new ArrayList(); - System.out.println("received transfer " + xfr.getDestination()); - } - - @Override public void header(Session ssn, Header header) - { - if (xfr == null || body == null) - { - ssn.connectionClose(ConnectionCloseCode.FRAMING_ERROR, - "no method segment"); - ssn.close(); - return; - } - - props = header.get(DeliveryProperties.class); - if (props != null) - { - System.out.println("received headers routing_key " + props.getRoutingKey()); - } - MessageProperties mp = header.get(MessageProperties.class); - System.out.println("MP: " + mp); - if (mp != null) - { - System.out.println(mp.getApplicationHeaders()); - } - - this.header = header; - } - - @Override public void data(Session ssn, Data data) - { - if (xfr == null || body == null) - { - ssn.connectionClose(ConnectionCloseCode.FRAMING_ERROR, "no method segment"); - ssn.close(); - return; - } - - body.add(data); - - if (data.isLast()) - { - String dest = xfr.getDestination(); - Message m = new Message(header, body); - - if (exchange.route(dest,props.getRoutingKey(),m)) - { - System.out.println("queued " + m); - dispatchMessages(ssn); - } - else - { - - reject(ssn); - } - ssn.processed(xfr); - xfr = null; - body = null; - } - } - - private void reject(Session ssn) - { - if (props != null && props.getDiscardUnroutable()) - { - return; - } - else - { - RangeSet ranges = new RangeSet(); - ranges.add(xfr.getId()); - ssn.messageReject(ranges, MessageRejectCode.UNROUTABLE, - "no such destination"); - } - } - - private void transferMessageToPeer(Session ssn,String dest, Message m) - { - System.out.println("\n==================> Transfering message to: " +dest + "\n"); - ssn.messageTransfer(dest, MessageAcceptMode.EXPLICIT, - MessageAcquireMode.PRE_ACQUIRED); - ssn.header(m.header); - for (Data d : m.body) - { - for (ByteBuffer b : d.getFragments()) - { - ssn.data(b); - } - } - ssn.endData(); - } - - private void dispatchMessages(Session ssn) - { - for (String dest: consumers.keySet()) - { - checkAndSendMessagesToConsumer(ssn,dest); - } - } - - private void checkAndSendMessagesToConsumer(Session ssn,String dest) - { - Consumer c = consumers.get(dest); - LinkedBlockingQueue queue = exchange.getQueue(c._queueName); - Message m = queue.poll(); - while (m != null && c._credit>0) - { - transferMessageToPeer(ssn,dest,m); - c._credit--; - m = queue.poll(); - } - } - - class Message - { - private final Header header; - private final List body; - - public Message(Header header, List body) - { - this.header = header; - this.body = body; - } - - public String toString() - { - StringBuilder sb = new StringBuilder(); - - if (header != null) - { - boolean first = true; - for (Struct st : header.getStructs()) - { - if (first) { first = false; } - else { sb.append(" "); } - sb.append(st); - } - } - - for (Data d : body) - { - for (ByteBuffer b : d.getFragments()) - { - sb.append(" | "); - sb.append(str(b)); - } - } - - return sb.toString(); - } - - } - - // ugly, but who cares :) - // assumes unit is always no of messages, not bytes - // assumes it's credit mode and not window - private class Consumer - { - long _credit; - String _queueName; - } - - public static final void main(String[] args) throws IOException - { - final ToyExchange exchange = new ToyExchange(); - ConnectionDelegate delegate = new ConnectionDelegate() - { - public SessionDelegate getSessionDelegate() - { - return new ToyBroker(exchange); - } - public void exception(Throwable t) - { - t.printStackTrace(); - } - public void closed() {} - }; - - //hack - delegate.setUsername("guest"); - delegate.setPassword("guest"); - - MinaHandler.accept("0.0.0.0", 5672, delegate); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/ToyClient.java b/java/common/src/main/java/org/apache/qpidity/ToyClient.java deleted file mode 100644 index a3233afcbe..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/ToyClient.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity; - -import java.util.*; - -import org.apache.qpidity.transport.*; -import org.apache.qpidity.transport.network.mina.MinaHandler; - - -/** - * ToyClient - * - * @author Rafael H. Schloming - */ - -class ToyClient extends SessionDelegate -{ - - @Override public void messageReject(Session ssn, MessageReject reject) - { - for (Range range : reject.getTransfers()) - { - for (long l = range.getLower(); l <= range.getUpper(); l++) - { - System.out.println("message rejected: " + - ssn.getCommand((int) l)); - } - } - } - - @Override public void header(Session ssn, Header header) - { - for (Struct st : header.getStructs()) - { - System.out.println("header: " + st); - } - } - - @Override public void data(Session ssn, Data data) - { - System.out.println("got data: " + data); - } - - public static final void main(String[] args) - { - Connection conn = MinaHandler.connect("0.0.0.0", 5672, - new ClientDelegate() - { - public SessionDelegate getSessionDelegate() - { - return new ToyClient(); - } - public void exception(Throwable t) - { - t.printStackTrace(); - } - public void closed() {} - }); - conn.send(new ConnectionEvent(0, new ProtocolHeader(1, - TransportConstants.getVersionMajor(), - TransportConstants.getVersionMinor()))); - - Channel ch = conn.getChannel(0); - Session ssn = new Session("my-session".getBytes()); - ssn.attach(ch); - ssn.sessionAttach(ssn.getName()); - - ssn.queueDeclare("asdf", null, null); - ssn.sync(); - - Map nested = new LinkedHashMap(); - nested.put("list", Arrays.asList("one", "two", "three")); - Map map = new LinkedHashMap(); - - map.put("str", "this is a string"); - - map.put("+int", 3); - map.put("-int", -3); - map.put("maxint", Integer.MAX_VALUE); - map.put("minint", Integer.MIN_VALUE); - - map.put("+short", (short) 1); - map.put("-short", (short) -1); - map.put("maxshort", (short) Short.MAX_VALUE); - map.put("minshort", (short) Short.MIN_VALUE); - - map.put("float", (float) 3.3); - map.put("double", 4.9); - map.put("char", 'c'); - - map.put("table", nested); - map.put("list", Arrays.asList(1, 2, 3)); - map.put("binary", new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); - - ssn.messageTransfer("asdf", MessageAcceptMode.EXPLICIT, - MessageAcquireMode.PRE_ACQUIRED); - ssn.header(new DeliveryProperties(), - new MessageProperties().setApplicationHeaders(map)); - ssn.data("this is the data"); - ssn.endData(); - - ssn.messageTransfer("fdsa", MessageAcceptMode.EXPLICIT, - MessageAcquireMode.PRE_ACQUIRED); - ssn.data("this should be rejected"); - ssn.endData(); - ssn.sync(); - - Future future = ssn.queueQuery("asdf"); - System.out.println(future.get().getQueue()); - ssn.sync(); - ssn.close(); - conn.close(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/ToyExchange.java b/java/common/src/main/java/org/apache/qpidity/ToyExchange.java deleted file mode 100644 index eab5f6c078..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/ToyExchange.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.apache.qpidity; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.apache.qpidity.ToyBroker.Message; - -public class ToyExchange -{ - final static String DIRECT = "amq.direct"; - final static String TOPIC = "amq.topic"; - - private Map>> directEx = new HashMap>>(); - private Map>> topicEx = new HashMap>>(); - private Map> queues = new HashMap>(); - - public void createQueue(String name) - { - queues.put(name, new LinkedBlockingQueue()); - } - - public LinkedBlockingQueue getQueue(String name) - { - return queues.get(name); - } - - public void bindQueue(String type,String binding,String queueName) - { - LinkedBlockingQueue queue = queues.get(queueName); - binding = normalizeKey(binding); - if(DIRECT.equals(type)) - { - - if (directEx.containsKey(binding)) - { - List> list = directEx.get(binding); - list.add(queue); - } - else - { - List> list = new LinkedList>(); - list.add(queue); - directEx.put(binding,list); - } - } - else - { - if (topicEx.containsKey(binding)) - { - List> list = topicEx.get(binding); - list.add(queue); - } - else - { - List> list = new LinkedList>(); - list.add(queue); - topicEx.put(binding,list); - } - } - } - - public boolean route(String dest,String routingKey,Message msg) - { - List> queues; - if(DIRECT.equals(dest)) - { - queues = directEx.get(routingKey); - } - else - { - queues = matchWildCard(routingKey); - } - if(queues != null && queues.size()>0) - { - System.out.println("Message stored in " + queues.size() + " queues"); - storeMessage(msg,queues); - return true; - } - else - { - System.out.println("Message unroutable " + msg); - return false; - } - } - - private String normalizeKey(String routingKey) - { - if(routingKey.indexOf(".*")>1) - { - return routingKey.substring(0,routingKey.indexOf(".*")); - } - else - { - return routingKey; - } - } - - private List> matchWildCard(String routingKey) - { - List> selected = new ArrayList>(); - - for(String key: topicEx.keySet()) - { - Pattern p = Pattern.compile(key); - Matcher m = p.matcher(routingKey); - if (m.find()) - { - for(LinkedBlockingQueue queue : topicEx.get(key)) - { - selected.add(queue); - } - } - } - - return selected; - } - - private void storeMessage(Message msg,List> selected) - { - for(LinkedBlockingQueue queue : selected) - { - queue.offer(msg); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/api/Message.java b/java/common/src/main/java/org/apache/qpidity/api/Message.java deleted file mode 100644 index f5488fde52..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/api/Message.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.apache.qpidity.api; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import org.apache.qpidity.transport.MessageProperties; -import org.apache.qpidity.transport.DeliveryProperties; -import org.apache.qpidity.transport.Header; - -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT 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 interface Message -{ - public Header getHeader(); - - public void setHeader(Header header); - - public MessageProperties getMessageProperties(); - - public DeliveryProperties getDeliveryProperties(); - - /** - * This will abstract the underlying message data. - * The Message implementation may not hold all message - * data in memory (especially in the case of large messages) - * - * The appendData function might write data to - *
    - *
  • Memory (Ex: ByteBuffer) - *
  • To Disk - *
  • To Socket (Stream) - *
- * @param src - the data to append - */ - public void appendData(byte[] src) throws IOException; - - - /** - * This will abstract the underlying message data. - * The Message implementation may not hold all message - * data in memory (especially in the case of large messages) - * - * The appendData function might write data to - *
    - *
  • Memory (Ex: ByteBuffer) - *
  • To Disk - *
  • To Socket (Stream) - *
- * @param src - the data to append - */ - public void appendData(ByteBuffer src) throws IOException; - - /** - * This will abstract the underlying message data. - * The Message implementation may not hold all message - * data in memory (especially in the case of large messages) - * - * The read function might copy data from - *
    - *
  • From memory (Ex: ByteBuffer) - *
  • From Disk - *
  • From Socket as and when it gets streamed - *
- * @param target The target byte[] which the data gets copied to - */ - public void readData(byte[] target) throws IOException; - - /** - * * This will abstract the underlying message data. - * The Message implementation may not hold all message - * data in memory (especially in the case of large messages) - * - * The read function might copy data from - *
    - *
  • From memory (Ex: ByteBuffer) - *
  • From Disk - *
  • From Socket as and when it gets streamed - *
- * - * @return A ByteBuffer containing data - * @throws IOException - */ - public ByteBuffer readData() throws IOException; - - /** - * This should clear the body of the message. - */ - public void clearData(); - - /** - * The provides access to the command Id assigned to the - * message transfer. - * This id is useful when you do - *
    - *
  • For message acquiring - If the transfer happend in no-acquire mode - * you could use this id to accquire it. - *
  • For releasing a message. You can use this id to release an acquired - * message - *
  • For Acknowledging a message - You need to pass this ID, in order to - * acknowledge the message - *
  • For Rejecting a message - You need to pass this ID, in order to reject - * the message. - *
- * - * @return the message transfer id. - */ - public int getMessageTransferId(); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java b/java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java deleted file mode 100644 index 89d7e7917f..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java +++ /dev/null @@ -1,250 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.dtx; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.qpidity.QpidException; - -import javax.transaction.xa.Xid; - -import java.io.*; - -/** - * Implements javax.transaction.dtx.Xid - */ -public class XidImpl implements Xid -{ - /** - * this session's logger - */ - private static final Logger _logger = LoggerFactory.getLogger(XidImpl.class); - - /** - * the transaction branch identifier part of XID as an array of bytes - */ - private byte[] _branchQualifier; - - /** - * the format identifier part of the XID. - */ - private int _formatID; - - /** - * the global transaction identifier part of XID as an array of bytes. - */ - private byte[] _globalTransactionID; - - //--- Constructors - - /** - * Create new Xid. - * this is an empty constructor. - */ - public XidImpl() - { - - } - - /** - * Create a new XidImpl from an existing Xid. - *

Usefull for casting external Xids - * - * @param xid Foreign Xid. - */ - public XidImpl(Xid xid) - { - _branchQualifier = xid.getBranchQualifier(); - _formatID = xid.getFormatId(); - _globalTransactionID = xid.getGlobalTransactionId(); - } - - /** - * Create a new Xid. - * - * @param branchQualifier The transaction branch identifier part of XID as an array of bytes. - * @param format The format identifier part of the XID. - * @param globalTransactionID The global transaction identifier part of XID as an array of bytes. - */ - public XidImpl(byte[] branchQualifier, int format, byte[] globalTransactionID) - { - _branchQualifier = branchQualifier; - _formatID = format; - _globalTransactionID = globalTransactionID; - } - - /** - * Create a new Xid form its String form - * 4 1 1 g b - * +---+---+---+---+---+---+---+- -+---+---+- -+---+ - * | format_id | g | b | txn-id | br-id | - * +---+---+---+---+---+---+---+- -+---+---+- -+---+ - * 0 4 5 6 6+g 6+g+b - * format_id: an implementation specific format identifier - *

- * gtrid_length: how many bytes of this form the transaction id - *

- * bqual_length: how many bytes of this form the branch id - *

- * data: a sequence of octets of at most 128 bytes containing the txn id and the - * branch id - *

- * Note - The sum of the two lengths must equal the length of the data field. - * - * @param xid an XID STring Form - * @throws QpidException If the string does not represent a valid Xid - */ - public XidImpl(String xid) throws QpidException - { - if (_logger.isDebugEnabled()) - { - _logger.debug("converting string " + xid + " into XidImpl"); - } - try - { - DataInputStream input = new DataInputStream(new ByteArrayInputStream(xid.getBytes())); - _formatID = (int) input.readLong(); - int g = input.readByte(); - int b = input.readByte(); - _globalTransactionID = new byte[g]; - _branchQualifier = new byte[b]; - if (input.read(_globalTransactionID, 0, g) != g) - { - throw new QpidException("Cannot convert the string " + xid + " into an Xid", null, null); - } - if (input.read(_branchQualifier, 0, b) != b) - { - throw new QpidException("Cannot convert the string " + xid + " into an Xid", null, null); - } - } - catch (IOException e) - { - throw new QpidException("cannot convert the string " + xid + " into an Xid", null, e); - } - } - - //--- Xid interface implementation - - /** - * Format identifier. O means the OSI CCR format. - * - * @return Global transaction identifier. - */ - public byte[] getGlobalTransactionId() - { - return _globalTransactionID; - } - - /** - * Obtain the transaction branch identifier part of XID as an array of bytes. - * - * @return Branch identifier part of XID. - */ - public byte[] getBranchQualifier() - { - return _branchQualifier; - } - - /** - * Obtain the format identifier part of the XID. - * - * @return Format identifier. O means the OSI CCR format. - */ - public int getFormatId() - { - return _formatID; - } - - //--- Object operations - - /** - * Indicates whether some other Xid is "equal to" this one. - *

Two Xids are equal if and only if their three elementary parts are equal - * - * @param o the object to compare this XidImpl against. - * @return true if the XidImpl are equal, false otherwise. - */ - public boolean equals(Object o) - { - if (this == o) - { - return true; - } - if (o instanceof XidImpl) - { - XidImpl other = (XidImpl) o; - if (_formatID == other.getFormatId()) - { - if (_branchQualifier.length == other.getBranchQualifier().length) - { - for (int i = 0; i < _branchQualifier.length; i++) - { - if (_branchQualifier[i] != other.getBranchQualifier()[i]) - { - return false; - } - } - if (_globalTransactionID.length == other.getGlobalTransactionId().length) - { - for (int i = 0; i < _globalTransactionID.length; i++) - { - if (_globalTransactionID[i] != other.getGlobalTransactionId()[i]) - { - return false; - } - } - // everithing is equal - return true; - } - } - } - } - return false; - } - - //-- Static helper method - /** - * Convert an Xid into the AMQP String format. - * - * 4 1 1 g b - * +---+---+---+---+---+---+---+- -+---+---+- -+---+ - * | format_id | g | b | txn-id | br-id | - * +---+---+---+---+---+---+---+- -+---+---+- -+---+ - * 0 4 5 6 6+g 6+g+b - * format_id: an implementation specific format identifier - *

- * gtrid_length: how many bytes of this form the transaction id - *

- * bqual_length: how many bytes of this form the branch id - *

- * data: a sequence of octets of at most 128 bytes containing the txn id and the - * branch id - *

- * Note - The sum of the two lengths must equal the length of the data field. - * - * @param xid an Xid to convert. - * @return The String representation of this Xid - * @throws QpidException In case of problem when converting this Xid into a string. - */ - public static org.apache.qpidity.transport.Xid convert(Xid xid) throws QpidException - { - return new org.apache.qpidity.transport.Xid(xid.getFormatId(), - xid.getGlobalTransactionId(), - xid.getBranchQualifier()); - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/exchange/ExchangeDefaults.java b/java/common/src/main/java/org/apache/qpidity/exchange/ExchangeDefaults.java deleted file mode 100644 index a99ea56d69..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/exchange/ExchangeDefaults.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.qpidity.exchange; - -/** - * Default exchange names - */ -public class ExchangeDefaults -{ - /** The default direct exchange, which is a special internal exchange that cannot be explicitly bound to. */ - public static final String DEFAULT_EXCHANGE_NAME = "<>"; - - /** The pre-defined topic exchange, the broker SHOULD provide this. */ - public static final String TOPIC_EXCHANGE_NAME = "amq.topic"; - - /** Defines the identifying type name of topic exchanges. */ - public static final String TOPIC_EXCHANGE_CLASS = "topic"; - - /** The pre-defined direct exchange, the broker MUST provide this. */ - public static final String DIRECT_EXCHANGE_NAME = "amq.direct"; - - /** Defines the identifying type name of direct exchanges. */ - public static final String DIRECT_EXCHANGE_CLASS = "direct"; - - /** The pre-defined headers exchange, the specification does not say this needs to be provided. */ - public static final String HEADERS_EXCHANGE_NAME = "amq.match"; - - /** Defines the identifying type name of headers exchanges. */ - public static final String HEADERS_EXCHANGE_CLASS = "headers"; - - /** The pre-defined fanout exchange, the boker MUST provide this. */ - public static final String FANOUT_EXCHANGE_NAME = "amq.fanout"; - - /** Defines the identifying type name of fanout exchanges. */ - public static final String FANOUT_EXCHANGE_CLASS = "fanout"; -} diff --git a/java/common/src/main/java/org/apache/qpidity/security/AMQPCallbackHandler.java b/java/common/src/main/java/org/apache/qpidity/security/AMQPCallbackHandler.java deleted file mode 100644 index 2e7afa1b87..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/security/AMQPCallbackHandler.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.security; - -import javax.security.auth.callback.CallbackHandler; - -public interface AMQPCallbackHandler extends CallbackHandler -{ - void initialise(String username,String password); -} diff --git a/java/common/src/main/java/org/apache/qpidity/security/CallbackHandlerRegistry.java b/java/common/src/main/java/org/apache/qpidity/security/CallbackHandlerRegistry.java deleted file mode 100644 index b23fea7e4a..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/security/CallbackHandlerRegistry.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.security; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.qpidity.QpidConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class CallbackHandlerRegistry -{ - private static final Logger _logger = LoggerFactory.getLogger(CallbackHandlerRegistry.class); - private static CallbackHandlerRegistry _instance = new CallbackHandlerRegistry(); - - private Map _mechanismToHandlerClassMap = new HashMap(); - - private StringBuilder _mechanisms; - - public static CallbackHandlerRegistry getInstance() - { - return _instance; - } - - public Class getCallbackHandlerClass(String mechanism) - { - return _mechanismToHandlerClassMap.get(mechanism); - } - - public String getMechanisms() - { - return _mechanisms.toString(); - } - - private CallbackHandlerRegistry() - { - // first we register any Sasl client factories - DynamicSaslRegistrar.registerSaslProviders(); - registerMechanisms(); - } - - private void registerMechanisms() - { - for (QpidConfig.SecurityMechanism securityMechanism: QpidConfig.get().getSecurityMechanisms() ) - { - Class clazz = null; - try - { - clazz = Class.forName(securityMechanism.getHandler()); - if (!AMQPCallbackHandler.class.isAssignableFrom(clazz)) - { - _logger.debug("SASL provider " + clazz + " does not implement " + AMQPCallbackHandler.class + - ". Skipping"); - continue; - } - _mechanismToHandlerClassMap.put(securityMechanism.getType(), clazz); - if (_mechanisms == null) - { - - _mechanisms = new StringBuilder(); - _mechanisms.append(securityMechanism.getType()); - } - else - { - _mechanisms.append(" " + securityMechanism.getType()); - } - } - catch (ClassNotFoundException ex) - { - _logger.debug("Unable to load class " + securityMechanism.getHandler() + ". Skipping that SASL provider"); - continue; - } - } - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/security/DynamicSaslRegistrar.java b/java/common/src/main/java/org/apache/qpidity/security/DynamicSaslRegistrar.java deleted file mode 100644 index 1798f0c210..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/security/DynamicSaslRegistrar.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.qpidity.security; - -import java.security.Security; -import java.util.Map; -import java.util.TreeMap; - -import javax.security.sasl.SaslClientFactory; - -import org.apache.qpidity.QpidConfig; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DynamicSaslRegistrar -{ - private static final Logger _logger = LoggerFactory.getLogger(DynamicSaslRegistrar.class); - - public static void registerSaslProviders() - { - Map factories = registerSaslClientFactories(); - if (factories.size() > 0) - { - Security.addProvider(new JCAProvider(factories)); - _logger.debug("Dynamic SASL provider added as a security provider"); - } - } - - private static Map registerSaslClientFactories() - { - TreeMap factoriesToRegister = - new TreeMap(); - - for (QpidConfig.SaslClientFactory factory: QpidConfig.get().getSaslClientFactories()) - { - String className = factory.getFactoryClass(); - try - { - Class clazz = Class.forName(className); - if (!(SaslClientFactory.class.isAssignableFrom(clazz))) - { - _logger.debug("Class " + clazz + " does not implement " + SaslClientFactory.class + " - skipping"); - continue; - } - factoriesToRegister.put(factory.getType(), clazz); - } - catch (Exception ex) - { - _logger.debug("Error instantiating SaslClientFactory calss " + className + " - skipping"); - } - } - return factoriesToRegister; - } - - -} diff --git a/java/common/src/main/java/org/apache/qpidity/security/JCAProvider.java b/java/common/src/main/java/org/apache/qpidity/security/JCAProvider.java deleted file mode 100644 index c775171a5f..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/security/JCAProvider.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.security; - -import java.security.Provider; -import java.security.Security; -import java.util.Map; - -public class JCAProvider extends Provider -{ - public JCAProvider(Map providerMap) - { - super("AMQSASLProvider", 1.0, "A JCA provider that registers all " + - "AMQ SASL providers that want to be registered"); - register(providerMap); - Security.addProvider(this); - } - - private void register(Map providerMap) - { - for (Map.Entry me :providerMap.entrySet()) - { - put("SaslClientFactory." + me.getKey(), me.getValue().getName()); - } - } -} \ No newline at end of file diff --git a/java/common/src/main/java/org/apache/qpidity/security/UsernamePasswordCallbackHandler.java b/java/common/src/main/java/org/apache/qpidity/security/UsernamePasswordCallbackHandler.java deleted file mode 100644 index 0fd647e015..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/security/UsernamePasswordCallbackHandler.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.qpidity.security; - -import java.io.IOException; - -import javax.security.auth.callback.Callback; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.UnsupportedCallbackException; - -public class UsernamePasswordCallbackHandler implements AMQPCallbackHandler -{ - private String _username; - private String _password; - - public void initialise(String username,String password) - { - _username = username; - _password = password; - } - - public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException - { - for (int i = 0; i < callbacks.length; i++) - { - Callback cb = callbacks[i]; - if (cb instanceof NameCallback) - { - ((NameCallback)cb).setName(_username); - } - else if (cb instanceof PasswordCallback) - { - ((PasswordCallback)cb).setPassword((_password).toCharArray()); - } - else - { - throw new UnsupportedCallbackException(cb); - } - } - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClient.java b/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClient.java deleted file mode 100644 index 6e4a0218d2..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClient.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.security.amqplain; - -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.FieldTableFactory; - -import javax.security.sasl.SaslClient; -import javax.security.sasl.SaslException; -import javax.security.auth.callback.CallbackHandler; -import javax.security.auth.callback.NameCallback; -import javax.security.auth.callback.PasswordCallback; -import javax.security.auth.callback.Callback; - -/** - * Implements the "AMQPlain" authentication protocol that uses FieldTables to send username and pwd. - * - */ -public class AmqPlainSaslClient implements SaslClient -{ - /** - * The name of this mechanism - */ - public static final String MECHANISM = "AMQPLAIN"; - - private CallbackHandler _cbh; - - public AmqPlainSaslClient(CallbackHandler cbh) - { - _cbh = cbh; - } - - public String getMechanismName() - { - return "AMQPLAIN"; - } - - public boolean hasInitialResponse() - { - return true; - } - - public byte[] evaluateChallenge(byte[] challenge) throws SaslException - { - // we do not care about the prompt or the default name - NameCallback nameCallback = new NameCallback("prompt", "defaultName"); - PasswordCallback pwdCallback = new PasswordCallback("prompt", false); - Callback[] callbacks = new Callback[]{nameCallback, pwdCallback}; - try - { - _cbh.handle(callbacks); - } - catch (Exception e) - { - throw new SaslException("Error handling SASL callbacks: " + e, e); - } - FieldTable table = FieldTableFactory.newFieldTable(); - table.setString("LOGIN", nameCallback.getName()); - table.setString("PASSWORD", new String(pwdCallback.getPassword())); - return table.getDataAsBytes(); - } - - public boolean isComplete() - { - return true; - } - - public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException - { - throw new SaslException("Not supported"); - } - - public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException - { - throw new SaslException("Not supported"); - } - - public Object getNegotiatedProperty(String propName) - { - return null; - } - - public void dispose() throws SaslException - { - _cbh = null; - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClientFactory.java b/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClientFactory.java deleted file mode 100644 index abc881f433..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/security/amqplain/AmqPlainSaslClientFactory.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.security.amqplain; - -import javax.security.sasl.SaslClientFactory; -import javax.security.sasl.SaslClient; -import javax.security.sasl.SaslException; -import javax.security.sasl.Sasl; -import javax.security.auth.callback.CallbackHandler; -import java.util.Map; - -public class AmqPlainSaslClientFactory implements SaslClientFactory -{ - public SaslClient createSaslClient(String[] mechanisms, String authorizationId, String protocol, String serverName, Map props, CallbackHandler cbh) throws SaslException - { - for (int i = 0; i < mechanisms.length; i++) - { - if (mechanisms[i].equals(AmqPlainSaslClient.MECHANISM)) - { - if (cbh == null) - { - throw new SaslException("CallbackHandler must not be null"); - } - return new AmqPlainSaslClient(cbh); - } - } - return null; - } - - public String[] getMechanismNames(Map props) - { - if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) || - props.containsKey(Sasl.POLICY_NODICTIONARY) || - props.containsKey(Sasl.POLICY_NOACTIVE)) - { - // returned array must be non null according to interface documentation - return new String[0]; - } - else - { - return new String[]{AmqPlainSaslClient.MECHANISM}; - } - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Binding.java b/java/common/src/main/java/org/apache/qpidity/transport/Binding.java deleted file mode 100644 index 18ed97098d..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Binding.java +++ /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. - * - */ -package org.apache.qpidity.transport; - - -/** - * Binding - * - */ - -public interface Binding -{ - - E endpoint(Sender sender); - - Receiver receiver(E endpoint); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Channel.java b/java/common/src/main/java/org/apache/qpidity/transport/Channel.java deleted file mode 100644 index fb8918eb7b..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Channel.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.qpidity.transport; - -import org.apache.qpidity.transport.network.Frame; -import org.apache.qpidity.transport.util.Logger; - -import java.nio.ByteBuffer; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import static org.apache.qpidity.transport.network.Frame.*; -import static org.apache.qpidity.transport.util.Functions.*; - - -/** - * Channel - * - * @author Rafael H. Schloming - */ - -public class Channel extends Invoker - implements Receiver, ProtocolDelegate -{ - - private static final Logger log = Logger.get(Channel.class); - - final private Connection connection; - final private int channel; - final private MethodDelegate delegate; - final private SessionDelegate sessionDelegate; - // session may be null - private Session session; - - private Lock commandLock = new ReentrantLock(); - private boolean first = true; - private ByteBuffer data = null; - - public Channel(Connection connection, int channel, SessionDelegate delegate) - { - this.connection = connection; - this.channel = channel; - this.delegate = new ChannelDelegate(); - this.sessionDelegate = delegate; - } - - public Connection getConnection() - { - return connection; - } - - public void received(ProtocolEvent event) - { - event.delegate(null, this); - } - - public void init(Void v, ProtocolHeader hdr) - { - connection.getConnectionDelegate().init(this, hdr); - } - - public void control(Void v, Method method) - { - switch (method.getEncodedTrack()) - { - case L1: - method.dispatch(this, connection.getConnectionDelegate()); - break; - case L2: - method.dispatch(this, delegate); - break; - case L3: - method.delegate(session, sessionDelegate); - break; - default: - throw new IllegalStateException - ("unknown track: " + method.getEncodedTrack()); - } - } - - public void command(Void v, Method method) - { - method.delegate(session, sessionDelegate); - } - - public void header(Void v, Header header) - { - header.delegate(session, sessionDelegate); - } - - public void data(Void v, Data data) - { - data.delegate(session, sessionDelegate); - } - - public void error(Void v, ProtocolError error) - { - throw new RuntimeException(error.getMessage()); - } - - public void exception(Throwable t) - { - session.exception(t); - } - - public void closed() - { - log.debug("channel closed: ", this); - if (session != null) - { - session.closed(); - } - connection.removeChannel(channel); - } - - public int getEncodedChannel() { - return channel; - } - - public Session getSession() - { - return session; - } - - void setSession(Session session) - { - this.session = session; - } - - private void emit(ProtocolEvent event) - { - connection.send(new ConnectionEvent(channel, event)); - } - - public void method(Method m) - { - if (m.getEncodedTrack() == Frame.L4) - { - commandLock.lock(); - } - - emit(m); - - if (m.getEncodedTrack() == Frame.L4 && !m.hasPayload()) - { - commandLock.unlock(); - } - } - - public void header(Header header) - { - emit(header); - } - - public void data(ByteBuffer buf) - { - if (data != null) - { - emit(new Data(data, first, false)); - first = false; - } - - data = buf; - } - - public void data(String str) - { - data(str.getBytes()); - } - - public void data(byte[] bytes) - { - data(ByteBuffer.wrap(bytes)); - } - - public void end() - { - emit(new Data(data, first, true)); - first = true; - data = null; - commandLock.unlock(); - } - - protected void invoke(Method m) - { - method(m); - } - - protected Future invoke(Method m, Class cls) - { - throw new UnsupportedOperationException(); - } - - public String toString() - { - return String.format("%s:%s", connection, channel); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.java b/java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.java deleted file mode 100644 index 96578ffeb8..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.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.qpidity.transport; - -import java.util.UUID; - - -/** - * ChannelDelegate - * - * @author Rafael H. Schloming - */ - -class ChannelDelegate extends MethodDelegate -{ - - public @Override void sessionAttach(Channel channel, SessionAttach atch) - { - Session ssn = new Session(atch.getName()); - ssn.attach(channel); - ssn.sessionAttached(ssn.getName()); - } - - public @Override void sessionDetached(Channel channel, SessionDetached closed) - { - channel.closed(); - } - - public @Override void sessionDetach(Channel channel, SessionDetach dtc) - { - channel.getSession().closed(); - channel.sessionDetached(dtc.getName(), SessionDetachCode.NORMAL); - channel.closed(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java b/java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java deleted file mode 100644 index 699854fb3b..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - - -/** - * ClientDelegate - * - */ - -public abstract class ClientDelegate extends ConnectionDelegate -{ - - public void init(Channel ch, ProtocolHeader hdr) - { - if (hdr.getMajor() != TransportConstants.getVersionMajor() && - hdr.getMinor() != TransportConstants.getVersionMinor()) - { - throw new RuntimeException("version missmatch: " + hdr); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Connection.java b/java/common/src/main/java/org/apache/qpidity/transport/Connection.java deleted file mode 100644 index 9829343491..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Connection.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import org.apache.qpidity.transport.util.Logger; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import java.nio.ByteBuffer; - - -/** - * Connection - * - * @author Rafael H. Schloming - * - * @todo the channels map should probably be replaced with something - * more efficient, e.g. an array or a map implementation that can use - * short instead of Short - */ - -// RA making this public until we sort out the package issues -public class Connection - implements Receiver, Sender -{ - - private static final Logger log = Logger.get(Connection.class); - - final private Sender sender; - final private ConnectionDelegate delegate; - private int channelMax = 1; - // want to make this final - private int _connectionId; - - final private Map channels = new HashMap(); - - public Connection(Sender sender, - ConnectionDelegate delegate) - { - this.sender = sender; - this.delegate = delegate; - } - - public void setConnectionId(int id) - { - _connectionId = id; - } - - public int getConnectionId() - { - return _connectionId; - } - - public ConnectionDelegate getConnectionDelegate() - { - return delegate; - } - - public void received(ConnectionEvent event) - { - log.debug("RECV: [%s] %s", this, event); - Channel channel = getChannel(event.getChannel()); - channel.received(event.getProtocolEvent()); - } - - public void send(ConnectionEvent event) - { - log.debug("SEND: [%s] %s", this, event); - sender.send(event); - } - - public int getChannelMax() - { - return channelMax; - } - - void setChannelMax(int max) - { - channelMax = max; - } - - public Channel getChannel() - { - synchronized (channels) - { - for (int i = 0; i < getChannelMax(); i++) - { - if (!channels.containsKey(i)) - { - return getChannel(i); - } - } - - throw new RuntimeException("no more channels available"); - } - } - - public Channel getChannel(int number) - { - synchronized (channels) - { - Channel channel = channels.get(number); - if (channel == null) - { - channel = new Channel(this, number, delegate.getSessionDelegate()); - channels.put(number, channel); - } - return channel; - } - } - - void removeChannel(int number) - { - synchronized (channels) - { - channels.remove(number); - } - } - - public void exception(Throwable t) - { - delegate.exception(t); - } - - public void closed() - { - log.debug("connection closed: %s", this); - synchronized (channels) - { - List values = new ArrayList(channels.values()); - for (Channel ch : values) - { - ch.closed(); - } - } - delegate.closed(); - } - - public void close() - { - sender.close(); - } - - public String toString() - { - return String.format("conn:%x", System.identityHashCode(this)); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java b/java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java deleted file mode 100644 index 14344991c6..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java +++ /dev/null @@ -1,301 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import org.apache.qpidity.transport.util.Logger; - -import org.apache.qpidity.SecurityHelper; -import org.apache.qpidity.QpidException; - -import java.io.UnsupportedEncodingException; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; - -import javax.security.sasl.Sasl; -import javax.security.sasl.SaslClient; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; - - -/** - * ConnectionDelegate - * - * @author Rafael H. Schloming - */ - -/** - * Currently only implemented client specific methods - * the server specific methods are dummy impls for testing - * - * the connectionClose is kind of different for both sides - */ -public abstract class ConnectionDelegate extends MethodDelegate -{ - - private static final Logger log = Logger.get(ConnectionDelegate.class); - - private String _username = "guest"; - private String _password = "guest";; - private String _mechanism; - private String _virtualHost; - private SaslClient saslClient; - private SaslServer saslServer; - private String _locale = "utf8"; - private int maxFrame = 64*1024; - private Condition _negotiationComplete; - private Lock _negotiationCompleteLock; - - public abstract SessionDelegate getSessionDelegate(); - - public abstract void exception(Throwable t); - - public abstract void closed(); - - public void setCondition(Lock negotiationCompleteLock,Condition negotiationComplete) - { - _negotiationComplete = negotiationComplete; - _negotiationCompleteLock = negotiationCompleteLock; - } - - public void init(Channel ch, ProtocolHeader hdr) - { - ch.getConnection().send(new ConnectionEvent(0, new ProtocolHeader - (1, - TransportConstants.getVersionMajor(), - TransportConstants.getVersionMinor()))); - if (hdr.getMajor() != TransportConstants.getVersionMajor() && - hdr.getMinor() != TransportConstants.getVersionMinor()) - { - // XXX - ch.getConnection().send(new ConnectionEvent(0, new ProtocolHeader - (1, - TransportConstants.getVersionMajor(), - TransportConstants.getVersionMinor()))); - ch.getConnection().close(); - } - else - { - List plain = new ArrayList(); - plain.add("PLAIN"); - List utf8 = new ArrayList(); - utf8.add("utf8"); - ch.connectionStart(null, plain, utf8); - } - } - - // ---------------------------------------------- - // Client side - //----------------------------------------------- - @Override public void connectionStart(Channel context, ConnectionStart struct) - { - String mechanism = null; - byte[] response = null; - try - { - mechanism = SecurityHelper.chooseMechanism(struct.getMechanisms()); - saslClient = Sasl.createSaslClient(new String[]{ mechanism },null, "AMQP", "localhost", null, - SecurityHelper.createCallbackHandler(mechanism,_username,_password )); - response = saslClient.evaluateChallenge(new byte[0]); - } - catch (UnsupportedEncodingException e) - { - // need error handling - } - catch (SaslException e) - { - // need error handling - } - catch (QpidException e) - { - // need error handling - } - - Map props = new HashMap(); - context.connectionStartOk(props, mechanism, response, _locale); - } - - @Override public void connectionSecure(Channel context, ConnectionSecure struct) - { - try - { - byte[] response = saslClient.evaluateChallenge(struct.getChallenge()); - context.connectionSecureOk(response); - } - catch (SaslException e) - { - // need error handling - } - } - - @Override public void connectionTune(Channel context, ConnectionTune struct) - { - context.getConnection().setChannelMax(struct.getChannelMax()); - context.connectionTuneOk(struct.getChannelMax(), struct.getMaxFrameSize(), struct.getHeartbeatMax()); - context.connectionOpen(_virtualHost, null, Option.INSIST); - } - - - @Override public void connectionOpenOk(Channel context, ConnectionOpenOk struct) - { - List knownHosts = struct.getKnownHosts(); - if(_negotiationCompleteLock != null) - { - _negotiationCompleteLock.lock(); - try - { - _negotiationComplete.signalAll(); - } - finally - { - _negotiationCompleteLock.unlock(); - } - } - } - - public void connectionRedirect(Channel context, ConnectionRedirect struct) - { - // not going to bother at the moment - } - - // ---------------------------------------------- - // Server side - //----------------------------------------------- - @Override public void connectionStartOk(Channel context, ConnectionStartOk struct) - { - //set the client side locale on the server side - _locale = struct.getLocale(); - _mechanism = struct.getMechanism(); - - //try - //{ - //saslServer = Sasl.createSaslServer(_mechanism, "AMQP", "ABC",null,SecurityHelper.createCallbackHandler(_mechanism,_username,_password)); - //byte[] challenge = saslServer.evaluateResponse(struct.getResponse().getBytes()); - byte[] challenge = null; - if ( challenge == null) - { - context.connectionTune(Integer.MAX_VALUE, maxFrame, 0, Integer.MAX_VALUE); - } - else - { - try - { - context.connectionSecure(challenge); - } - catch(Exception e) - { - - } - } - - - /*} - catch (SaslException e) - { - // need error handling - } - catch (QpidException e) - { - // need error handling - }*/ - } - - @Override public void connectionSecureOk(Channel context, ConnectionSecureOk struct) - { - try - { - saslServer = Sasl.createSaslServer(_mechanism, "AMQP", "ABC",new HashMap(),SecurityHelper.createCallbackHandler(_mechanism,_username,_password)); - byte[] challenge = saslServer.evaluateResponse(struct.getResponse()); - if ( challenge == null) - { - context.connectionTune(Integer.MAX_VALUE, maxFrame, 0, Integer.MAX_VALUE); - } - else - { - try - { - context.connectionSecure(challenge); - } - catch(Exception e) - { - - } - } - - - } - catch (SaslException e) - { - // need error handling - } - catch (QpidException e) - { - // need error handling - } - } - - - @Override public void connectionOpen(Channel context, ConnectionOpen struct) - { - List hosts = new ArrayList(); - hosts.add("amqp:1223243232325"); - context.connectionOpenOk(hosts); - } - - public String getPassword() - { - return _password; - } - - public void setPassword(String password) - { - _password = password; - } - - public String getUsername() - { - return _username; - } - - public void setUsername(String username) - { - _username = username; - } - - public String getVirtualHost() - { - return _virtualHost; - } - - public void setVirtualHost(String host) - { - _virtualHost = host; - } - - public String getUnsupportedProtocol() - { - return null; - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionEvent.java b/java/common/src/main/java/org/apache/qpidity/transport/ConnectionEvent.java deleted file mode 100644 index 62d8f4d99d..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionEvent.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - - -/** - * ConnectionEvent - * - */ - -public class ConnectionEvent -{ - - private final int channel; - private final ProtocolEvent event; - - public ConnectionEvent(int channel, ProtocolEvent event) - { - this.channel = channel; - this.event = event; - } - - public int getChannel() - { - return channel; - } - - public ProtocolEvent getProtocolEvent() - { - return event; - } - - public String toString() - { - return String.format("[%d] %s", channel, event); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Data.java b/java/common/src/main/java/org/apache/qpidity/transport/Data.java deleted file mode 100644 index 4f61380809..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Data.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import org.apache.qpidity.transport.network.Frame; - -import java.nio.ByteBuffer; - -import java.util.Collections; - -import static org.apache.qpidity.transport.util.Functions.*; - - -/** - * Data - * - */ - -public class Data implements ProtocolEvent -{ - - private final Iterable fragments; - private final boolean first; - private final boolean last; - - public Data(Iterable fragments, boolean first, boolean last) - { - this.fragments = fragments; - this.first = first; - this.last = last; - } - - public Data(ByteBuffer buf, boolean first, boolean last) - { - this(Collections.singletonList(buf), first, last); - } - - public Iterable getFragments() - { - return fragments; - } - - public boolean isFirst() - { - return first; - } - - public boolean isLast() - { - return last; - } - - public byte getEncodedTrack() - { - return Frame.L4; - } - - public void delegate(C context, ProtocolDelegate delegate) - { - delegate.data(context, this); - } - - public String toString() - { - StringBuffer str = new StringBuffer(); - str.append("Data("); - boolean first = true; - int left = 64; - for (ByteBuffer buf : getFragments()) - { - if (first) - { - first = false; - } - else - { - str.append(" | "); - } - str.append(str(buf, left)); - left -= buf.remaining(); - if (left < 0) - { - break; - } - } - str.append(")"); - return str.toString(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Echo.java b/java/common/src/main/java/org/apache/qpidity/transport/Echo.java deleted file mode 100644 index 03d0d3e161..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Echo.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import org.apache.qpidity.transport.network.mina.MinaHandler; - - -/** - * Echo - * - */ - -public class Echo extends SessionDelegate -{ - - private MessageTransfer xfr = null; - - public void messageTransfer(Session ssn, MessageTransfer xfr) - { - this.xfr = xfr; - ssn.invoke(xfr); - } - - public void header(Session ssn, Header hdr) - { - ssn.header(hdr); - } - - public void data(Session ssn, Data data) - { - for (ByteBuffer buf : data.getFragments()) - { - ssn.data(buf); - } - if (data.isLast()) - { - ssn.endData(); - } - - // XXX: should be able to get command-id from any segment - ssn.processed(xfr); - } - - public static final void main(String[] args) throws IOException - { - ConnectionDelegate delegate = new ConnectionDelegate() - { - public SessionDelegate getSessionDelegate() - { - return new Echo(); - } - public void exception(Throwable t) - { - t.printStackTrace(); - } - public void closed() {} - }; - - //hack - delegate.setUsername("guest"); - delegate.setPassword("guest"); - - MinaHandler.accept("0.0.0.0", 5672, delegate); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Field.java b/java/common/src/main/java/org/apache/qpidity/transport/Field.java deleted file mode 100644 index ebbd59288b..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Field.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.qpidity.transport; - -import org.apache.qpidity.transport.codec.Decoder; -import org.apache.qpidity.transport.codec.Encoder; - - -/** - * Field - * - */ - -public abstract class Field -{ - - private final Class container; - private final Class type; - private final String name; - private final int index; - - Field(Class container, Class type, String name, int index) - { - this.container = container; - this.type = type; - this.name = name; - this.index = index; - } - - public final Class getContainer() - { - return container; - } - - public final Class getType() - { - return type; - } - - public final String getName() - { - return name; - } - - public final int getIndex() - { - return index; - } - - protected final C check(Object struct) - { - return container.cast(struct); - } - - public abstract boolean has(Object struct); - - public abstract void has(Object struct, boolean value); - - public abstract T get(Object struct); - - public abstract void read(Decoder dec, Object struct); - - public abstract void write(Encoder enc, Object struct); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Future.java b/java/common/src/main/java/org/apache/qpidity/transport/Future.java deleted file mode 100644 index 8936f06831..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Future.java +++ /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. - * - */ -package org.apache.qpidity.transport; - - -/** - * Future - * - * @author Rafael H. Schloming - */ - -public interface Future -{ - - T get(); - - boolean isDone(); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Header.java b/java/common/src/main/java/org/apache/qpidity/transport/Header.java deleted file mode 100644 index ae11bb0c69..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Header.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import org.apache.qpidity.transport.network.Frame; - -import java.util.List; -import java.nio.ByteBuffer; - - -/** - * Header - * - * @author Rafael H. Schloming - */ - -public class Header implements ProtocolEvent { - - private final List structs; - private ByteBuffer _buf; - private boolean _noPayload; - - public Header(List structs, boolean lastframe) - { - this.structs = structs; - _noPayload= lastframe; - } - - public List getStructs() - { - return structs; - } - - public void setBuf(ByteBuffer buf) - { - _buf = buf; - } - - public ByteBuffer getBuf() - { - return _buf; - } - public T get(Class klass) - { - for (Struct st : structs) - { - if (klass.isInstance(st)) - { - return klass.cast(st); - } - } - - return null; - } - - public byte getEncodedTrack() - { - return Frame.L4; - } - - public void delegate(C context, ProtocolDelegate delegate) - { - delegate.header(context, this); - } - - public boolean hasNoPayload() - { - return _noPayload; - } - - - public String toString() - { - StringBuffer str = new StringBuffer(); - str.append("Header("); - boolean first = true; - for (Struct s : structs) - { - if (first) - { - first = false; - } - else - { - str.append(", "); - } - str.append(s); - } - str.append(")"); - return str.toString(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Method.java b/java/common/src/main/java/org/apache/qpidity/transport/Method.java deleted file mode 100644 index f72ebd570c..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Method.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import org.apache.qpidity.transport.network.Frame; - -/** - * Method - * - * @author Rafael H. Schloming - */ - -public abstract class Method extends Struct implements ProtocolEvent -{ - - public static final Method create(int type) - { - // XXX: should generate separate factories for separate - // namespaces - return (Method) StructFactory.createInstruction(type); - } - - // XXX: command subclass? - private int id; - private boolean idSet = false; - private boolean sync = false; - - public final int getId() - { - return id; - } - - void setId(int id) - { - this.id = id; - this.idSet = true; - } - - public final boolean isSync() - { - return sync; - } - - void setSync(boolean value) - { - this.sync = value; - } - - public abstract boolean hasPayload(); - - public abstract byte getEncodedTrack(); - - public abstract void dispatch(C context, MethodDelegate delegate); - - public void delegate(C context, ProtocolDelegate delegate) - { - if (getEncodedTrack() == Frame.L4) - { - delegate.command(context, this); - } - else - { - delegate.control(context, this); - } - } - - public String toString() - { - if (getEncodedTrack() != Frame.L4) - { - return super.toString(); - } - - StringBuilder str = new StringBuilder(); - - if (idSet) - { - str.append("id="); - str.append(id); - } - - if (sync) - { - if (str.length() > 0) - { - str.append(" "); - } - str.append(" [sync]"); - } - - if (str.length() > 0) - { - str.append(" "); - } - str.append(super.toString()); - return str.toString(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java b/java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java deleted file mode 100644 index 028d570416..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - - -/** - * ProtocolDelegate - * - */ - -public interface ProtocolDelegate -{ - - void init(C context, ProtocolHeader header); - - void control(C context, Method control); - - void command(C context, Method command); - - void header(C context, Header header); - - void data(C context, Data data); - - void error(C context, ProtocolError error); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolError.java b/java/common/src/main/java/org/apache/qpidity/transport/ProtocolError.java deleted file mode 100644 index 59fc3d2552..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolError.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import org.apache.qpidity.transport.network.NetworkDelegate; -import org.apache.qpidity.transport.network.NetworkEvent; - - -/** - * ProtocolError - * - * @author Rafael H. Schloming - */ - -public class ProtocolError implements NetworkEvent, ProtocolEvent -{ - - private final byte track; - private final String format; - private final Object[] args; - - public ProtocolError(byte track, String format, Object ... args) - { - this.track = track; - this.format = format; - this.args = args; - } - - public byte getEncodedTrack() - { - return track; - } - - public String getMessage() - { - return String.format(format, args); - } - - public void delegate(C context, ProtocolDelegate delegate) - { - delegate.error(context, this); - } - - public void delegate(NetworkDelegate delegate) - { - delegate.error(this); - } - - public String toString() - { - return String.format("protocol error: %s", getMessage()); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolEvent.java b/java/common/src/main/java/org/apache/qpidity/transport/ProtocolEvent.java deleted file mode 100644 index 0b38dc6f28..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolEvent.java +++ /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. - * - */ -package org.apache.qpidity.transport; - - -/** - * ProtocolEvent - * - */ - -public interface ProtocolEvent -{ - - byte getEncodedTrack(); - - void delegate(C context, ProtocolDelegate delegate); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolHeader.java b/java/common/src/main/java/org/apache/qpidity/transport/ProtocolHeader.java deleted file mode 100644 index f9cd6f3947..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolHeader.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import java.nio.ByteBuffer; - -import org.apache.qpidity.transport.network.NetworkDelegate; -import org.apache.qpidity.transport.network.NetworkEvent; -import org.apache.qpidity.transport.network.Frame; - - -/** - * ProtocolHeader - * - * @author Rafael H. Schloming - */ - -//RA making this public until we sort out the package issues - -public class ProtocolHeader implements NetworkEvent, ProtocolEvent -{ - - private static final byte[] AMQP = {'A', 'M', 'Q', 'P' }; - private static final byte CLASS = 1; - - final private byte instance; - final private byte major; - final private byte minor; - - public ProtocolHeader(byte instance, byte major, byte minor) - { - this.instance = instance; - this.major = major; - this.minor = minor; - } - - public ProtocolHeader(int instance, int major, int minor) - { - this((byte) instance, (byte) major, (byte) minor); - } - - public byte getInstance() - { - return instance; - } - - public byte getMajor() - { - return major; - } - - public byte getMinor() - { - return minor; - } - - public byte getEncodedTrack() - { - return Frame.L1; - } - - public ByteBuffer toByteBuffer() - { - ByteBuffer buf = ByteBuffer.allocate(8); - buf.put(AMQP); - buf.put(CLASS); - buf.put(instance); - buf.put(major); - buf.put(minor); - buf.flip(); - return buf; - } - - public void delegate(C context, ProtocolDelegate delegate) - { - delegate.init(context, this); - } - - public void delegate(NetworkDelegate delegate) - { - delegate.init(this); - } - - public String toString() - { - return String.format("AMQP.%d %d-%d", instance, major, minor); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Range.java b/java/common/src/main/java/org/apache/qpidity/transport/Range.java deleted file mode 100644 index 14522cd45f..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Range.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import java.util.ArrayList; -import java.util.List; - -import static org.apache.qpid.util.Serial.*; - - -/** - * Range - * - * @author Rafael H. Schloming - */ - -public final class Range -{ - private final int lower; - private final int upper; - - public Range(int lower, int upper) - { - this.lower = lower; - this.upper = upper; - } - - public int getLower() - { - return lower; - } - - public int getUpper() - { - return upper; - } - - public boolean includes(int value) - { - return le(lower, value) && le(value, upper); - } - - public boolean includes(Range range) - { - return includes(range.lower) && includes(range.upper); - } - - public boolean intersects(Range range) - { - return (includes(range.lower) || includes(range.upper) || - range.includes(lower) || range.includes(upper)); - } - - public boolean touches(Range range) - { - return (intersects(range) || - includes(range.upper + 1) || includes(range.lower - 1) || - range.includes(upper + 1) || range.includes(lower - 1)); - } - - public Range span(Range range) - { - return new Range(min(lower, range.lower), max(upper, range.upper)); - } - - public List subtract(Range range) - { - List result = new ArrayList(); - - if (includes(range.lower) && le(lower, range.lower - 1)) - { - result.add(new Range(lower, range.lower - 1)); - } - - if (includes(range.upper) && le(range.upper + 1, upper)) - { - result.add(new Range(range.upper + 1, upper)); - } - - if (result.isEmpty() && !range.includes(this)) - { - result.add(this); - } - - return result; - } - - public Range intersect(Range range) - { - int l = max(lower, range.lower); - int r = min(upper, range.upper); - if (gt(l, r)) - { - return null; - } - else - { - return new Range(l, r); - } - } - - public String toString() - { - return "[" + lower + ", " + upper + "]"; - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java b/java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java deleted file mode 100644 index e05e399262..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import java.util.Iterator; -import java.util.ListIterator; -import java.util.LinkedList; - -import static org.apache.qpid.util.Serial.*; - -/** - * RangeSet - * - * @author Rafael H. Schloming - */ - -public final class RangeSet implements Iterable -{ - - private LinkedList ranges = new LinkedList(); - - public int size() - { - return ranges.size(); - } - - public Iterator iterator() - { - return ranges.iterator(); - } - - public boolean includes(Range range) - { - for (Range r : this) - { - if (r.includes(range)) - { - return true; - } - } - - return false; - } - - public boolean includes(int n) - { - for (Range r : this) - { - if (r.includes(n)) - { - return true; - } - } - - return false; - } - - public void add(Range range) - { - ListIterator it = ranges.listIterator(); - - while (it.hasNext()) - { - Range next = it.next(); - if (range.touches(next)) - { - it.remove(); - range = range.span(next); - } - else if (lt(range.getUpper(), next.getLower())) - { - it.previous(); - it.add(range); - return; - } - } - - it.add(range); - } - - public void add(int lower, int upper) - { - add(new Range(lower, upper)); - } - - public void add(int value) - { - add(value, value); - } - - public void clear() - { - ranges.clear(); - } - - public RangeSet copy() - { - RangeSet copy = new RangeSet(); - copy.ranges.addAll(ranges); - return copy; - } - - public String toString() - { - StringBuffer str = new StringBuffer(); - str.append("{"); - boolean first = true; - for (Range range : ranges) - { - if (first) - { - first = false; - } - else - { - str.append(", "); - } - str.append(range); - } - str.append("}"); - return str.toString(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Receiver.java b/java/common/src/main/java/org/apache/qpidity/transport/Receiver.java deleted file mode 100644 index 8952ebf2a5..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Receiver.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - - -/** - * Receiver - * - */ - -public interface Receiver -{ - - void received(T msg); - - void exception(Throwable t); - - void closed(); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Result.java b/java/common/src/main/java/org/apache/qpidity/transport/Result.java deleted file mode 100644 index 2126a76a53..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Result.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - - -/** - * Result - * - * @author Rafael H. Schloming - */ - -public abstract class Result extends Struct {} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Sender.java b/java/common/src/main/java/org/apache/qpidity/transport/Sender.java deleted file mode 100644 index 6da8358bd6..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Sender.java +++ /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. - * - */ -package org.apache.qpidity.transport; - - -/** - * Sender - * - */ - -public interface Sender -{ - - void send(T msg); - - void close(); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Session.java b/java/common/src/main/java/org/apache/qpidity/transport/Session.java deleted file mode 100644 index 988ac4788f..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Session.java +++ /dev/null @@ -1,565 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - - -import org.apache.qpidity.transport.network.Frame; - -import org.apache.qpidity.transport.util.Logger; - -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.atomic.AtomicBoolean; - -import static org.apache.qpidity.transport.Option.*; -import static org.apache.qpidity.transport.util.Functions.*; -import static org.apache.qpid.util.Serial.*; - -/** - * Session - * - * @author Rafael H. Schloming - */ - -public class Session extends Invoker -{ - - private static final Logger log = Logger.get(Session.class); - - private static boolean ENABLE_REPLAY = false; - - static - { - String enableReplay = "enable_command_replay"; - try - { - ENABLE_REPLAY = new Boolean(System.getProperties().getProperty(enableReplay, "false")); - } - catch (Exception e) - { - ENABLE_REPLAY = false; - } - } - - private byte[] name; - private long timeout = 60000; - private boolean autoSync = false; - - // channel may be null - Channel channel; - - // incoming command count - int commandsIn = 0; - // completed incoming commands - private final Object processedLock = new Object(); - private RangeSet processed = new RangeSet(); - private Range syncPoint = null; - - // outgoing command count - private int commandsOut = 0; - private Map commands = new HashMap(); - private int maxComplete = commandsOut - 1; - private boolean needSync = false; - - private AtomicBoolean closed = new AtomicBoolean(false); - - public Session(byte[] name) - { - this.name = name; - } - - public byte[] getName() - { - return name; - } - - public void setAutoSync(boolean value) - { - synchronized (commands) - { - this.autoSync = value; - } - } - - public Map getOutstandingCommands() - { - return commands; - } - - public int getCommandsOut() - { - return commandsOut; - } - - public int getCommandsIn() - { - return commandsIn; - } - - public int nextCommandId() - { - return commandsIn++; - } - - final void identify(Method cmd) - { - int id = nextCommandId(); - cmd.setId(id); - log.debug("ID: [%s] %s", this.channel, id); - if ((id % 65536) == 0) - { - flushProcessed(true); - } - } - - public void processed(Method command) - { - processed(command.getId()); - } - - public void processed(int command) - { - processed(new Range(command, command)); - } - - public void processed(int lower, int upper) - { - - processed(new Range(lower, upper)); - } - - public void processed(Range range) - { - log.debug("%s processed(%s)", this, range); - - boolean flush; - synchronized (processedLock) - { - processed.add(range); - flush = syncPoint != null && processed.includes(syncPoint); - } - if (flush) - { - flushProcessed(); - } - } - - public void flushProcessed() - { - flushProcessed(false); - } - - private void flushProcessed(boolean timely_reply) - { - RangeSet copy; - synchronized (processedLock) - { - copy = processed.copy(); - } - sessionCompleted(copy, timely_reply ? TIMELY_REPLY : NO_OPTION); - } - - void knownComplete(RangeSet kc) - { - synchronized (processedLock) - { - RangeSet newProcessed = new RangeSet(); - for (Range pr : processed) - { - for (Range kr : kc) - { - for (Range r : pr.subtract(kr)) - { - newProcessed.add(r); - } - } - } - this.processed = newProcessed; - } - } - - void syncPoint() - { - int id = getCommandsIn() - 1; - log.debug("%s synced to %d", this, id); - Range range = new Range(0, id - 1); - boolean flush; - synchronized (processedLock) - { - flush = processed.includes(range); - if (!flush) - { - syncPoint = range; - } - } - if (flush) - { - flushProcessed(); - } - } - - public void attach(Channel channel) - { - this.channel = channel; - channel.setSession(this); - } - - public Method getCommand(int id) - { - synchronized (commands) - { - return commands.get(id); - } - } - - boolean complete(int lower, int upper) - { - log.debug("%s complete(%d, %d)", this, lower, upper); - synchronized (commands) - { - int old = maxComplete; - for (int id = max(maxComplete, lower); le(id, upper); id++) - { - commands.remove(id); - } - if (le(lower, maxComplete + 1)) - { - maxComplete = max(maxComplete, upper); - } - log.debug("%s commands remaining: %s", this, commands); - commands.notifyAll(); - return gt(maxComplete, old); - } - } - - protected void invoke(Method m) - { - if (m.getEncodedTrack() == Frame.L4) - { - synchronized (commands) - { - int next = commandsOut++; - m.setId(next); - if (next == 0) - { - sessionCommandPoint(0, 0); - } - if (ENABLE_REPLAY) - { - commands.put(next, m); - } - if (autoSync) - { - m.setSync(true); - } - needSync = !m.isSync(); - channel.method(m); - if (autoSync && !m.hasPayload()) - { - sync(); - } - - // flush every 64K commands to avoid ambiguity on - // wraparound - if ((next % 65536) == 0) - { - sessionFlush(COMPLETED); - } - } - } - else - { - channel.method(m); - } - } - - public void header(Header header) - { - channel.header(header); - } - - public Header header(List structs) - { - Header res = new Header(structs, false); - header(res); - return res; - } - - public Header header(Struct ... structs) - { - return header(Arrays.asList(structs)); - } - - public void data(ByteBuffer buf) - { - channel.data(buf); - } - - public void data(String str) - { - channel.data(str); - } - - public void data(byte[] bytes) - { - channel.data(bytes); - } - - public void endData() - { - channel.end(); - synchronized (commands) - { - if (autoSync) - { - sync(); - } - } - } - - public void sync() - { - sync(timeout); - } - - public void sync(long timeout) - { - log.debug("%s sync()", this); - synchronized (commands) - { - int point = commandsOut - 1; - - if (needSync && lt(maxComplete, point)) - { - ExecutionSync sync = new ExecutionSync(); - sync.setSync(true); - invoke(sync); - } - - long start = System.currentTimeMillis(); - long elapsed = 0; - while (!closed.get() && elapsed < timeout && lt(maxComplete, point)) - { - try { - log.debug("%s waiting for[%d]: %d, %s", this, point, - maxComplete, commands); - commands.wait(timeout - elapsed); - elapsed = System.currentTimeMillis() - start; - } - catch (InterruptedException e) - { - throw new RuntimeException(e); - } - } - - if (lt(maxComplete, point)) - { - if (closed.get()) - { - throw new SessionException(getExceptions()); - } - else - { - throw new RuntimeException - (String.format - ("timed out waiting for sync: complete = %s, point = %s", maxComplete, point)); - } - } - } - } - - private Map> results = - new HashMap>(); - private List exceptions = - new ArrayList(); - - void result(int command, Struct result) - { - ResultFuture future; - synchronized (results) - { - future = results.remove(command); - } - future.set(result); - } - - void addException(ExecutionException exc) - { - synchronized (exceptions) - { - exceptions.add(exc); - } - } - - List getExceptions() - { - synchronized (exceptions) - { - return new ArrayList(exceptions); - } - } - - protected Future invoke(Method m, Class klass) - { - synchronized (commands) - { - int command = commandsOut; - ResultFuture future = new ResultFuture(klass); - synchronized (results) - { - results.put(command, future); - } - invoke(m); - return future; - } - } - - private class ResultFuture implements Future - { - - private final Class klass; - private T result; - - private ResultFuture(Class klass) - { - this.klass = klass; - } - - private void set(Struct result) - { - synchronized (this) - { - this.result = klass.cast(result); - notifyAll(); - } - } - - public T get(long timeout) - { - synchronized (this) - { - long start = System.currentTimeMillis(); - long elapsed = 0; - while (!closed.get() && timeout - elapsed > 0 && !isDone()) - { - try - { - log.debug("%s waiting for result: %s", Session.this, this); - wait(timeout - elapsed); - elapsed = System.currentTimeMillis() - start; - } - catch (InterruptedException e) - { - throw new RuntimeException(e); - } - } - } - - if (isDone()) - { - return result; - } - else if (closed.get()) - { - throw new SessionException(getExceptions()); - } - else - { - return null; - } - } - - public T get() - { - return get(timeout); - } - - public boolean isDone() - { - return result != null; - } - - public String toString() - { - return String.format("Future(%s)", isDone() ? result : klass); - } - - } - - public void close() - { - sessionRequestTimeout(0); - sessionDetach(name); - synchronized (commands) - { - long start = System.currentTimeMillis(); - long elapsed = 0; - try - { - while (!closed.get() && elapsed < timeout) - { - commands.wait(timeout - elapsed); - elapsed = System.currentTimeMillis() - start; - } - } - catch (InterruptedException e) - { - throw new RuntimeException(e); - } - } - } - - public void exception(Throwable t) - { - log.error(t, "caught exception"); - } - - public void closed() - { - closed.set(true); - synchronized (commands) - { - commands.notifyAll(); - } - synchronized (results) - { - for (ResultFuture result : results.values()) - { - synchronized(result) - { - result.notifyAll(); - } - } - } - channel.setSession(null); - channel = null; - } - - public String toString() - { - return String.format("ssn:%s", str(name)); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java b/java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java deleted file mode 100644 index 0e289c54e9..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import org.apache.qpidity.transport.network.Frame; - - -/** - * SessionDelegate - * - * @author Rafael H. Schloming - */ - -public abstract class SessionDelegate - extends MethodDelegate - implements ProtocolDelegate -{ - public void init(Session ssn, ProtocolHeader hdr) { } - - public void control(Session ssn, Method method) { - method.dispatch(ssn, this); - } - - public void command(Session ssn, Method method) { - ssn.identify(method); - method.dispatch(ssn, this); - if (!method.hasPayload()) - { - ssn.processed(method); - } - } - - public void header(Session ssn, Header header) { } - - public void data(Session ssn, Data data) { } - - public void error(Session ssn, ProtocolError error) { } - - @Override public void executionResult(Session ssn, ExecutionResult result) - { - ssn.result(result.getCommandId(), result.getValue()); - } - - @Override public void executionException(Session ssn, ExecutionException exc) - { - ssn.addException(exc); - } - - @Override public void sessionCompleted(Session ssn, SessionCompleted cmp) - { - RangeSet ranges = cmp.getCommands(); - RangeSet known = null; - if (cmp.getTimelyReply()) - { - known = new RangeSet(); - } - - if (ranges != null) - { - for (Range range : ranges) - { - boolean advanced = ssn.complete(range.getLower(), range.getUpper()); - if (advanced && known != null) - { - known.add(range); - } - } - } - - if (known != null) - { - ssn.sessionKnownCompleted(known); - } - } - - @Override public void sessionKnownCompleted(Session ssn, SessionKnownCompleted kcmp) - { - RangeSet kc = kcmp.getCommands(); - if (kc != null) - { - ssn.knownComplete(kc); - } - } - - @Override public void sessionFlush(Session ssn, SessionFlush flush) - { - if (flush.getCompleted()) - { - ssn.flushProcessed(); - } - if (flush.getConfirmed()) - { - ssn.flushProcessed(); - } - if (flush.getExpected()) - { - throw new Error("not implemented"); - } - } - - @Override public void sessionCommandPoint(Session ssn, SessionCommandPoint scp) - { - ssn.commandsIn = scp.getCommandId(); - } - - @Override public void executionSync(Session ssn, ExecutionSync sync) - { - ssn.syncPoint(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/SessionException.java b/java/common/src/main/java/org/apache/qpidity/transport/SessionException.java deleted file mode 100644 index fc866f3694..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/SessionException.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.qpidity.transport; - -import java.util.List; - -/** - * SessionException - * - */ - -public class SessionException extends RuntimeException -{ - - private List exceptions; - - public SessionException(List exceptions) - { - super(exceptions.isEmpty() ? "" : exceptions.toString()); - this.exceptions = exceptions; - } - - public List getExceptions() - { - return exceptions; - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/Struct.java b/java/common/src/main/java/org/apache/qpidity/transport/Struct.java deleted file mode 100644 index a15d0a1fb8..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/Struct.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import java.util.List; -import java.util.Map; - -import org.apache.qpidity.transport.codec.Decoder; -import org.apache.qpidity.transport.codec.Encodable; -import org.apache.qpidity.transport.codec.Encoder; - - -/** - * Struct - * - * @author Rafael H. Schloming - */ - -public abstract class Struct implements Encodable -{ - - public static Struct create(int type) - { - return StructFactory.create(type); - } - - boolean dirty = true; - - public boolean isDirty() - { - return dirty; - } - - public void setDirty(boolean dirty) - { - this.dirty = dirty; - } - - public abstract int getStructType(); - - public abstract int getSizeWidth(); - - public abstract int getPackWidth(); - - public final int getEncodedType() - { - int type = getStructType(); - if (type < 0) - { - throw new UnsupportedOperationException(); - } - return type; - } - - private final boolean isBit(Field f) - { - return f.getType().equals(Boolean.class); - } - - private final boolean packed() - { - return getPackWidth() > 0; - } - - private final boolean encoded(Field f) - { - return !packed() || !isBit(f) && f.has(this); - } - - private final int getFlagWidth() - { - return (getFields().size() + 7)/8; - } - - private final int getPaddWidth() - { - int pw = getPackWidth() - getFlagWidth(); - assert pw > 0; - return pw; - } - - private final int getFlagCount() - { - return 8*getPackWidth(); - } - - private final int getReservedFlagCount() - { - return getFlagCount() - getFields().size(); - } - - public abstract void read(Decoder dec); - - public abstract void write(Encoder enc); - - public abstract Map getFields(); - - public String toString() - { - StringBuilder str = new StringBuilder(); - str.append(getClass().getSimpleName()); - - str.append("("); - boolean first = true; - for (Map.Entry me : getFields().entrySet()) - { - if (first) - { - first = false; - } - else - { - str.append(", "); - } - str.append(me.getKey()); - str.append("="); - str.append(me.getValue()); - } - str.append(")"); - - return str.toString(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java b/java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java deleted file mode 100644 index e9a0705de0..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.apache.qpidity.transport; - -public class TransportConstants -{ - - private static byte _protocol_version_minor = 10; - private static byte _protocol_version_major = 0; - - public static void setVersionMajor(byte value) - { - _protocol_version_major = value; - } - - public static void setVersionMinor(byte value) - { - _protocol_version_minor = value; - } - - public static byte getVersionMajor() - { - return _protocol_version_major; - } - - public static byte getVersionMinor() - { - return _protocol_version_minor; - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/TransportException.java b/java/common/src/main/java/org/apache/qpidity/transport/TransportException.java deleted file mode 100644 index 593209df82..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/TransportException.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.qpidity.transport; - - -/** - * TransportException - */ - -public class TransportException extends RuntimeException -{ - - public TransportException(String msg) - { - super(msg); - } - - public TransportException(String msg, Throwable cause) - { - super(msg, cause); - } - - public TransportException(Throwable cause) - { - super(cause); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractDecoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractDecoder.java deleted file mode 100644 index ebfc6b120f..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractDecoder.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.io.UnsupportedEncodingException; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpidity.transport.RangeSet; -import org.apache.qpidity.transport.Struct; -import org.apache.qpidity.transport.Type; - -import static org.apache.qpidity.transport.util.Functions.*; - - -/** - * AbstractDecoder - * - * @author Rafael H. Schloming - */ - -abstract class AbstractDecoder implements Decoder -{ - - protected abstract byte doGet(); - - protected abstract void doGet(byte[] bytes); - - protected byte get() - { - return doGet(); - } - - protected void get(byte[] bytes) - { - doGet(bytes); - } - - protected short uget() - { - return (short) (0xFF & get()); - } - - public short readUint8() - { - return uget(); - } - - public int readUint16() - { - int i = uget() << 8; - i |= uget(); - return i; - } - - public long readUint32() - { - long l = uget() << 24; - l |= uget() << 16; - l |= uget() << 8; - l |= uget(); - return l; - } - - public int readSequenceNo() - { - return (int) readUint32(); - } - - public long readUint64() - { - long l = 0; - for (int i = 0; i < 8; i++) - { - l |= ((long) (0xFF & get())) << (56 - i*8); - } - return l; - } - - public long readDatetime() - { - return readUint64(); - } - - private static final String decode(byte[] bytes, String charset) - { - try - { - return new String(bytes, charset); - } - catch (UnsupportedEncodingException e) - { - throw new RuntimeException(e); - } - } - - - public String readStr8() - { - short size = readUint8(); - byte[] bytes = new byte[size]; - get(bytes); - return decode(bytes, "UTF-8"); - } - - public String readStr16() - { - int size = readUint16(); - byte[] bytes = new byte[size]; - get(bytes); - return decode(bytes, "UTF-8"); - } - - public byte[] readVbin8() - { - int size = readUint8(); - byte[] bytes = new byte[size]; - get(bytes); - return bytes; - } - - public byte[] readVbin16() - { - int size = readUint16(); - byte[] bytes = new byte[size]; - get(bytes); - return bytes; - } - - public byte[] readVbin32() - { - int size = (int) readUint32(); - byte[] bytes = new byte[size]; - get(bytes); - return bytes; - } - - public RangeSet readSequenceSet() - { - int count = readUint16()/8; - if (count == 0) - { - return null; - } - else - { - RangeSet ranges = new RangeSet(); - for (int i = 0; i < count; i++) - { - ranges.add(readSequenceNo(), readSequenceNo()); - } - return ranges; - } - } - - public RangeSet readByteRanges() - { - throw new Error("not implemented"); - } - - public UUID readUuid() - { - long msb = readUint64(); - long lsb = readUint64(); - return new UUID(msb, lsb); - } - - public String readContent() - { - throw new Error("Deprecated"); - } - - public Struct readStruct(int type) - { - Struct st = Struct.create(type); - int width = st.getSizeWidth(); - if (width > 0) - { - long size = readSize(width); - if (size == 0) - { - return null; - } - } - if (type > 0) - { - int code = readUint16(); - assert code == type; - } - st.read(this); - return st; - } - - public Struct readStruct32() - { - long size = readUint32(); - if (size == 0) - { - return null; - } - else - { - int type = readUint16(); - Struct result = Struct.create(type); - result.read(this); - return result; - } - } - - public Map readMap() - { - long size = readUint32(); - long count = readUint32(); - Map result = new LinkedHashMap(); - for (int i = 0; i < count; i++) - { - String key = readStr8(); - byte code = get(); - Type t = getType(code); - Object value = read(t); - result.put(key, value); - } - return result; - } - - public List readList() - { - long size = readUint32(); - long count = readUint32(); - List result = new ArrayList(); - for (int i = 0; i < count; i++) - { - byte code = get(); - Type t = getType(code); - Object value = read(t); - result.add(value); - } - return result; - } - - public List readArray() - { - long size = readUint32(); - if (size == 0) - { - return Collections.EMPTY_LIST; - } - - byte code = get(); - Type t = getType(code); - long count = readUint32(); - - List result = new ArrayList(); - for (int i = 0; i < count; i++) - { - Object value = read(t); - result.add(value); - } - return result; - } - - private Type getType(byte code) - { - Type type = Type.get(code); - if (type == null) - { - throw new IllegalArgumentException("unknown code: " + code); - } - else - { - return type; - } - } - - private long readSize(Type t) - { - if (t.fixed) - { - return t.width; - } - else - { - return readSize(t.width); - } - } - - private long readSize(int width) - { - switch (width) - { - case 1: - return readUint8(); - case 2: - return readUint16(); - case 4: - return readUint32(); - default: - throw new IllegalStateException("illegal width: " + width); - } - } - - private byte[] readBytes(Type t) - { - long size = readSize(t); - byte[] result = new byte[(int) size]; - get(result); - return result; - } - - private Object read(Type t) - { - switch (t) - { - case BIN8: - case UINT8: - return readUint8(); - case INT8: - return get(); - case CHAR: - return (char) get(); - case BOOLEAN: - return get() > 0; - - case BIN16: - case UINT16: - return readUint16(); - - case INT16: - return (short) readUint16(); - - case BIN32: - case UINT32: - return readUint32(); - - case CHAR_UTF32: - case INT32: - return (int) readUint32(); - - case FLOAT: - return Float.intBitsToFloat((int) readUint32()); - - case BIN64: - case UINT64: - case INT64: - case DATETIME: - return readUint64(); - - case DOUBLE: - return Double.longBitsToDouble(readUint64()); - - case UUID: - return readUuid(); - - case STR8: - return readStr8(); - - case STR16: - return readStr16(); - - case STR8_LATIN: - case STR8_UTF16: - case STR16_LATIN: - case STR16_UTF16: - // XXX: need to do character conversion - return new String(readBytes(t)); - - case MAP: - return readMap(); - case LIST: - return readList(); - case ARRAY: - return readArray(); - case STRUCT32: - return readStruct32(); - - case BIN40: - case DEC32: - case BIN72: - case DEC64: - // XXX: what types are we supposed to use here? - return readBytes(t); - - case VOID: - return null; - - default: - return readBytes(t); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractEncoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractEncoder.java deleted file mode 100644 index aa90627943..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/AbstractEncoder.java +++ /dev/null @@ -1,589 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.io.UnsupportedEncodingException; - -import java.nio.ByteBuffer; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpidity.transport.Range; -import org.apache.qpidity.transport.RangeSet; -import org.apache.qpidity.transport.Struct; -import org.apache.qpidity.transport.Type; - -import static org.apache.qpidity.transport.util.Functions.*; - - -/** - * AbstractEncoder - * - * @author Rafael H. Schloming - */ - -abstract class AbstractEncoder implements Encoder -{ - - private static Map,Type> ENCODINGS = new HashMap,Type>(); - static - { - ENCODINGS.put(Boolean.class, Type.BOOLEAN); - ENCODINGS.put(String.class, Type.STR16); - ENCODINGS.put(Long.class, Type.INT64); - ENCODINGS.put(Integer.class, Type.INT32); - ENCODINGS.put(Short.class, Type.INT16); - ENCODINGS.put(Byte.class, Type.INT8); - ENCODINGS.put(Map.class, Type.MAP); - ENCODINGS.put(List.class, Type.LIST); - ENCODINGS.put(Float.class, Type.FLOAT); - ENCODINGS.put(Double.class, Type.DOUBLE); - ENCODINGS.put(Character.class, Type.CHAR); - ENCODINGS.put(byte[].class, Type.VBIN32); - } - - protected Sizer sizer() - { - return new SizeEncoder(); - } - - protected abstract void doPut(byte b); - - protected abstract void doPut(ByteBuffer src); - - protected void put(byte b) - { - doPut(b); - } - - protected void put(ByteBuffer src) - { - doPut(src); - } - - protected void put(byte[] bytes) - { - put(ByteBuffer.wrap(bytes)); - } - - public void writeUint8(short b) - { - assert b < 0x100; - - put((byte) b); - } - - public void writeUint16(int s) - { - assert s < 0x10000; - - put(lsb(s >>> 8)); - put(lsb(s)); - } - - public void writeUint32(long i) - { - assert i < 0x100000000L; - - put(lsb(i >>> 24)); - put(lsb(i >>> 16)); - put(lsb(i >>> 8)); - put(lsb(i)); - } - - public void writeSequenceNo(int i) - { - writeUint32(i); - } - - public void writeUint64(long l) - { - for (int i = 0; i < 8; i++) - { - put(lsb(l >> (56 - i*8))); - } - } - - - public void writeDatetime(long l) - { - writeUint64(l); - } - - private static final String checkLength(String s, int n) - { - if (s == null) - { - return ""; - } - - if (s.length() > n) - { - throw new IllegalArgumentException("string too long: " + s); - } - else - { - return s; - } - } - - private static final byte[] encode(String s, String charset) - { - try - { - return s.getBytes(charset); - } - catch (UnsupportedEncodingException e) - { - throw new RuntimeException(e); - } - } - - public void writeStr8(String s) - { - s = checkLength(s, 255); - writeUint8((short) s.length()); - put(ByteBuffer.wrap(encode(s, "UTF-8"))); - } - - public void writeStr16(String s) - { - s = checkLength(s, 65535); - writeUint16(s.length()); - put(ByteBuffer.wrap(encode(s, "UTF-8"))); - } - - public void writeVbin8(byte[] bytes) - { - if (bytes == null) { bytes = new byte[0]; } - if (bytes.length > 255) - { - throw new IllegalArgumentException("array too long: " + bytes.length); - } - writeUint8((short) bytes.length); - put(ByteBuffer.wrap(bytes)); - } - - public void writeVbin16(byte[] bytes) - { - if (bytes == null) { bytes = new byte[0]; } - writeUint16(bytes.length); - put(ByteBuffer.wrap(bytes)); - } - - public void writeVbin32(byte[] bytes) - { - if (bytes == null) { bytes = new byte[0]; } - writeUint32(bytes.length); - put(ByteBuffer.wrap(bytes)); - } - - public void writeSequenceSet(RangeSet ranges) - { - if (ranges == null) - { - writeUint16((short) 0); - } - else - { - writeUint16(ranges.size() * 8); - for (Range range : ranges) - { - writeSequenceNo(range.getLower()); - writeSequenceNo(range.getUpper()); - } - } - } - - public void writeByteRanges(RangeSet ranges) - { - throw new Error("not implemented"); - } - - public void writeUuid(UUID uuid) - { - long msb = 0; - long lsb = 0; - if (uuid != null) - { - msb = uuid.getMostSignificantBits(); - lsb = uuid.getLeastSignificantBits(); - } - writeUint64(msb); - writeUint64(lsb); - } - - public void writeStruct(int type, Struct s) - { - boolean empty = false; - if (s == null) - { - s = Struct.create(type); - empty = true; - } - - int width = s.getSizeWidth(); - if (width > 0) - { - if (empty) - { - writeSize(width, 0); - } - else - { - Sizer sizer = sizer(); - s.write(sizer); - writeSize(width, sizer.size()); - } - } - - if (type > 0) - { - writeUint16(type); - } - - s.write(this); - } - - public void writeStruct32(Struct s) - { - if (s == null) - { - writeUint32(0); - } - else - { - Sizer sizer = sizer(); - sizer.writeUint16(s.getEncodedType()); - s.write(sizer); - writeUint32(sizer.size()); - writeUint16(s.getEncodedType()); - s.write(this); - } - } - - private Type encoding(Object value) - { - if (value == null) - { - return Type.VOID; - } - - Class klass = value.getClass(); - Type type = resolve(klass); - - if (type == null) - { - throw new IllegalArgumentException - ("unable to resolve type: " + klass + ", " + value); - } - else - { - return type; - } - } - - static final Type resolve(Class klass) - { - Type type = ENCODINGS.get(klass); - if (type != null) - { - return type; - } - - Class sup = klass.getSuperclass(); - if (sup != null) - { - type = resolve(klass.getSuperclass()); - - if (type != null) - { - return type; - } - } - - for (Class iface : klass.getInterfaces()) - { - type = resolve(iface); - if (type != null) - { - return type; - } - } - - return null; - } - - public void writeMap(Map map) - { - if (map == null) - { - writeUint32(0); - return; - } - - Sizer sizer = sizer(); - sizer.writeMap(map); - // XXX: - 4 - writeUint32(sizer.size() - 4); - writeUint32(map.size()); - writeMapEntries(map); - } - - protected void writeMapEntries(Map map) - { - for (Map.Entry entry : map.entrySet()) - { - String key = entry.getKey(); - Object value = entry.getValue(); - Type type = encoding(value); - writeStr8(key); - put(type.code); - write(type, value); - } - } - - public void writeList(List list) - { - Sizer sizer = sizer(); - sizer.writeList(list); - // XXX: - 4 - writeUint32(sizer.size() - 4); - writeUint32(list.size()); - writeListEntries(list); - } - - protected void writeListEntries(List list) - { - for (Object value : list) - { - Type type = encoding(value); - put(type.code); - write(type, value); - } - } - - public void writeArray(List array) - { - if (array == null) - { - array = Collections.EMPTY_LIST; - } - - Sizer sizer = sizer(); - sizer.writeArray(array); - // XXX: -4 - writeUint32(sizer.size() - 4); - writeArrayEntries(array); - } - - protected void writeArrayEntries(List array) - { - Type type; - - if (array.isEmpty()) - { - return; - } - else - { - type = encoding(array.get(0)); - } - - put(type.code); - - writeUint32(array.size()); - - for (Object value : array) - { - write(type, value); - } - } - - private void writeSize(Type t, int size) - { - if (t.fixed) - { - if (size != t.width) - { - throw new IllegalArgumentException - ("size does not match fixed width " + t.width + ": " + - size); - } - } - else - { - writeSize(t.width, size); - } - } - - private void writeSize(int width, int size) - { - // XXX: should check lengths - switch (width) - { - case 1: - writeUint8((short) size); - break; - case 2: - writeUint16(size); - break; - case 4: - writeUint32(size); - break; - default: - throw new IllegalStateException("illegal width: " + width); - } - } - - private void writeBytes(Type t, byte[] bytes) - { - writeSize(t, bytes.length); - put(bytes); - } - - private T coerce(Class klass, Object value) - { - if (klass.isInstance(value)) - { - return klass.cast(value); - } - else - { - throw new IllegalArgumentException("" + value); - } - } - - private void write(Type t, Object value) - { - switch (t) - { - case BIN8: - case UINT8: - writeUint8(coerce(Short.class, value)); - break; - case INT8: - put(coerce(Byte.class, value)); - break; - case CHAR: - put((byte) ((char)coerce(Character.class, value))); - break; - case BOOLEAN: - if (coerce(Boolean.class, value)) - { - put((byte) 1); - } - else - { - put((byte) 0); - } - break; - - case BIN16: - case UINT16: - writeUint16(coerce(Integer.class, value)); - break; - - case INT16: - writeUint16(coerce(Short.class, value)); - break; - - case BIN32: - case UINT32: - writeUint32(coerce(Long.class, value)); - break; - - case CHAR_UTF32: - case INT32: - writeUint32(coerce(Integer.class, value)); - break; - - case FLOAT: - writeUint32(Float.floatToIntBits(coerce(Float.class, value))); - break; - - case BIN64: - case UINT64: - case INT64: - case DATETIME: - writeUint64(coerce(Long.class, value)); - break; - - case DOUBLE: - long bits = Double.doubleToLongBits(coerce(Double.class, value)); - writeUint64(bits); - break; - - case UUID: - writeUuid(coerce(UUID.class, value)); - break; - - case STR8: - writeStr8(coerce(String.class, value)); - break; - - case STR16: - writeStr16(coerce(String.class, value)); - break; - - case STR8_LATIN: - case STR8_UTF16: - case STR16_LATIN: - case STR16_UTF16: - // XXX: need to do character conversion - writeBytes(t, coerce(String.class, value).getBytes()); - break; - - case MAP: - writeMap((Map) coerce(Map.class, value)); - break; - case LIST: - writeList(coerce(List.class, value)); - break; - case ARRAY: - writeArray(coerce(List.class, value)); - break; - case STRUCT32: - writeStruct32(coerce(Struct.class, value)); - break; - - case BIN40: - case DEC32: - case BIN72: - case DEC64: - // XXX: what types are we supposed to use here? - writeBytes(t, coerce(byte[].class, value)); - break; - - case VOID: - break; - - default: - writeBytes(t, coerce(byte[].class, value)); - break; - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/BBDecoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/BBDecoder.java deleted file mode 100644 index cf40cef8bf..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/BBDecoder.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - - -/** - * BBDecoder - * - * @author Rafael H. Schloming - */ - -public final class BBDecoder extends AbstractDecoder -{ - - private final ByteBuffer in; - - public BBDecoder(ByteBuffer in) - { - this.in = in; - this.in.order(ByteOrder.BIG_ENDIAN); - } - - protected byte doGet() - { - return in.get(); - } - - protected void doGet(byte[] bytes) - { - in.get(bytes); - } - - public boolean hasRemaining() - { - return in.hasRemaining(); - } - - public short readUint8() - { - return (short) (0xFF & in.get()); - } - - public int readUint16() - { - return 0xFFFF & in.getShort(); - } - - public long readUint32() - { - return 0xFFFFFFFFL & in.getInt(); - } - - public long readUint64() - { - return in.getLong(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/BBEncoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/BBEncoder.java deleted file mode 100644 index 2e7b41bf42..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/BBEncoder.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; - - -/** - * BBEncoder - * - * @author Rafael H. Schloming - */ - -public final class BBEncoder extends AbstractEncoder -{ - - private final ByteBuffer out; - - public BBEncoder(ByteBuffer out) { - this.out = out; - this.out.order(ByteOrder.BIG_ENDIAN); - } - - protected void doPut(byte b) - { - out.put(b); - } - - protected void doPut(ByteBuffer src) - { - out.put(src); - } - - public void writeUint8(short b) - { - assert b < 0x100; - - out.put((byte) b); - } - - public void writeUint16(int s) - { - assert s < 0x10000; - - out.putShort((short) s); - } - - public void writeUint32(long i) - { - assert i < 0x100000000L; - - out.putInt((int) i); - } - - public void writeUint64(long l) - { - out.putLong(l); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Decoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/Decoder.java deleted file mode 100644 index dec901748d..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Decoder.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpidity.transport.RangeSet; -import org.apache.qpidity.transport.Struct; - - -/** - * Decoder - * - * @author Rafael H. Schloming - */ - -public interface Decoder -{ - - boolean hasRemaining(); - - short readUint8(); - int readUint16(); - long readUint32(); - long readUint64(); - - long readDatetime(); - UUID readUuid(); - - int readSequenceNo(); - RangeSet readSequenceSet(); // XXX - RangeSet readByteRanges(); // XXX - - String readStr8(); - String readStr16(); - - byte[] readVbin8(); - byte[] readVbin16(); - byte[] readVbin32(); - - Struct readStruct32(); - Map readMap(); - List readList(); - List readArray(); - - Struct readStruct(int type); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Encodable.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/Encodable.java deleted file mode 100644 index 60c2ea97b8..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Encodable.java +++ /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. - * - */ -package org.apache.qpidity.transport.codec; - - -/** - * Encodable - * - * @author Rafael H. Schloming - */ - -public interface Encodable -{ - - void write(Encoder enc); - - void read(Decoder dec); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Encoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/Encoder.java deleted file mode 100644 index 9d7a1a695d..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Encoder.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpidity.transport.RangeSet; -import org.apache.qpidity.transport.Struct; - - -/** - * Encoder - * - * @author Rafael H. Schloming - */ - -public interface Encoder -{ - - void writeUint8(short b); - void writeUint16(int s); - void writeUint32(long i); - void writeUint64(long l); - - void writeDatetime(long l); - void writeUuid(UUID uuid); - - void writeSequenceNo(int s); - void writeSequenceSet(RangeSet ranges); // XXX - void writeByteRanges(RangeSet ranges); // XXX - - void writeStr8(String s); - void writeStr16(String s); - - void writeVbin8(byte[] bytes); - void writeVbin16(byte[] bytes); - void writeVbin32(byte[] bytes); - - void writeStruct32(Struct s); - void writeMap(Map map); - void writeList(List list); - void writeArray(List array); - - void writeStruct(int type, Struct s); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/FragmentDecoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/FragmentDecoder.java deleted file mode 100644 index 474211ced2..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/FragmentDecoder.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.nio.BufferUnderflowException; -import java.nio.ByteBuffer; - -import java.util.Iterator; - -import static java.lang.Math.*; - - -/** - * FragmentDecoder - * - * @author Rafael H. Schloming - */ - -public class FragmentDecoder extends AbstractDecoder -{ - - private final Iterator fragments; - private ByteBuffer current; - - public FragmentDecoder(Iterator fragments) - { - this.fragments = fragments; - this.current = null; - } - - public boolean hasRemaining() - { - advance(); - return current != null || fragments.hasNext(); - } - - private void advance() - { - while (current == null && fragments.hasNext()) - { - current = fragments.next(); - if (current.hasRemaining()) - { - break; - } - else - { - current = null; - } - } - } - - private void preRead() - { - advance(); - - if (current == null) - { - throw new BufferUnderflowException(); - } - } - - private void postRead() - { - if (current.remaining() == 0) - { - current = null; - } - } - - protected byte doGet() - { - preRead(); - byte b = current.get(); - postRead(); - return b; - } - - protected void doGet(byte[] bytes) - { - int remaining = bytes.length; - int offset = 0; - while (remaining > 0) - { - preRead(); - int size = min(remaining, current.remaining()); - current.get(bytes, offset, size); - offset += size; - remaining -= size; - postRead(); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/SizeEncoder.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/SizeEncoder.java deleted file mode 100644 index 2e7e883a0b..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/SizeEncoder.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.nio.ByteBuffer; - -import java.util.Map; -import java.util.UUID; - -import org.apache.qpidity.transport.RangeSet; - - -/** - * SizeEncoder - * - * @author Rafael H. Schloming - */ - -public class SizeEncoder extends AbstractEncoder implements Sizer -{ - - private int size; - - public SizeEncoder() { - this(0); - } - - public SizeEncoder(int size) { - this.size = size; - } - - protected Sizer sizer() - { - return Sizer.NULL; - } - - public int getSize() { - return size; - } - - public void setSize(int size) { - this.size = size; - } - - public int size() - { - return getSize(); - } - - protected void doPut(byte b) - { - size += 1; - } - - protected void doPut(ByteBuffer src) - { - size += src.remaining(); - } - - public void writeUint8(short b) - { - size += 1; - } - - public void writeUint16(int s) - { - size += 2; - } - - public void writeUint32(long i) - { - size += 4; - } - - public void writeUint64(long l) - { - size += 8; - } - - public void writeDatetime(long l) - { - size += 8; - } - - public void writeUuid(UUID uuid) - { - size += 16; - } - - public void writeSequenceNo(int s) - { - size += 4; - } - - public void writeSequenceSet(RangeSet ranges) - { - size += 2 + 8*ranges.size(); - } - - //void writeByteRanges(RangeSet ranges); // XXX - - //void writeStr8(String s); - //void writeStr16(String s); - - //void writeVbin8(byte[] bytes); - //void writeVbin16(byte[] bytes); - //void writeVbin32(byte[] bytes); - - //void writeStruct32(Struct s); - //void writeMap(Map map); - //void writeList(List list); - //void writeArray(List array); - - //void writeStruct(int type, Struct s); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Sizer.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/Sizer.java deleted file mode 100644 index d386987d64..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Sizer.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.codec; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpidity.transport.RangeSet; -import org.apache.qpidity.transport.Struct; - - -/** - * Sizer - * - */ - -public interface Sizer extends Encoder -{ - - public static final Sizer NULL = new Sizer() - { - public void writeUint8(short b) {} - public void writeUint16(int s) {} - public void writeUint32(long i) {} - public void writeUint64(long l) {} - - public void writeDatetime(long l) {} - public void writeUuid(UUID uuid) {} - - public void writeSequenceNo(int s) {} - public void writeSequenceSet(RangeSet ranges) {} // XXX - public void writeByteRanges(RangeSet ranges) {} // XXX - - public void writeStr8(String s) {} - public void writeStr16(String s) {} - - public void writeVbin8(byte[] bytes) {} - public void writeVbin16(byte[] bytes) {} - public void writeVbin32(byte[] bytes) {} - - public void writeStruct32(Struct s) {} - public void writeMap(Map map) {} - public void writeList(List list) {} - public void writeArray(List array) {} - - public void writeStruct(int type, Struct s) {} - - public int getSize() { return 0; } - - public int size() { return 0; } - }; - - int getSize(); - - int size(); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/codec/Validator.java b/java/common/src/main/java/org/apache/qpidity/transport/codec/Validator.java deleted file mode 100644 index 743e9f3cae..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/codec/Validator.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.qpidity.transport.codec; - -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.qpidity.transport.RangeSet; -import org.apache.qpidity.transport.Struct; - - -/** - * Validator - * - */ - -public class Validator -{ - - public static final void checkBit(boolean b) - { - // no illegal values - } - - public static final void checkUint8(short s) - { - if (s > 0xFF || s < 0) - { - throw new IllegalArgumentException("" + s); - } - } - - public static final void checkUint16(int i) - { - if (i > 0xFFFF || i < 0) - { - throw new IllegalArgumentException("" + i); - } - } - - public static final void checkUint32(long l) - { - // XXX: we can't currently validate this because we do thinks - // like pass in -1 for 0xFFFFFFFF - // if (l > 0xFFFFFFFFL || l < 0) - // { - // throw new IllegalArgumentException("" + l); - // } - } - - public static final void checkSequenceNo(int s) - { - // no illegal values - } - - public static final void checkUint64(long l) - { - // no illegal values - } - - public static final void checkDatetime(long l) - { - // no illegal values - } - - public static final void checkUuid(UUID u) - { - // no illegal values - } - - public static final void checkStr8(String value) - { - if (value != null && value.length() > 255) - { - throw new IllegalArgumentException("" + value); - } - } - - public static final void checkStr16(String value) - { - if (value != null && value.length() > 0xFFFF) - { - throw new IllegalArgumentException("" + value); - } - } - - public static final void checkVbin8(byte[] value) - { - if (value != null && value.length > 255) - { - throw new IllegalArgumentException("" + value); - } - } - - public static final void checkVbin16(byte[] value) - { - if (value != null && value.length > 0xFFFF) - { - throw new IllegalArgumentException("" + value); - } - } - - public static final void checkByteRanges(RangeSet r) - { - // no illegal values - } - - public static final void checkSequenceSet(RangeSet r) - { - // no illegal values - } - - public static final void checkVbin32(byte[] value) - { - // no illegal values - } - - public static final void checkStruct32(Struct s) - { - // no illegal values - } - - public static final void checkArray(List array) - { - if (array == null) - { - return; - } - - for (Object o : array) - { - checkObject(o); - } - } - - public static final void checkMap(Map map) - { - if (map == null) - { - return; - } - - for (Map.Entry entry : map.entrySet()) - { - checkStr8(entry.getKey()); - checkObject(entry.getValue()); - } - } - - public static final void checkObject(Object o) - { - if (o != null && AbstractEncoder.resolve(o.getClass()) == null) - { - throw new IllegalArgumentException("cannot encode " + o.getClass()); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/Assembler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/Assembler.java deleted file mode 100644 index 3a7a550573..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/Assembler.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.network; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import java.nio.ByteBuffer; - -import org.apache.qpidity.transport.codec.BBDecoder; -import org.apache.qpidity.transport.codec.Decoder; -import org.apache.qpidity.transport.codec.FragmentDecoder; - -import org.apache.qpidity.transport.ConnectionEvent; -import org.apache.qpidity.transport.Data; -import org.apache.qpidity.transport.Header; -import org.apache.qpidity.transport.Method; -import org.apache.qpidity.transport.ProtocolError; -import org.apache.qpidity.transport.ProtocolEvent; -import org.apache.qpidity.transport.ProtocolHeader; -import org.apache.qpidity.transport.Receiver; -import org.apache.qpidity.transport.SegmentType; -import org.apache.qpidity.transport.Struct; - - -/** - * Assembler - * - */ - -public class Assembler implements Receiver, NetworkDelegate -{ - - private final Receiver receiver; - private final Map> segments; - - public Assembler(Receiver receiver) - { - this.receiver = receiver; - segments = new HashMap>(); - } - - private int segmentKey(Frame frame) - { - // XXX: can this overflow? - return (frame.getTrack() + 1) * frame.getChannel(); - } - - private List getSegment(Frame frame) - { - return segments.get(segmentKey(frame)); - } - - private void setSegment(Frame frame, List segment) - { - int key = segmentKey(frame); - if (segments.containsKey(key)) - { - error(new ProtocolError(Frame.L2, "segment in progress: %s", - frame)); - } - segments.put(segmentKey(frame), segment); - } - - private void clearSegment(Frame frame) - { - segments.remove(segmentKey(frame)); - } - - private void emit(int channel, ProtocolEvent event) - { - receiver.received(new ConnectionEvent(channel, event)); - } - - private void emit(Frame frame, ProtocolEvent event) - { - emit(frame.getChannel(), event); - } - - public void received(NetworkEvent event) - { - event.delegate(this); - } - - public void exception(Throwable t) - { - this.receiver.exception(t); - } - - public void closed() - { - this.receiver.closed(); - } - - public void init(ProtocolHeader header) - { - emit(0, header); - } - - public void frame(Frame frame) - { - switch (frame.getType()) - { - case BODY: - emit(frame, new Data(frame, frame.isFirstFrame(), - frame.isLastFrame())); - break; - default: - assemble(frame); - break; - } - } - - public void error(ProtocolError error) - { - emit(0, error); - } - - private void assemble(Frame frame) - { - List segment; - if (frame.isFirstFrame()) - { - segment = new ArrayList(); - setSegment(frame, segment); - } - else - { - segment = getSegment(frame); - } - - for (ByteBuffer buf : frame) - { - segment.add(buf); - } - - if (frame.isLastFrame()) - { - clearSegment(frame); - emit(frame, decode(frame, frame.getType(), segment)); - } - } - - private ProtocolEvent decode(Frame frame, SegmentType type, List segment) - { - Decoder dec; - if (segment.size() == 1) - { - dec = new BBDecoder(segment.get(0)); - } - else - { - dec = new FragmentDecoder(segment.iterator()); - } - - switch (type) - { - case CONTROL: - int controlType = dec.readUint16(); - Method control = Method.create(controlType); - control.read(dec); - return control; - case COMMAND: - int commandType = dec.readUint16(); - // read in the session header, right now we don't use it - dec.readUint16(); - Method command = Method.create(commandType); - command.read(dec); - return command; - case HEADER: - List structs = new ArrayList(); - while (dec.hasRemaining()) - { - structs.add(dec.readStruct32()); - } - return new Header(structs,frame.isLastFrame() && frame.isLastSegment()); - default: - throw new IllegalStateException("unknown frame type: " + type); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/Disassembler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/Disassembler.java deleted file mode 100644 index da9ba84ab0..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/Disassembler.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.network; - -import org.apache.qpidity.transport.codec.BBEncoder; -import org.apache.qpidity.transport.codec.SizeEncoder; - -import org.apache.qpidity.transport.ConnectionEvent; -import org.apache.qpidity.transport.Data; -import org.apache.qpidity.transport.Header; -import org.apache.qpidity.transport.Method; -import org.apache.qpidity.transport.ProtocolDelegate; -import org.apache.qpidity.transport.ProtocolError; -import org.apache.qpidity.transport.ProtocolEvent; -import org.apache.qpidity.transport.ProtocolHeader; -import org.apache.qpidity.transport.SegmentType; -import org.apache.qpidity.transport.Sender; -import org.apache.qpidity.transport.Struct; - -import java.nio.ByteBuffer; -import java.util.Iterator; - -import static org.apache.qpidity.transport.network.Frame.*; - -import static java.lang.Math.*; - - -/** - * Disassembler - * - */ - -public class Disassembler implements Sender, - ProtocolDelegate -{ - - private final Sender sender; - private final int maxPayload; - - public Disassembler(Sender sender, int maxFrame) - { - if (maxFrame <= HEADER_SIZE || maxFrame >= 64*1024) - { - throw new IllegalArgumentException - ("maxFrame must be > HEADER_SIZE and < 64K: " + maxFrame); - } - this.sender = sender; - this.maxPayload = maxFrame - HEADER_SIZE; - - } - - public void send(ConnectionEvent event) - { - event.getProtocolEvent().delegate(event, this); - } - - public void close() - { - sender.close(); - } - - private void fragment(byte flags, SegmentType type, ConnectionEvent event, - ByteBuffer buf, boolean first, boolean last) - { - byte track = event.getProtocolEvent().getEncodedTrack() == Frame.L4 ? (byte) 1 : (byte) 0; - - if(!buf.hasRemaining()) - { - //empty data - byte nflags = flags; - if (first) - { - nflags |= FIRST_FRAME; - first = false; - } - nflags |= LAST_FRAME; - Frame frame = new Frame(nflags, type, track, event.getChannel()); - // frame.addFragment(buf); - sender.send(frame); - } - else - { - while (buf.hasRemaining()) - { - ByteBuffer slice = buf.slice(); - slice.limit(min(maxPayload, slice.remaining())); - buf.position(buf.position() + slice.remaining()); - - byte newflags = flags; - if (first) - { - newflags |= FIRST_FRAME; - first = false; - } - if (last && !buf.hasRemaining()) - { - newflags |= LAST_FRAME; - } - - Frame frame = new Frame(newflags, type, track, event.getChannel()); - frame.addFragment(slice); - sender.send(frame); - } - } - } - - public void init(ConnectionEvent event, ProtocolHeader header) - { - sender.send(header); - } - - public void control(ConnectionEvent event, Method method) - { - method(event, method, SegmentType.CONTROL); - } - - public void command(ConnectionEvent event, Method method) - { - method(event, method, SegmentType.COMMAND); - } - - private void method(ConnectionEvent event, Method method, SegmentType type) - { - SizeEncoder sizer = new SizeEncoder(); - sizer.writeUint16(method.getEncodedType()); - if (type == SegmentType.COMMAND) - { - sizer.writeUint16(0); - } - method.write(sizer); - - ByteBuffer buf = ByteBuffer.allocate(sizer.size()); - BBEncoder enc = new BBEncoder(buf); - enc.writeUint16(method.getEncodedType()); - if (type == SegmentType.COMMAND) - { - if (method.isSync()) - { - enc.writeUint16(0x0101); - } - else - { - enc.writeUint16(0x0100); - } - } - method.write(enc); - buf.flip(); - - byte flags = FIRST_SEG; - - if (!method.hasPayload()) - { - flags |= LAST_SEG; - } - - fragment(flags, type, event, buf, true, true); - } - - public void header(ConnectionEvent event, Header header) - { - ByteBuffer buf; - if( header.getBuf() == null) - { - SizeEncoder sizer = new SizeEncoder(); - for (Struct st : header.getStructs()) - { - sizer.writeStruct32(st); - } - - buf = ByteBuffer.allocate(sizer.size()); - BBEncoder enc = new BBEncoder(buf); - for (Struct st : header.getStructs()) - { - enc.writeStruct32(st); - } - header.setBuf(buf); - } - else - { - buf = header.getBuf(); - } - buf.flip(); - fragment((byte) 0x0, SegmentType.HEADER, event, buf, true, true); - } - - public void data(ConnectionEvent event, Data data) - { - boolean first = data.isFirst(); - for (Iterator it = data.getFragments().iterator(); - it.hasNext(); ) - { - ByteBuffer buf = it.next(); - boolean last = data.isLast() && !it.hasNext(); - fragment(LAST_SEG, SegmentType.BODY, event, buf, first, last); - first = false; - } - } - - public void error(ConnectionEvent event, ProtocolError error) - { - sender.send(error); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/Frame.java b/java/common/src/main/java/org/apache/qpidity/transport/network/Frame.java deleted file mode 100644 index 2abac382e6..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/Frame.java +++ /dev/null @@ -1,175 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.network; - -import org.apache.qpidity.transport.SegmentType; -import org.apache.qpidity.transport.util.SliceIterator; - -import java.nio.ByteBuffer; - -import java.util.ArrayList; -import java.util.List; -import java.util.Iterator; - -import static org.apache.qpidity.transport.util.Functions.*; - - -/** - * Frame - * - * @author Rafael H. Schloming - */ - -public final class Frame implements NetworkEvent, Iterable -{ - public static final int HEADER_SIZE = 12; - - // XXX: enums? - public static final byte L1 = 0; - public static final byte L2 = 1; - public static final byte L3 = 2; - public static final byte L4 = 3; - - public static final byte RESERVED = 0x0; - - public static final byte VERSION = 0x0; - - public static final byte FIRST_SEG = 0x8; - public static final byte LAST_SEG = 0x4; - public static final byte FIRST_FRAME = 0x2; - public static final byte LAST_FRAME = 0x1; - - final private byte flags; - final private SegmentType type; - final private byte track; - final private int channel; - final private List fragments; - private int size; - - public Frame(byte flags, SegmentType type, byte track, int channel) - { - this.flags = flags; - this.type = type; - this.track = track; - this.channel = channel; - this.size = 0; - this.fragments = new ArrayList(); - } - - public void addFragment(ByteBuffer fragment) - { - fragments.add(fragment); - size += fragment.remaining(); - } - - public byte getFlags() - { - return flags; - } - - public int getChannel() - { - return channel; - } - - public int getSize() - { - return size; - } - - public SegmentType getType() - { - return type; - } - - public byte getTrack() - { - return track; - } - - private boolean flag(byte mask) - { - return (flags & mask) != 0; - } - - public boolean isFirstSegment() - { - return flag(FIRST_SEG); - } - - public boolean isLastSegment() - { - return flag(LAST_SEG); - } - - public boolean isFirstFrame() - { - return flag(FIRST_FRAME); - } - - public boolean isLastFrame() - { - return flag(LAST_FRAME); - } - - public Iterator getFragments() - { - return new SliceIterator(fragments.iterator()); - } - - public Iterator iterator() - { - return getFragments(); - } - - public void delegate(NetworkDelegate delegate) - { - delegate.frame(this); - } - - public String toString() - { - StringBuilder str = new StringBuilder(); - str.append(String.format - ("[%05d %05d %1d %s %d%d%d%d] ", getChannel(), getSize(), - getTrack(), getType(), - isFirstSegment() ? 1 : 0, isLastSegment() ? 1 : 0, - isFirstFrame() ? 1 : 0, isLastFrame() ? 1 : 0)); - - boolean first = true; - for (ByteBuffer buf : this) - { - if (first) - { - first = false; - } - else - { - str.append(" | "); - } - - str.append(str(buf)); - } - - return str.toString(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/InputHandler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/InputHandler.java deleted file mode 100644 index d1c03348b4..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/InputHandler.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.network; - -import java.nio.ByteBuffer; - -import org.apache.qpidity.transport.ProtocolError; -import org.apache.qpidity.transport.ProtocolHeader; -import org.apache.qpidity.transport.Receiver; -import org.apache.qpidity.transport.SegmentType; - -import static org.apache.qpidity.transport.util.Functions.*; - -import static org.apache.qpidity.transport.network.InputHandler.State.*; - - -/** - * InputHandler - * - * @author Rafael H. Schloming - */ - -public class InputHandler implements Receiver -{ - - public enum State - { - PROTO_HDR, - PROTO_HDR_M, - PROTO_HDR_Q, - PROTO_HDR_P, - PROTO_HDR_CLASS, - PROTO_HDR_INSTANCE, - PROTO_HDR_MAJOR, - PROTO_HDR_MINOR, - FRAME_HDR, - FRAME_HDR_TYPE, - FRAME_HDR_SIZE1, - FRAME_HDR_SIZE2, - FRAME_HDR_RSVD1, - FRAME_HDR_TRACK, - FRAME_HDR_CH1, - FRAME_HDR_CH2, - FRAME_HDR_RSVD2, - FRAME_HDR_RSVD3, - FRAME_HDR_RSVD4, - FRAME_HDR_RSVD5, - FRAME_FRAGMENT, - ERROR; - } - - private final Receiver receiver; - private State state; - - private byte instance; - private byte major; - private byte minor; - - private byte flags; - private SegmentType type; - private byte track; - private int channel; - private int size; - private Frame frame; - - public InputHandler(Receiver receiver, State state) - { - this.receiver = receiver; - this.state = state; - } - - public InputHandler(Receiver receiver) - { - this(receiver, PROTO_HDR); - } - - private void init() - { - receiver.received(new ProtocolHeader(instance, major, minor)); - } - - private void frame() - { - assert size == frame.getSize(); - receiver.received(frame); - frame = null; - } - - private void error(String fmt, Object ... args) - { - receiver.received(new ProtocolError(Frame.L1, fmt, args)); - } - - public void received(ByteBuffer buf) - { - while (buf.hasRemaining()) - { - state = next(buf); - } - } - - private State next(ByteBuffer buf) - { - switch (state) { - case PROTO_HDR: - return expect(buf, 'A', PROTO_HDR_M); - case PROTO_HDR_M: - return expect(buf, 'M', PROTO_HDR_Q); - case PROTO_HDR_Q: - return expect(buf, 'Q', PROTO_HDR_P); - case PROTO_HDR_P: - return expect(buf, 'P', PROTO_HDR_CLASS); - case PROTO_HDR_CLASS: - return expect(buf, 1, PROTO_HDR_INSTANCE); - case PROTO_HDR_INSTANCE: - instance = buf.get(); - return PROTO_HDR_MAJOR; - case PROTO_HDR_MAJOR: - major = buf.get(); - return PROTO_HDR_MINOR; - case PROTO_HDR_MINOR: - minor = buf.get(); - init(); - return FRAME_HDR; - case FRAME_HDR: - flags = buf.get(); - return FRAME_HDR_TYPE; - case FRAME_HDR_TYPE: - type = SegmentType.get(buf.get()); - return FRAME_HDR_SIZE1; - case FRAME_HDR_SIZE1: - size = (0xFF & buf.get()) << 8; - return FRAME_HDR_SIZE2; - case FRAME_HDR_SIZE2: - size += 0xFF & buf.get(); - size -= 12; - if (size < 0 || size > (64*1024 - 12)) - { - error("bad frame size: %d", size); - return ERROR; - } - else - { - return FRAME_HDR_RSVD1; - } - case FRAME_HDR_RSVD1: - return expect(buf, 0, FRAME_HDR_TRACK); - case FRAME_HDR_TRACK: - byte b = buf.get(); - if ((b & 0xF0) != 0) { - error("non-zero reserved bits in upper nibble of " + - "frame header byte 5: '%x'", b); - return ERROR; - } else { - track = (byte) (b & 0xF); - return FRAME_HDR_CH1; - } - case FRAME_HDR_CH1: - channel = (0xFF & buf.get()) << 8; - return FRAME_HDR_CH2; - case FRAME_HDR_CH2: - channel += 0xFF & buf.get(); - return FRAME_HDR_RSVD2; - case FRAME_HDR_RSVD2: - return expect(buf, 0, FRAME_HDR_RSVD3); - case FRAME_HDR_RSVD3: - return expect(buf, 0, FRAME_HDR_RSVD4); - case FRAME_HDR_RSVD4: - return expect(buf, 0, FRAME_HDR_RSVD5); - case FRAME_HDR_RSVD5: - if (!expect(buf, 0)) - { - return ERROR; - } - - frame = new Frame(flags, type, track, channel); - if (size > buf.remaining()) { - frame.addFragment(buf.slice()); - buf.position(buf.limit()); - return FRAME_FRAGMENT; - } else { - ByteBuffer payload = buf.slice(); - payload.limit(size); - buf.position(buf.position() + size); - frame.addFragment(payload); - frame(); - return FRAME_HDR; - } - case FRAME_FRAGMENT: - int delta = size - frame.getSize(); - if (delta > buf.remaining()) { - frame.addFragment(buf.slice()); - buf.position(buf.limit()); - return FRAME_FRAGMENT; - } else { - ByteBuffer fragment = buf.slice(); - fragment.limit(delta); - buf.position(buf.position() + delta); - frame.addFragment(fragment); - frame(); - return FRAME_HDR; - } - default: - throw new IllegalStateException(); - } - } - - private State expect(ByteBuffer buf, int expected, State next) - { - return expect(buf, (byte) expected, next); - } - - private State expect(ByteBuffer buf, char expected, State next) - { - return expect(buf, (byte) expected, next); - } - - private State expect(ByteBuffer buf, byte expected, State next) - { - if (expect(buf, expected)) - { - return next; - } - else - { - return ERROR; - } - } - - private boolean expect(ByteBuffer buf, int expected) - { - return expect(buf, (byte) expected); - } - - private boolean expect(ByteBuffer buf, byte expected) - { - byte b = buf.get(); - if (b == expected) - { - return true; - } - else - { - error("expecting '%x', got '%x'", expected, b); - return false; - } - } - - public void exception(Throwable t) - { - receiver.exception(t); - } - - public void closed() - { - receiver.closed(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkDelegate.java b/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkDelegate.java deleted file mode 100644 index 48655edd0c..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkDelegate.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.network; - -import org.apache.qpidity.transport.ProtocolError; -import org.apache.qpidity.transport.ProtocolHeader; - - -/** - * NetworkDelegate - * - * @author Rafael H. Schloming - */ - -public interface NetworkDelegate -{ - - void init(ProtocolHeader header); - - void frame(Frame frame); - - void error(ProtocolError error); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkEvent.java b/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkEvent.java deleted file mode 100644 index 080efee704..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/NetworkEvent.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.qpidity.transport.network; - - -/** - * NetworkEvent - * - */ - -public interface NetworkEvent -{ - - void delegate(NetworkDelegate delegate); - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/OutputHandler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/OutputHandler.java deleted file mode 100644 index b749332fa3..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/OutputHandler.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.network; - -import java.nio.ByteBuffer; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.qpidity.transport.Constant; -import org.apache.qpidity.transport.ProtocolError; -import org.apache.qpidity.transport.ProtocolHeader; -import org.apache.qpidity.transport.Sender; - -import static org.apache.qpidity.transport.network.Frame.*; - - -/** - * OutputHandler - * - */ - -public class OutputHandler implements Sender, NetworkDelegate -{ - - private Sender sender; - private Object lock = new Object(); - private int bytes = 0; - private List frames = new ArrayList(); - - public OutputHandler(Sender sender) - { - this.sender = sender; - } - - public void send(NetworkEvent event) - { - event.delegate(this); - } - - public void close() - { - synchronized (lock) - { - sender.close(); - } - } - - public void init(ProtocolHeader header) - { - synchronized (lock) - { - sender.send(header.toByteBuffer()); - } - } - - public void frame(Frame frame) - { - synchronized (lock) - { - frames.add(frame); - bytes += HEADER_SIZE + frame.getSize(); - - if (frame.isLastFrame() && frame.isLastSegment() || bytes > 64*1024) - { - ByteBuffer buf = ByteBuffer.allocate(bytes); - for (Frame f : frames) - { - buf.put(f.getFlags()); - buf.put((byte) f.getType().getValue()); - buf.putShort((short) (f.getSize() + HEADER_SIZE)); - // RESERVED - buf.put(RESERVED); - buf.put(f.getTrack()); - buf.putShort((short) f.getChannel()); - // RESERVED - buf.putInt(0); - for(ByteBuffer frg : f) - { - buf.put(frg); - } - } - buf.flip(); - - frames.clear(); - bytes = 0; - - sender.send(buf); - } - } - } - - public void error(ProtocolError error) - { - throw new IllegalStateException("XXX"); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoHandler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoHandler.java deleted file mode 100644 index 568526d9db..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoHandler.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.apache.qpidity.transport.network.io; - -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.qpidity.transport.Connection; -import org.apache.qpidity.transport.ConnectionDelegate; -import org.apache.qpidity.transport.Receiver; -import org.apache.qpidity.transport.network.Assembler; -import org.apache.qpidity.transport.network.Disassembler; -import org.apache.qpidity.transport.network.InputHandler; -import org.apache.qpidity.transport.network.OutputHandler; -import org.apache.qpidity.transport.util.Logger; - -/** - * This class provides a synchronous IO implementation using - * the java.io classes. The IoHandler runs in its own thread. - * The following params are configurable via JVM arguments - * TCP_NO_DELAY - amqj.tcpNoDelay - * SO_RCVBUF - amqj.receiveBufferSize - * SO_SNDBUF - amqj.sendBufferSize - */ -public class IoHandler implements Runnable -{ - private static int DEFAULT_READ_WRITE_BUFFER_SIZE = 64 * 1024; - - private Receiver _receiver; - private Socket _socket; - private byte[] _readBuf; - private static AtomicInteger _count = new AtomicInteger(); - private int _readBufferSize; - private int _writeBufferSize; - - private static final Logger log = Logger.get(IoHandler.class); - - private IoHandler() - { - _readBufferSize = Integer.getInteger("amqj.receiveBufferSize",DEFAULT_READ_WRITE_BUFFER_SIZE); - _writeBufferSize = Integer.getInteger("amqj.sendBufferSize",DEFAULT_READ_WRITE_BUFFER_SIZE); - } - - public static final Connection connect(String host, int port, - ConnectionDelegate delegate) - { - IoHandler handler = new IoHandler(); - return handler.connectInternal(host,port,delegate); - } - - private Connection connectInternal(String host, int port, - ConnectionDelegate delegate) - { - try - { - InetAddress address = InetAddress.getByName(host); - _socket = new Socket(); - _socket.setReuseAddress(true); - _socket.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay")); - - log.debug("default-SO_RCVBUF : " + _socket.getReceiveBufferSize()); - log.debug("default-SO_SNDBUF : " + _socket.getSendBufferSize()); - - _socket.setSendBufferSize(_writeBufferSize); - _socket.setReceiveBufferSize(_readBufferSize); - - log.debug("new-SO_RCVBUF : " + _socket.getReceiveBufferSize()); - log.debug("new-SO_SNDBUF : " + _socket.getSendBufferSize()); - - if (address != null) - { - _socket.connect(new InetSocketAddress(address, port)); - } - while (!_socket.isConnected()) - { - - } - - } - catch (SocketException e) - { - throw new RuntimeException("Error connecting to broker",e); - } - catch (IOException e) - { - throw new RuntimeException("Error connecting to broker",e); - } - - IoSender sender = new IoSender(_socket); - Connection con = new Connection - (new Disassembler(new OutputHandler(sender), 64*1024 - 1), - delegate); - - con.setConnectionId(_count.incrementAndGet()); - _receiver = new InputHandler(new Assembler(con), InputHandler.State.PROTO_HDR); - - Thread t = new Thread(this); - t.setName("IO Handler Thread-" + _count.get()); - t.start(); - - return con; - } - - public void run() - { - // I set the read_buffer size simillar to SO_RCVBUF - // Haven't tested with a lower value to see its better or worse - _readBuf = new byte[_readBufferSize]; - try - { - InputStream in = _socket.getInputStream(); - int read = 0; - while(_socket.isConnected()) - { - try - { - read = in.read(_readBuf); - if (read > 0) - { - ByteBuffer b = ByteBuffer.allocate(read); - b.put(_readBuf,0,read); - b.flip(); - _receiver.received(b); - } - } - catch(Exception e) - { - throw new RuntimeException("Error reading from socket input stream",e); - } - } - } - catch (IOException e) - { - throw new RuntimeException("Error getting input stream from the socket",e); - } - finally - { - try - { - _socket.close(); - } - catch(Exception e) - { - log.error(e,"Error closing socket"); - } - } - } - - /** - * Will experiment in a future version with batching - */ - public static void startBatchingFrames(int connectionId) - { - - } - - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoSender.java b/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoSender.java deleted file mode 100644 index 1adde531a6..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/io/IoSender.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.transport.network.io; - -import java.io.IOException; -import java.io.OutputStream; -import java.net.Socket; - -import org.apache.qpidity.transport.Sender; - -public class IoSender implements Sender -{ - private final Object lock = new Object(); - private Socket _socket; - private OutputStream _outStream; - - public IoSender(Socket socket) - { - this._socket = socket; - try - { - _outStream = _socket.getOutputStream(); - } - catch(IOException e) - { - throw new RuntimeException("Error getting output stream for socket",e); - } - } - - /* - * Currently I don't implement any in memory buffering - * and just write straight to the wire. - * I want to experiment with buffering and see if I can - * get more performance, all though latency will suffer - * a bit. - */ - public void send(java.nio.ByteBuffer buf) - { - write(buf); - } - - /* The extra copying sucks. - * If I know for sure that the buf is backed - * by an array then I could do buf.array() - */ - private void write(java.nio.ByteBuffer buf) - { - byte[] array = new byte[buf.remaining()]; - buf.get(array); - if( _socket.isConnected()) - { - synchronized (lock) - { - try - { - _outStream.write(array); - } - catch(Exception e) - { - e.fillInStackTrace(); - throw new RuntimeException("Error trying to write to the socket",e); - } - } - } - else - { - throw new RuntimeException("Trying to write on a closed socket"); - } - } - - /* - * Haven't used this, but the intention is - * to experiment with it in the future. - * Also need to make sure the buffer size - * is configurable - */ - public void setStartBatching() - { - } - - public void close() - { - synchronized (lock) - { - try - { - _socket.close(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaHandler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaHandler.java deleted file mode 100644 index c6855e3d48..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaHandler.java +++ /dev/null @@ -1,305 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.network.mina; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; - -import org.apache.mina.common.*; - -import org.apache.mina.transport.socket.nio.SocketAcceptor; -import org.apache.mina.transport.socket.nio.SocketSessionConfig; -import org.apache.mina.transport.socket.nio.SocketConnector; -import org.apache.mina.filter.ReadThrottleFilterBuilder; -import org.apache.mina.filter.WriteBufferLimitFilterBuilder; -import org.apache.mina.filter.executor.ExecutorFilter; - -import org.apache.qpidity.transport.Binding; -import org.apache.qpidity.transport.Connection; -import org.apache.qpidity.transport.ConnectionDelegate; -import org.apache.qpidity.transport.Receiver; -import org.apache.qpidity.transport.Sender; - -import org.apache.qpidity.transport.util.Logger; - -import org.apache.qpidity.transport.network.Assembler; -import org.apache.qpidity.transport.network.Disassembler; -import org.apache.qpidity.transport.network.InputHandler; -import org.apache.qpidity.transport.network.OutputHandler; - -import static org.apache.qpidity.transport.util.Functions.*; - -/** - * MinaHandler - * - * @author Rafael H. Schloming - */ -//RA making this public until we sort out the package issues -public class MinaHandler implements IoHandler -{ - private static final int MAX_FRAME_SIZE = 64 * 1024 - 1; - /** Default buffer size for pending messages reads */ - private static final String DEFAULT_READ_BUFFER_LIMIT = "262144"; - /** Default buffer size for pending messages writes */ - private static final String DEFAULT_WRITE_BUFFER_LIMIT = "262144"; - private static final int MAX_RCVBUF = 64*1024; - - private static final Logger log = Logger.get(MinaHandler.class); - - static - { - ByteBuffer.setAllocator(new SimpleByteBufferAllocator()); - ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers")); - } - - private final Binding binding; - - private MinaHandler(Binding binding) - { - this.binding = binding; - } - - public void messageReceived(IoSession ssn, Object obj) - { - Attachment attachment = (Attachment) ssn.getAttachment(); - ByteBuffer buf = (ByteBuffer) obj; - try - { - attachment.receiver.received(buf.buf()); - } - catch (Throwable t) - { - log.error(t, "exception handling buffer %s", str(buf.buf())); - throw new RuntimeException(t); - } - } - - public void messageSent(IoSession ssn, Object obj) - { - // do nothing - } - - public void exceptionCaught(IoSession ssn, Throwable e) - { - Attachment attachment = (Attachment) ssn.getAttachment(); - attachment.receiver.exception(e); - } - - /** - * Invoked by MINA when a MINA session for a new connection is created. This method sets up the filter chain on the - * session, which filters the events handled by this handler. The filter chain consists of, handing off events - * to an optional protectio - * - * @param session The MINA session. - * @throws Exception Any underlying exceptions are allowed to fall through to MINA. - */ - public void sessionCreated(IoSession session) throws Exception - { - log.debug("Protocol session created for session " + System.identityHashCode(session)); - - if (Boolean.getBoolean("protectio")) - { - try - { - //Add IO Protection Filters - IoFilterChain chain = session.getFilterChain(); - - session.getFilterChain().addLast("tempExecutorFilterForFilterBuilder", new ExecutorFilter()); - - ReadThrottleFilterBuilder readfilter = new ReadThrottleFilterBuilder(); - readfilter.setMaximumConnectionBufferSize( - Integer.parseInt(System.getProperty("qpid.read.buffer.limit", DEFAULT_READ_BUFFER_LIMIT))); - readfilter.attach(chain); - - WriteBufferLimitFilterBuilder writefilter = new WriteBufferLimitFilterBuilder(); - writefilter.setMaximumConnectionBufferSize( - Integer.parseInt(System.getProperty("qpid.write.buffer.limit", DEFAULT_WRITE_BUFFER_LIMIT))); - writefilter.attach(chain); - session.getFilterChain().remove("tempExecutorFilterForFilterBuilder"); - - log.info("Using IO Read/Write Filter Protection"); - } - catch (Exception e) - { - log.error("Unable to attach IO Read/Write Filter Protection :" + e.getMessage()); - } - } - } - - public void sessionOpened(final IoSession ssn) - { - log.debug("opened: %s", this); - E endpoint = binding.endpoint(new MinaSender(ssn)); - Attachment attachment = - new Attachment(endpoint, binding.receiver(endpoint)); - - // We need to synchronize and notify here because the MINA - // connect future returns the session prior to the attachment - // being set. This is arguably a bug in MINA. - synchronized (ssn) - { - ssn.setAttachment(attachment); - ssn.notifyAll(); - } - } - - public void sessionClosed(IoSession ssn) - { - log.debug("closed: %s", ssn); - Attachment attachment = (Attachment) ssn.getAttachment(); - attachment.receiver.closed(); - ssn.setAttachment(null); - } - - public void sessionIdle(IoSession ssn, IdleStatus status) - { - // do nothing - } - - private static class Attachment - { - - E endpoint; - Receiver receiver; - - Attachment(E endpoint, Receiver receiver) - { - this.endpoint = endpoint; - this.receiver = receiver; - } - } - - public static final void accept(String host, int port, - Binding binding) - throws IOException - { - accept(new InetSocketAddress(host, port), binding); - } - - public static final void accept(SocketAddress address, - Binding binding) - throws IOException - { - IoAcceptor acceptor = new SocketAcceptor(); - acceptor.bind(address, new MinaHandler(binding)); - } - - public static final E connect(String host, int port, - Binding binding) - { - return connect(new InetSocketAddress(host, port), binding); - } - - public static final E connect(SocketAddress address, - Binding binding) - { - MinaHandler handler = new MinaHandler(binding); - SocketConnector connector = new SocketConnector(); - IoServiceConfig acceptorConfig = connector.getDefaultConfig(); - acceptorConfig.setThreadModel(ThreadModel.MANUAL); - SocketSessionConfig scfg = (SocketSessionConfig) acceptorConfig.getSessionConfig(); - scfg.setTcpNoDelay(Boolean.getBoolean("amqj.tcpNoDelay")); - Integer sendBufferSize = Integer.getInteger("amqj.sendBufferSize"); - if (sendBufferSize != null && sendBufferSize > 0) - { - scfg.setSendBufferSize(sendBufferSize); - } - Integer receiveBufferSize = Integer.getInteger("amqj.receiveBufferSize"); - if (receiveBufferSize != null && receiveBufferSize > 0) - { - scfg.setReceiveBufferSize(receiveBufferSize); - } - else if (scfg.getReceiveBufferSize() > MAX_RCVBUF) - { - scfg.setReceiveBufferSize(MAX_RCVBUF); - } - connector.setWorkerTimeout(0); - ConnectFuture cf = connector.connect(address, handler); - cf.join(); - IoSession ssn = cf.getSession(); - - // We need to synchronize and wait here because the MINA - // connect future returns the session prior to the attachment - // being set. This is arguably a bug in MINA. - synchronized (ssn) - { - while (ssn.getAttachment() == null) - { - try - { - ssn.wait(); - } - catch (InterruptedException e) - { - throw new RuntimeException(e); - } - } - } - - Attachment attachment = (Attachment) ssn.getAttachment(); - return attachment.endpoint; - } - - public static final void accept(String host, int port, - ConnectionDelegate delegate) - throws IOException - { - accept(host, port, new ConnectionBinding - (delegate, InputHandler.State.PROTO_HDR)); - } - - public static final Connection connect(String host, int port, - ConnectionDelegate delegate) - { - return connect(host, port, new ConnectionBinding - (delegate, InputHandler.State.PROTO_HDR)); - } - - private static class ConnectionBinding - implements Binding - { - - private final ConnectionDelegate delegate; - private final InputHandler.State state; - - ConnectionBinding(ConnectionDelegate delegate, - InputHandler.State state) - { - this.delegate = delegate; - this.state = state; - } - - public Connection endpoint(Sender sender) - { - // XXX: hardcoded max-frame - return new Connection - (new Disassembler(new OutputHandler(sender), MAX_FRAME_SIZE), delegate); - } - - public Receiver receiver(Connection conn) - { - return new InputHandler(new Assembler(conn), state); - } - - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaSender.java b/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaSender.java deleted file mode 100644 index f0f5731037..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/mina/MinaSender.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.network.mina; - -import org.apache.mina.common.ByteBuffer; -import org.apache.mina.common.CloseFuture; -import org.apache.mina.common.IoSession; -import org.apache.mina.common.WriteFuture; - -import org.apache.qpidity.transport.Sender; -import org.apache.qpidity.transport.TransportException; - - -/** - * MinaSender - */ - -public class MinaSender implements Sender -{ - private static final int TIMEOUT = 2 * 60 * 1000; - - private final IoSession session; - private WriteFuture lastWrite = null; - - public MinaSender(IoSession session) - { - this.session = session; - } - - public void send(java.nio.ByteBuffer buf) - { - if (session.isClosing()) - { - throw new TransportException("attempted to write to a closed socket"); - } - - synchronized (this) - { - lastWrite = session.write(ByteBuffer.wrap(buf)); - } - } - - public synchronized void close() - { - // MINA will sometimes throw away in-progress writes when you - // ask it to close - synchronized (this) - { - if (lastWrite != null) - { - lastWrite.join(); - } - } - CloseFuture closed = session.close(); - closed.join(); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioHandler.java b/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioHandler.java deleted file mode 100644 index a7339427c7..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioHandler.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.apache.qpidity.transport.network.nio; - -import java.io.EOFException; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.net.SocketException; -import java.nio.ByteBuffer; -import java.nio.channels.SocketChannel; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -import org.apache.qpidity.transport.Connection; -import org.apache.qpidity.transport.ConnectionDelegate; -import org.apache.qpidity.transport.Receiver; -import org.apache.qpidity.transport.network.Assembler; -import org.apache.qpidity.transport.network.Disassembler; -import org.apache.qpidity.transport.network.InputHandler; -import org.apache.qpidity.transport.network.OutputHandler; - -public class NioHandler implements Runnable -{ - private Receiver _receiver; - private SocketChannel _ch; - private ByteBuffer _readBuf; - private static Map _handlers = new ConcurrentHashMap(); - private AtomicInteger _count = new AtomicInteger(); - - private NioHandler(){} - - public static final Connection connect(String host, int port, - ConnectionDelegate delegate) - { - NioHandler handler = new NioHandler(); - return handler.connectInternal(host,port,delegate); - } - - private Connection connectInternal(String host, int port, - ConnectionDelegate delegate) - { - try - { - SocketAddress address = new InetSocketAddress(host,port); - _ch = SocketChannel.open(); - _ch.socket().setReuseAddress(true); - _ch.configureBlocking(true); - _ch.socket().setTcpNoDelay(true); - if (address != null) - { - _ch.socket().connect(address); - } - while (_ch.isConnectionPending()) - { - - } - - } - catch (SocketException e) - { - - e.printStackTrace(); - } - catch (IOException e) - { - e.printStackTrace(); - } - - NioSender sender = new NioSender(_ch); - Connection con = new Connection - (new Disassembler(new OutputHandler(sender), 64*1024 - 1), - delegate); - - con.setConnectionId(_count.incrementAndGet()); - _handlers.put(con.getConnectionId(),sender); - - _receiver = new InputHandler(new Assembler(con), InputHandler.State.FRAME_HDR); - - Thread t = new Thread(this); - t.start(); - - return con; - } - - public void run() - { - _readBuf = ByteBuffer.allocate(512); - long read = 0; - while(_ch.isConnected() && _ch.isOpen()) - { - try - { - read = _ch.read(_readBuf); - if (read > 0) - { - _readBuf.flip(); - ByteBuffer b = ByteBuffer.allocate(_readBuf.remaining()); - b.put(_readBuf); - b.flip(); - _readBuf.clear(); - _receiver.received(b); - } - } - catch(Exception e) - { - e.printStackTrace(); - } - } - - //throw new EOFException("The underlying socket/channel has closed"); - } - - public static void startBatchingFrames(int connectionId) - { - NioSender sender = _handlers.get(connectionId); - sender.setStartBatching(); - } - - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioSender.java b/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioSender.java deleted file mode 100644 index 2cfe6c2089..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/network/nio/NioSender.java +++ /dev/null @@ -1,95 +0,0 @@ -package org.apache.qpidity.transport.network.nio; - -import java.nio.ByteBuffer; -import java.nio.channels.SocketChannel; - -import org.apache.qpidity.transport.Sender; - -public class NioSender implements Sender -{ - private final Object lock = new Object(); - private SocketChannel _ch; - private boolean _batch = false; - private ByteBuffer _batcher; - - public NioSender(SocketChannel ch) - { - this._ch = ch; - } - - public void send(java.nio.ByteBuffer buf) - { - if (_batch) - { - //System.out.println(_batcher.position() + " , " + buf.remaining() + " , " + buf.position() + ","+_batcher.capacity()); - if (_batcher.position() + buf.remaining() >= _batcher.capacity()) - { - _batcher.flip(); - write(_batcher); - _batcher.clear(); - if (buf.remaining() > _batcher.capacity()) - { - write(buf); - } - else - { - _batcher.put(buf); - } - } - else - { - _batcher.put(buf); - } - } - else - { - write(buf); - } - } - - private void write(java.nio.ByteBuffer buf) - { - synchronized (lock) - { - if( _ch.isConnected() && _ch.isOpen()) - { - try - { - _ch.write(buf); - } - catch(Exception e) - { - e.fillInStackTrace(); - } - } - else - { - throw new RuntimeException("Trying to write on a closed socket"); - } - - } - } - - public void setStartBatching() - { - _batch = true; - _batcher = ByteBuffer.allocate(1024); - } - - public void close() - { - // MINA will sometimes throw away in-progress writes when you - // ask it to close - synchronized (lock) - { - try - { - _ch.close(); - } - catch(Exception e) - { - e.printStackTrace(); - } - } - } -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/util/Functions.java b/java/common/src/main/java/org/apache/qpidity/transport/util/Functions.java deleted file mode 100644 index 0038cdf118..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/util/Functions.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.util; - -import java.nio.ByteBuffer; - -import static java.lang.Math.*; - - -/** - * Functions - * - * @author Rafael H. Schloming - */ - -public class Functions -{ - - public static final byte lsb(int i) - { - return (byte) (0xFF & i); - } - - public static final byte lsb(long l) - { - return (byte) (0xFF & l); - } - - public static final String str(ByteBuffer buf) - { - return str(buf, buf.remaining()); - } - - public static final String str(ByteBuffer buf, int limit) - { - StringBuilder str = new StringBuilder(); - str.append('"'); - - for (int i = 0; i < min(buf.remaining(), limit); i++) - { - byte c = buf.get(buf.position() + i); - - if (c > 31 && c < 127 && c != '\\') - { - str.append((char)c); - } - else - { - str.append(String.format("\\x%02x", c)); - } - } - - str.append('"'); - - if (limit < buf.remaining()) - { - str.append("..."); - } - - return str.toString(); - } - - public static final String str(byte[] bytes) - { - return str(ByteBuffer.wrap(bytes)); - } - - public static final String str(byte[] bytes, int limit) - { - return str(ByteBuffer.wrap(bytes), limit); - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/util/Logger.java b/java/common/src/main/java/org/apache/qpidity/transport/util/Logger.java deleted file mode 100644 index 0159036a34..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/util/Logger.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport.util; - -import org.slf4j.LoggerFactory; - -/** - * Logger - * - */ - -public final class Logger -{ - - public static final Logger get(Class klass) - { - return new Logger(LoggerFactory.getLogger(klass)); - } - - private final org.slf4j.Logger log; - - private Logger(org.slf4j.Logger log) - { - this.log = log; - } - - public void debug(String message, Object ... args) - { - if (log.isDebugEnabled()) - { - log.debug(String.format(message, args)); - } - } - - public void debug(Throwable t, String message, Object ... args) - { - if (log.isDebugEnabled()) - { - log.debug(String.format(message, args), t); - } - } - - public void error(String message, Object ... args) - { - if (log.isErrorEnabled()) - { - log.error(String.format(message, args)); - } - } - - public void error(Throwable t, String message, Object ... args) - { - if (log.isErrorEnabled()) - { - log.error(String.format(message, args), t); - } - } - - public void warn(String message, Object ... args) - { - if (log.isWarnEnabled()) - { - log.warn(String.format(message, args)); - } - } - - public void warn(Throwable t, String message, Object ... args) - { - if (log.isWarnEnabled()) - { - log.warn(String.format(message, args), t); - } - } - - public void info(String message, Object ... args) - { - if (log.isInfoEnabled()) - { - log.info(String.format(message, args)); - } - } - - public void info(Throwable t, String message, Object ... args) - { - if (log.isInfoEnabled()) - { - log.info(String.format(message, args), t); - } - } - - public void trace(String message, Object ... args) - { - if (log.isTraceEnabled()) - { - log.trace(String.format(message, args)); - } - } - - public void trace(Throwable t, String message, Object ... args) - { - if (log.isTraceEnabled()) - { - log.trace(String.format(message, args), t); - } - } - -} diff --git a/java/common/src/main/java/org/apache/qpidity/transport/util/SliceIterator.java b/java/common/src/main/java/org/apache/qpidity/transport/util/SliceIterator.java deleted file mode 100644 index 32392a3561..0000000000 --- a/java/common/src/main/java/org/apache/qpidity/transport/util/SliceIterator.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.qpidity.transport.util; - -import java.nio.ByteBuffer; - -import java.util.Iterator; - - -/** - * SliceIterator - * - * @author Rafael H. Schloming - */ - -public class SliceIterator implements Iterator -{ - - final private Iterator iterator; - - public SliceIterator(Iterator iterator) - { - this.iterator = iterator; - } - - public boolean hasNext() - { - return iterator.hasNext(); - } - - public ByteBuffer next() - { - return iterator.next().slice(); - } - - public void remove() - { - throw new UnsupportedOperationException(); - } - -} diff --git a/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java new file mode 100644 index 0000000000..b9ca210483 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/transport/ConnectionTest.java @@ -0,0 +1,121 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.transport; + +import org.apache.mina.util.AvailablePortFinder; + +import org.apache.qpid.util.concurrent.Condition; + +import org.apache.qpid.transport.network.ConnectionBinding; +import org.apache.qpid.transport.network.io.IoAcceptor; +import org.apache.qpid.transport.network.io.IoTransport; +import org.apache.qpid.transport.util.Logger; + +import junit.framework.TestCase; + +import java.util.Random; + +/** + * ConnectionTest + */ + +public class ConnectionTest extends TestCase +{ + + private static final Logger log = Logger.get(ConnectionTest.class); + + private int port; + + protected void setUp() throws Exception + { + super.setUp(); + + port = AvailablePortFinder.getNextAvailable(12000); + + ConnectionDelegate server = new ConnectionDelegate() { + public void init(Channel ch, ProtocolHeader hdr) { + ch.getConnection().close(); + } + + public SessionDelegate getSessionDelegate() { + return new SessionDelegate() {}; + } + public void exception(Throwable t) { + log.error(t, "exception caught"); + } + public void closed() {} + }; + + IoAcceptor ioa = new IoAcceptor + ("localhost", port, new ConnectionBinding(server)); + ioa.start(); + } + + private Connection connect(final Condition closed) + { + Connection conn = IoTransport.connect("localhost", port, new ConnectionDelegate() + { + public SessionDelegate getSessionDelegate() + { + return new SessionDelegate() {}; + } + public void exception(Throwable t) + { + t.printStackTrace(); + } + public void closed() + { + if (closed != null) + { + closed.set(); + } + } + }); + + conn.send(new ProtocolHeader(1, 0, 10)); + return conn; + } + + public void testClosedNotificationAndWriteToClosed() throws Exception + { + Condition closed = new Condition(); + Connection conn = connect(closed); + if (!closed.get(3000)) + { + fail("never got notified of connection close"); + } + + Channel ch = conn.getChannel(0); + Session ssn = new Session("test".getBytes()); + ssn.attach(ch); + + try + { + ssn.sessionAttach(ssn.getName()); + fail("writing to a closed socket succeeded"); + } + catch (TransportException e) + { + // expected + } + } + +} diff --git a/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java b/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.java new file mode 100644 index 0000000000..ad45d00e46 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/transport/RangeSetTest.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.transport; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import junit.framework.TestCase; + +import static org.apache.qpid.util.Serial.*; + +/** + * RangeSetTest + * + */ + +public class RangeSetTest extends TestCase +{ + + private void check(RangeSet ranges) + { + List posts = new ArrayList(); + for (Range range : ranges) + { + posts.add(range.getLower()); + posts.add(range.getUpper()); + } + + List sorted = new ArrayList(posts); + Collections.sort(sorted, COMPARATOR); + + assertEquals(posts, sorted); + + int idx = 1; + while (idx + 1 < posts.size()) + { + assertTrue(!eq(posts.get(idx) + 1, posts.get(idx+1))); + idx += 2; + } + } + + public void test1() + { + RangeSet ranges = new RangeSet(); + ranges.add(5, 10); + check(ranges); + ranges.add(15, 20); + check(ranges); + ranges.add(23, 25); + check(ranges); + ranges.add(12, 14); + check(ranges); + ranges.add(0, 1); + check(ranges); + ranges.add(3, 11); + check(ranges); + } + + public void test2() + { + RangeSet rs = new RangeSet(); + check(rs); + + rs.add(1); + assertTrue(rs.includes(1)); + assertTrue(!rs.includes(2)); + assertTrue(!rs.includes(0)); + check(rs); + + rs.add(2); + assertTrue(!rs.includes(0)); + assertTrue(rs.includes(1)); + assertTrue(rs.includes(2)); + assertTrue(!rs.includes(3)); + check(rs); + + rs.add(0); + + assertTrue(!rs.includes(-1)); + assertTrue(rs.includes(0)); + assertTrue(rs.includes(1)); + assertTrue(rs.includes(2)); + assertTrue(!rs.includes(3)); + check(rs); + + rs.add(37); + + assertTrue(!rs.includes(-1)); + assertTrue(rs.includes(0)); + assertTrue(rs.includes(1)); + assertTrue(rs.includes(2)); + assertTrue(!rs.includes(3)); + assertTrue(!rs.includes(36)); + assertTrue(rs.includes(37)); + assertTrue(!rs.includes(38)); + check(rs); + + rs.add(-1); + check(rs); + + rs.add(-3); + check(rs); + + rs.add(1, 20); + assertTrue(!rs.includes(21)); + assertTrue(rs.includes(20)); + check(rs); + } + + public void testAddSelf() + { + RangeSet a = new RangeSet(); + a.add(0, 8); + check(a); + a.add(0, 8); + check(a); + assertEquals(a.size(), 1); + Range range = a.iterator().next(); + assertEquals(range.getLower(), 0); + assertEquals(range.getUpper(), 8); + } + + public void testIntersect1() + { + Range a = new Range(0, 10); + Range b = new Range(9, 20); + Range i1 = a.intersect(b); + Range i2 = b.intersect(a); + assertEquals(i1.getUpper(), 10); + assertEquals(i2.getUpper(), 10); + assertEquals(i1.getLower(), 9); + assertEquals(i2.getLower(), 9); + } + + public void testIntersect2() + { + Range a = new Range(0, 10); + Range b = new Range(11, 20); + assertNull(a.intersect(b)); + assertNull(b.intersect(a)); + } + + public void testIntersect3() + { + Range a = new Range(0, 10); + Range b = new Range(3, 5); + Range i1 = a.intersect(b); + Range i2 = b.intersect(a); + assertEquals(i1.getUpper(), 5); + assertEquals(i2.getUpper(), 5); + assertEquals(i1.getLower(), 3); + assertEquals(i2.getLower(), 3); + } + + public void testSubtract1() + { + Range a = new Range(0, 10); + assertTrue(a.subtract(a).isEmpty()); + } + + public void testSubtract2() + { + Range a = new Range(0, 10); + Range b = new Range(20, 30); + List ranges = a.subtract(b); + assertEquals(ranges.size(), 1); + Range d = ranges.get(0); + assertEquals(d.getLower(), a.getLower()); + assertEquals(d.getUpper(), a.getUpper()); + } + + public void testSubtract3() + { + Range a = new Range(20, 30); + Range b = new Range(0, 10); + List ranges = a.subtract(b); + assertEquals(ranges.size(), 1); + Range d = ranges.get(0); + assertEquals(d.getLower(), a.getLower()); + assertEquals(d.getUpper(), a.getUpper()); + } + + public void testSubtract4() + { + Range a = new Range(0, 10); + Range b = new Range(3, 5); + List ranges = a.subtract(b); + assertEquals(ranges.size(), 2); + Range low = ranges.get(0); + Range high = ranges.get(1); + assertEquals(low.getLower(), 0); + assertEquals(low.getUpper(), 2); + assertEquals(high.getLower(), 6); + assertEquals(high.getUpper(), 10); + } + + public void testSubtract5() + { + Range a = new Range(0, 10); + Range b = new Range(3, 20); + List ranges = a.subtract(b); + assertEquals(ranges.size(), 1); + Range d = ranges.get(0); + assertEquals(d.getLower(), 0); + assertEquals(d.getUpper(), 2); + } + + public void testSubtract6() + { + Range a = new Range(0, 10); + Range b = new Range(-10, 5); + List ranges = a.subtract(b); + assertEquals(ranges.size(), 1); + Range d = ranges.get(0); + assertEquals(d.getLower(), 6); + assertEquals(d.getUpper(), 10); + } + +} diff --git a/java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java b/java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java deleted file mode 100644 index 1a83786e12..0000000000 --- a/java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import org.apache.mina.util.AvailablePortFinder; - -import org.apache.qpid.util.concurrent.Condition; - -import org.apache.qpidity.transport.network.mina.MinaHandler; -import org.apache.qpidity.transport.util.Logger; - -import junit.framework.TestCase; - -import java.util.Random; - -/** - * ConnectionTest - */ - -public class ConnectionTest extends TestCase -{ - - private static final Logger log = Logger.get(ConnectionTest.class); - - private int port; - - protected void setUp() throws Exception - { - super.setUp(); - - port = AvailablePortFinder.getNextAvailable(12000); - - ConnectionDelegate server = new ConnectionDelegate() { - public void init(Channel ch, ProtocolHeader hdr) { - ch.getConnection().close(); - } - - public SessionDelegate getSessionDelegate() { - return new SessionDelegate() {}; - } - public void exception(Throwable t) { - log.error(t, "exception caught"); - } - public void closed() {} - }; - - MinaHandler.accept("localhost", port, server); - } - - private Connection connect(final Condition closed) - { - Connection conn = MinaHandler.connect("localhost", port, new ConnectionDelegate() - { - public SessionDelegate getSessionDelegate() - { - return new SessionDelegate() {}; - } - public void exception(Throwable t) - { - t.printStackTrace(); - } - public void closed() - { - if (closed != null) - { - closed.set(); - } - } - }); - - conn.send(new ConnectionEvent(0, new ProtocolHeader(1, 0, 10))); - return conn; - } - - public void testClosedNotificationAndWriteToClosed() throws Exception - { - Condition closed = new Condition(); - Connection conn = connect(closed); - if (!closed.get(3000)) - { - fail("never got notified of connection close"); - } - - Channel ch = conn.getChannel(0); - Session ssn = new Session("test".getBytes()); - ssn.attach(ch); - - try - { - ssn.sessionAttach(ssn.getName()); - fail("writing to a closed socket succeeded"); - } - catch (TransportException e) - { - // expected - } - } - -} diff --git a/java/common/src/test/java/org/apache/qpidity/transport/RangeSetTest.java b/java/common/src/test/java/org/apache/qpidity/transport/RangeSetTest.java deleted file mode 100644 index 474d47d8d7..0000000000 --- a/java/common/src/test/java/org/apache/qpidity/transport/RangeSetTest.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.transport; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import junit.framework.TestCase; - -import static org.apache.qpid.util.Serial.*; - -/** - * RangeSetTest - * - */ - -public class RangeSetTest extends TestCase -{ - - private void check(RangeSet ranges) - { - List posts = new ArrayList(); - for (Range range : ranges) - { - posts.add(range.getLower()); - posts.add(range.getUpper()); - } - - List sorted = new ArrayList(posts); - Collections.sort(sorted, COMPARATOR); - - assertEquals(posts, sorted); - - int idx = 1; - while (idx + 1 < posts.size()) - { - assertTrue(!eq(posts.get(idx) + 1, posts.get(idx+1))); - idx += 2; - } - } - - public void test1() - { - RangeSet ranges = new RangeSet(); - ranges.add(5, 10); - check(ranges); - ranges.add(15, 20); - check(ranges); - ranges.add(23, 25); - check(ranges); - ranges.add(12, 14); - check(ranges); - ranges.add(0, 1); - check(ranges); - ranges.add(3, 11); - check(ranges); - } - - public void test2() - { - RangeSet rs = new RangeSet(); - check(rs); - - rs.add(1); - assertTrue(rs.includes(1)); - assertTrue(!rs.includes(2)); - assertTrue(!rs.includes(0)); - check(rs); - - rs.add(2); - assertTrue(!rs.includes(0)); - assertTrue(rs.includes(1)); - assertTrue(rs.includes(2)); - assertTrue(!rs.includes(3)); - check(rs); - - rs.add(0); - - assertTrue(!rs.includes(-1)); - assertTrue(rs.includes(0)); - assertTrue(rs.includes(1)); - assertTrue(rs.includes(2)); - assertTrue(!rs.includes(3)); - check(rs); - - rs.add(37); - - assertTrue(!rs.includes(-1)); - assertTrue(rs.includes(0)); - assertTrue(rs.includes(1)); - assertTrue(rs.includes(2)); - assertTrue(!rs.includes(3)); - assertTrue(!rs.includes(36)); - assertTrue(rs.includes(37)); - assertTrue(!rs.includes(38)); - check(rs); - - rs.add(-1); - check(rs); - - rs.add(-3); - check(rs); - - rs.add(1, 20); - assertTrue(!rs.includes(21)); - assertTrue(rs.includes(20)); - check(rs); - } - - public void testAddSelf() - { - RangeSet a = new RangeSet(); - a.add(0, 8); - check(a); - a.add(0, 8); - check(a); - assertEquals(a.size(), 1); - Range range = a.iterator().next(); - assertEquals(range.getLower(), 0); - assertEquals(range.getUpper(), 8); - } - - public void testIntersect1() - { - Range a = new Range(0, 10); - Range b = new Range(9, 20); - Range i1 = a.intersect(b); - Range i2 = b.intersect(a); - assertEquals(i1.getUpper(), 10); - assertEquals(i2.getUpper(), 10); - assertEquals(i1.getLower(), 9); - assertEquals(i2.getLower(), 9); - } - - public void testIntersect2() - { - Range a = new Range(0, 10); - Range b = new Range(11, 20); - assertNull(a.intersect(b)); - assertNull(b.intersect(a)); - } - - public void testIntersect3() - { - Range a = new Range(0, 10); - Range b = new Range(3, 5); - Range i1 = a.intersect(b); - Range i2 = b.intersect(a); - assertEquals(i1.getUpper(), 5); - assertEquals(i2.getUpper(), 5); - assertEquals(i1.getLower(), 3); - assertEquals(i2.getLower(), 3); - } - - public void testSubtract1() - { - Range a = new Range(0, 10); - assertTrue(a.subtract(a).isEmpty()); - } - - public void testSubtract2() - { - Range a = new Range(0, 10); - Range b = new Range(20, 30); - List ranges = a.subtract(b); - assertEquals(ranges.size(), 1); - Range d = ranges.get(0); - assertEquals(d.getLower(), a.getLower()); - assertEquals(d.getUpper(), a.getUpper()); - } - - public void testSubtract3() - { - Range a = new Range(20, 30); - Range b = new Range(0, 10); - List ranges = a.subtract(b); - assertEquals(ranges.size(), 1); - Range d = ranges.get(0); - assertEquals(d.getLower(), a.getLower()); - assertEquals(d.getUpper(), a.getUpper()); - } - - public void testSubtract4() - { - Range a = new Range(0, 10); - Range b = new Range(3, 5); - List ranges = a.subtract(b); - assertEquals(ranges.size(), 2); - Range low = ranges.get(0); - Range high = ranges.get(1); - assertEquals(low.getLower(), 0); - assertEquals(low.getUpper(), 2); - assertEquals(high.getLower(), 6); - assertEquals(high.getUpper(), 10); - } - - public void testSubtract5() - { - Range a = new Range(0, 10); - Range b = new Range(3, 20); - List ranges = a.subtract(b); - assertEquals(ranges.size(), 1); - Range d = ranges.get(0); - assertEquals(d.getLower(), 0); - assertEquals(d.getUpper(), 2); - } - - public void testSubtract6() - { - Range a = new Range(0, 10); - Range b = new Range(-10, 5); - List ranges = a.subtract(b); - assertEquals(ranges.size(), 1); - Range d = ranges.get(0); - assertEquals(d.getLower(), 6); - assertEquals(d.getUpper(), 10); - } - -} -- cgit v1.2.1