diff options
author | Rafael H. Schloming <rhs@apache.org> | 2008-04-16 13:32:13 +0000 |
---|---|---|
committer | Rafael H. Schloming <rhs@apache.org> | 2008-04-16 13:32:13 +0000 |
commit | d054b41aaa1466b65c9dc2acf1b22ca98ec3128c (patch) | |
tree | 08055eba3020d3dcad5c9a9587d98b15d0b97c89 | |
parent | f375be1908ad22329fe9ed21a8c196475ade7e59 (diff) | |
download | qpid-python-d054b41aaa1466b65c9dc2acf1b22ca98ec3128c.tar.gz |
QPID-901: updates to the java client to use the 0-10 final spec instead of the 0-10 preview spec; this includes improvements to the codegen process as well as some modifications to the shared code path in the client to not lose per message state when consumers are closed.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@648692 13f79535-47bb-0310-9956-ffa450edef68
114 files changed, 1903 insertions, 13587 deletions
diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java index a9257ccf70..8bb27847ce 100755 --- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DeclareQueue.java @@ -31,13 +31,13 @@ public class DeclareQueue // declare and bind queue session.queueDeclare("message_queue", null, null); - session.queueBind("message_queue", "amq.direct", "routing_key", null); + session.exchangeBind("message_queue", "amq.direct", "routing_key", null); // confirm completion session.sync(); //cleanup - session.sessionClose(); + session.sessionDetach(session.getName()); try { con.close(); diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java index 7c27051fb2..7329792a2b 100755 --- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/DirectProducer.java @@ -8,6 +8,8 @@ import org.apache.qpidity.nclient.Connection; import org.apache.qpidity.nclient.Session; import org.apache.qpidity.nclient.util.MessageListener; import org.apache.qpidity.transport.DeliveryProperties; +import org.apache.qpidity.transport.MessageAcceptMode; +import org.apache.qpidity.transport.MessageAcquireMode; public class DirectProducer implements MessageListener { @@ -65,13 +67,13 @@ public class DirectProducer implements MessageListener for (int i=0; i<10; i++) { - session.messageTransfer("amq.direct", Session.TRANSFER_CONFIRM_MODE_REQUIRED, Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE); + session.messageTransfer("amq.direct", MessageAcceptMode.EXPLICIT,MessageAcquireMode.PRE_ACQUIRED); session.header(deliveryProps); session.data("Message " + i); session.endData(); } - session.messageTransfer("amq.direct", Session.TRANSFER_CONFIRM_MODE_REQUIRED, Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE); + session.messageTransfer("amq.direct", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED); session.header(deliveryProps); session.data("That's all, folks!"); session.endData(); @@ -80,7 +82,7 @@ public class DirectProducer implements MessageListener session.sync(); //cleanup - session.sessionClose(); + session.sessionDetach(session.getName()); try { con.close(); diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java index 244dbdbeae..b199c3a69a 100755 --- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/direct/Listener.java @@ -9,6 +9,8 @@ import org.apache.qpidity.nclient.Session; import org.apache.qpidity.nclient.util.MessageListener; import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; +import org.apache.qpidity.transport.MessageCreditUnit; + /** * This listens to messages on a queue and terminates * when it sees the final message @@ -84,8 +86,9 @@ public class Listener implements MessageListener // issue credits - session.messageFlow("listener_destination", Session.MESSAGE_FLOW_UNIT_BYTE, Session.MESSAGE_FLOW_MAX_BYTES); - session.messageFlow("listener_destination", Session.MESSAGE_FLOW_UNIT_MESSAGE, 11); + // XXX + session.messageFlow("listener_destination", MessageCreditUnit.BYTE, Session.MESSAGE_FLOW_MAX_BYTES); + session.messageFlow("listener_destination", MessageCreditUnit.MESSAGE, 11); // confirm completion session.sync(); @@ -96,7 +99,7 @@ public class Listener implements MessageListener session.messageCancel("listener_destination"); //cleanup - session.sessionClose(); + session.sessionDetach(session.getName()); try { diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java index cb49e9d28f..67f24148d8 100755 --- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/DeclareQueue.java @@ -31,13 +31,13 @@ public class DeclareQueue // declare and bind queue session.queueDeclare("message_queue", null, null); - session.queueBind("message_queue", "amq.fanout",null, null); + session.exchangeBind("message_queue", "amq.fanout",null, null); // confirm completion session.sync(); //cleanup - session.sessionClose(); + session.sessionDetach(session.getName()); try { con.close(); diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java index 1dfc468cd4..4c647fde36 100755 --- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/FannoutProducer.java @@ -4,6 +4,8 @@ import org.apache.qpidity.nclient.Client; import org.apache.qpidity.nclient.Connection; import org.apache.qpidity.nclient.Session; import org.apache.qpidity.transport.DeliveryProperties; +import org.apache.qpidity.transport.MessageAcceptMode; +import org.apache.qpidity.transport.MessageAcquireMode; public class FannoutProducer { @@ -32,13 +34,13 @@ public class FannoutProducer for (int i=0; i<10; i++) { - session.messageTransfer("amq.fanout", Session.TRANSFER_CONFIRM_MODE_REQUIRED, Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE); + session.messageTransfer("amq.fanout", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED); session.header(deliveryProps); session.data("Message " + i); session.endData(); } - session.messageTransfer("amq.fanout", Session.TRANSFER_CONFIRM_MODE_REQUIRED, Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE); + session.messageTransfer("amq.fanout", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED); session.header(deliveryProps); session.data("That's all, folks!"); session.endData(); @@ -47,7 +49,7 @@ public class FannoutProducer session.sync(); //cleanup - session.sessionClose(); + session.sessionDetach(session.getName()); try { con.close(); diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java index cf12e80b5c..1feb5cfe23 100755 --- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/fanout/Listener.java @@ -9,6 +9,10 @@ import org.apache.qpidity.nclient.Session; import org.apache.qpidity.nclient.util.MessageListener; import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; +import org.apache.qpidity.transport.MessageAcceptMode; +import org.apache.qpidity.transport.MessageAcquireMode; +import org.apache.qpidity.transport.MessageCreditUnit; + /** * This listens to messages on a queue and terminates * when it sees the final message @@ -83,8 +87,9 @@ public class Listener implements MessageListener // issue credits - session.messageFlow("listener_destination", Session.MESSAGE_FLOW_UNIT_BYTE, Session.MESSAGE_FLOW_MAX_BYTES); - session.messageFlow("listener_destination", Session.MESSAGE_FLOW_UNIT_MESSAGE, 11); + // XXX + session.messageFlow("listener_destination", MessageCreditUnit.BYTE, Session.MESSAGE_FLOW_MAX_BYTES); + session.messageFlow("listener_destination", MessageCreditUnit.MESSAGE, 11); // confirm completion session.sync(); @@ -95,7 +100,7 @@ public class Listener implements MessageListener session.messageCancel("listener_destination"); //cleanup - session.sessionClose(); + session.sessionDetach(session.getName()); try { con.close(); diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java index e5c560860e..f26e5418b4 100755 --- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicListener.java @@ -8,6 +8,7 @@ import org.apache.qpidity.nclient.Connection; import org.apache.qpidity.nclient.Session; import org.apache.qpidity.nclient.util.MessageListener; import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; +import org.apache.qpidity.transport.MessageCreditUnit; import org.apache.qpidity.transport.Option; @@ -44,11 +45,11 @@ public class TopicListener implements MessageListener } } - public void prepareQueue(Session session,String queueName,String routingKey) + public void prepareQueue(Session session,String queueName,String bindingKey) { session.queueDeclare(queueName, null, null, Option.EXCLUSIVE, Option.AUTO_DELETE); - session.queueBind(queueName, "amq.topic", routingKey, null); - session.queueBind(queueName, "amq.topic", "control", null); + session.exchangeBind(queueName, "amq.topic", bindingKey, null); + session.exchangeBind(queueName, "amq.topic", "control", null); session.messageSubscribe(queueName,queueName, Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED, @@ -56,8 +57,9 @@ public class TopicListener implements MessageListener new MessagePartListenerAdapter(this), null, Option.NO_OPTION); // issue credits - session.messageFlow(queueName, Session.MESSAGE_FLOW_UNIT_BYTE, Session.MESSAGE_FLOW_MAX_BYTES); - session.messageFlow(queueName, Session.MESSAGE_FLOW_UNIT_MESSAGE, 24); + // XXX: need to be able to set to null + session.messageFlow(queueName, MessageCreditUnit.BYTE, Session.MESSAGE_FLOW_MAX_BYTES); + session.messageFlow(queueName, MessageCreditUnit.MESSAGE, 24); } public void cancelSubscription(Session session,String dest) @@ -106,7 +108,7 @@ public class TopicListener implements MessageListener listener.cancelSubscription(session,"weather"); //cleanup - session.sessionClose(); + session.sessionDetach(session.getName()); try { con.close(); diff --git a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java index b33a6b967b..c960643504 100755 --- a/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java +++ b/java/client/example/src/main/java/org/apache/qpid/example/amqpexample/pubsub/TopicPublisher.java @@ -4,6 +4,8 @@ import org.apache.qpidity.nclient.Client; import org.apache.qpidity.nclient.Connection; import org.apache.qpidity.nclient.Session; import org.apache.qpidity.transport.DeliveryProperties; +import org.apache.qpidity.transport.MessageAcceptMode; +import org.apache.qpidity.transport.MessageAcquireMode; public class TopicPublisher { @@ -16,7 +18,7 @@ public class TopicPublisher deliveryProps.setRoutingKey(routing_key); for (int i=0; i<5; i++) { - session.messageTransfer("amq.topic", Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED,Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE); + session.messageTransfer("amq.topic", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED); session.header(deliveryProps); session.data("Message " + i); session.endData(); @@ -26,7 +28,7 @@ public class TopicPublisher public void noMoreMessages(Session session) { - session.messageTransfer("amq.topic", Session.TRANSFER_CONFIRM_MODE_REQUIRED, Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE); + session.messageTransfer("amq.topic", MessageAcceptMode.EXPLICIT, MessageAcquireMode.PRE_ACQUIRED); session.header(new DeliveryProperties().setRoutingKey("control")); session.data("That's all, folks!"); session.endData(); @@ -61,7 +63,7 @@ public class TopicPublisher session.sync(); //cleanup - session.sessionClose(); + session.sessionDetach(session.getName()); try { con.close(); diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java index a6c7b70bf6..f79523e546 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; @@ -201,8 +202,18 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess */ private final AtomicLong _highestDeliveryTag = new AtomicLong(-1); + /** + * All the not yet acknowledged message tags + */ + protected ConcurrentLinkedQueue<Long> _unacknowledgedMessageTags = new ConcurrentLinkedQueue<Long>(); + + /** + * All the delivered message tags + */ + protected ConcurrentLinkedQueue<Long> _deliveredMessageTags = new ConcurrentLinkedQueue<Long>(); + /** Holds the dispatcher thread for this session. */ - private Dispatcher _dispatcher; + protected Dispatcher _dispatcher; /** Holds the message factory factory for this session. */ protected MessageFactoryRegistry _messageFactoryRegistry; @@ -372,9 +383,14 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess throw new IllegalStateException("Session is already closed"); } - for (BasicMessageConsumer consumer : _consumers.values()) + while (true) { - consumer.acknowledge(); + Long tag = _unacknowledgedMessageTags.poll(); + if (tag == null) + { + break; + } + acknowledgeMessage(tag, false); } } @@ -553,15 +569,19 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess try { - // Acknowledge up to message last delivered (if any) for each consumer. - // need to send ack for messages delivered to consumers so far - for (Iterator<BasicMessageConsumer> i = _consumers.values().iterator(); i.hasNext();) + // Acknowledge all delivered messages + while (true) { - // Sends acknowledgement to server - i.next().acknowledgeLastDelivered(); + Long tag = _deliveredMessageTags.poll(); + if (tag == null) + { + break; + } + + acknowledgeMessage(tag, false); } - // Commits outstanding messages sent and outstanding acknowledgements. + // Commits outstanding messages and acknowledgments sendCommit(); } catch (AMQException e) @@ -1136,6 +1156,16 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess return _suspended; } + protected void addUnacknowledgedMessage(long id) + { + _unacknowledgedMessageTags.add(id); + } + + protected void addDeliveredMessage(long id) + { + _deliveredMessageTags.add(id); + } + /** * Invoked by the MINA IO thread (indirectly) when a message is received from the transport. Puts the message onto * the queue read by the dispatcher. @@ -1167,7 +1197,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess { AMQProtocolHandler protocolHandler = getProtocolHandler(); declareExchange(amqd, protocolHandler, false); - AMQShortString queueName = declareQueue(amqd, protocolHandler); + AMQShortString queueName = declareQueue(amqd, protocolHandler, false); bindQueue(queueName, amqd.getRoutingKey(), new FieldTable(), amqd.getExchangeName(),amqd); } @@ -1215,11 +1245,6 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess suspendChannel(true); } - for (BasicMessageConsumer consumer : _consumers.values()) - { - consumer.clearUnackedMessages(); - } - if (_dispatcher != null) { _dispatcher.rollback(); @@ -1296,10 +1321,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess suspendChannel(true); } - if (_dispatcher != null) - { - _dispatcher.rollback(); - } + releaseForRollback(); sendRollback(); @@ -1319,6 +1341,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess } } + public abstract void releaseForRollback(); + public abstract void sendRollback() throws AMQException, FailoverException ; @@ -1973,7 +1997,8 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess * * @todo Be aware of possible changes to parameter order as versions change. */ - protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler) + protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler, + final boolean noLocal) throws AMQException { /*return new FailoverRetrySupport<AMQShortString, AMQException>(*/ @@ -2111,7 +2136,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess declareExchange(amqd, protocolHandler, false); - AMQShortString queueName = declareQueue(amqd, protocolHandler); + AMQShortString queueName = declareQueue(amqd, protocolHandler, consumer.isNoLocal()); // store the consumer queue name consumer.setQueuename(queueName); @@ -2317,7 +2342,7 @@ public abstract class AMQSession extends Closeable implements Session, QueueSess public abstract void sendSuspendChannel(boolean suspend) throws AMQException, FailoverException; /** Responsible for decoding a message fragment and passing it to the appropriate message consumer. */ - private class Dispatcher extends Thread + class Dispatcher extends Thread { /** Track the 'stopped' state of the dispatcher, a session starts in the stopped state. */ diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java index 16d5a07141..2d60877c5e 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java @@ -31,9 +31,11 @@ import org.apache.qpidity.nclient.Session; import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; import org.apache.qpidity.ErrorCode; import org.apache.qpidity.QpidException; +import org.apache.qpidity.transport.MessageCreditUnit; +import org.apache.qpidity.transport.MessageFlowMode; import org.apache.qpidity.transport.RangeSet; import org.apache.qpidity.transport.Option; -import org.apache.qpidity.transport.BindingQueryResult; +import org.apache.qpidity.transport.ExchangeBoundResult; import org.apache.qpidity.transport.Future; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,6 +44,7 @@ import javax.jms.*; import javax.jms.IllegalStateException; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.HashMap; import java.util.UUID; import java.util.Map; @@ -68,11 +71,6 @@ public class AMQSession_0_10 extends AMQSession private Object _currentExceptionLock = new Object(); private QpidException _currentException; - /** - * All the not yet acknoledged message tags - */ - private ConcurrentLinkedQueue<Long> _unacknowledgedMessageTags = new ConcurrentLinkedQueue<Long>(); - //--- constructors /** @@ -125,19 +123,6 @@ public class AMQSession_0_10 extends AMQSession defaultPrefetchHigh, defaultPrefetchLow); } - //------- 0-10 specific methods - - /** - * Add a message tag to be acknowledged - * This is used for client ack mode - * - * @param tag The id of the message to be acknowledged - */ - void addMessageTag(long tag) - { - _unacknowledgedMessageTags.add(tag); - } - //------- overwritten methods of class AMQSession public TopicSubscriber createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal) @@ -219,7 +204,7 @@ public class AMQSession_0_10 extends AMQSession for (AMQShortString rk: destination.getBindingKeys()) { _logger.debug("Binding queue : " + queueName.toString() + " exchange: " + exchangeName.toString() + " using binding key " + rk.asString()); - getQpidSession().queueBind(queueName.toString(), exchangeName.toString(), rk.toString(), args); + getQpidSession().exchangeBind(queueName.toString(), exchangeName.toString(), rk.toString(), args); } // We need to sync so that we get notify of an error. getQpidSession().sync(); @@ -237,7 +222,8 @@ public class AMQSession_0_10 extends AMQSession public void sendClose(long timeout) throws AMQException, FailoverException { getQpidSession().sync(); - getQpidSession().sessionClose(); + getQpidSession().sessionRequestTimeout(0); + getQpidSession().sessionDetach(getQpidSession().getName()); getCurrentException(); } @@ -285,18 +271,43 @@ public class AMQSession_0_10 extends AMQSession public void sendRecover() throws AMQException, FailoverException { // release all unack messages - /*RangeSet ranges = new RangeSet(); - for (long messageTag : _unacknowledgedMessageTags) + RangeSet ranges = new RangeSet(); + while (true) { - // release this message - ranges.add(messageTag); - }*/ - getQpidSession().messageRecover(Option.REQUEUE); + Long tag = _unacknowledgedMessageTags.poll(); + if (tag == null) + { + break; + } + ranges.add(tag); + } + getQpidSession().messageRelease(ranges, Option.SET_REDELIVERED); // We need to sync so that we get notify of an error. getQpidSession().sync(); getCurrentException(); } + public void releaseForRollback() + { + if (_dispatcher != null) + { + _dispatcher.rollback(); + } + + RangeSet ranges = new RangeSet(); + while (true) + { + Long tag = _deliveredMessageTags.poll(); + if (tag == null) + { + break; + } + + ranges.add(tag); + } + getQpidSession().messageRelease(ranges, Option.SET_REDELIVERED); + } + /** * Release (0_8 notion of Reject) an acquired message * @@ -308,7 +319,7 @@ public class AMQSession_0_10 extends AMQSession // The value of requeue is always true RangeSet ranges = new RangeSet(); ranges.add(deliveryTag); - getQpidSession().messageRelease(ranges); + getQpidSession().messageRelease(ranges, Option.SET_REDELIVERED); //I don't think we need to sync } @@ -357,9 +368,8 @@ public class AMQSession_0_10 extends AMQSession rk = routingKey.toString(); } - Future<BindingQueryResult> result = - getQpidSession().bindingQuery(exchangeName.toString(),queueName.toString(), rk, null); - BindingQueryResult bindingQueryResult = result.get(); + ExchangeBoundResult bindingQueryResult = + getQpidSession().exchangeBound(exchangeName.toString(),queueName.toString(), rk, null).get(); if (rk == null) { @@ -394,25 +404,25 @@ public class AMQSession_0_10 extends AMQSession (Boolean.getBoolean("noAck") ?Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED:Session.TRANSFER_CONFIRM_MODE_REQUIRED), preAcquire ? Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE : Session.TRANSFER_ACQUIRE_MODE_NO_ACQUIRE, new MessagePartListenerAdapter((BasicMessageConsumer_0_10) consumer), null, - consumer.isNoLocal() ? Option.NO_LOCAL : Option.NO_OPTION, consumer.isExclusive() ? Option.EXCLUSIVE : Option.NO_OPTION); + if (ClientProperties.MAX_PREFETCH == 0) { - getQpidSession().messageFlowMode(consumer.getConsumerTag().toString(), Session.MESSAGE_FLOW_MODE_CREDIT); + getQpidSession().messageSetFlowMode(consumer.getConsumerTag().toString(), MessageFlowMode.CREDIT); } else { - getQpidSession().messageFlowMode(consumer.getConsumerTag().toString(), Session.MESSAGE_FLOW_MODE_WINDOW); + getQpidSession().messageSetFlowMode(consumer.getConsumerTag().toString(), MessageFlowMode.WINDOW); } - getQpidSession().messageFlow(consumer.getConsumerTag().toString(), Session.MESSAGE_FLOW_UNIT_BYTE, 0xFFFFFFFF); + getQpidSession().messageFlow(consumer.getConsumerTag().toString(), MessageCreditUnit.BYTE, 0xFFFFFFFF); // We need to sync so that we get notify of an error. // only if not immediat prefetch if(ClientProperties.MAX_PREFETCH > 0 && (consumer.isStrated() || _immediatePrefetch)) { // set the flow getQpidSession().messageFlow(consumer.getConsumerTag().toString(), - org.apache.qpidity.nclient.Session.MESSAGE_FLOW_UNIT_MESSAGE, - ClientProperties.MAX_PREFETCH); + MessageCreditUnit.MESSAGE, + ClientProperties.MAX_PREFETCH); } getQpidSession().sync(); getCurrentException(); @@ -458,7 +468,8 @@ public class AMQSession_0_10 extends AMQSession /** * Declare a queue with the given queueName */ - public AMQShortString send0_10QueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler) + public AMQShortString send0_10QueueDeclare(final AMQDestination amqd, final AMQProtocolHandler protocolHandler, + final boolean noLocal) throws AMQException, FailoverException { AMQShortString res; @@ -471,10 +482,16 @@ public class AMQSession_0_10 extends AMQSession { res = amqd.getAMQQueueName(); } - getQpidSession().queueDeclare(res.toString(), null, null, + Map<String,Object> arguments = null; + if (noLocal) + { + arguments = new HashMap<String,Object>(); + arguments.put("no-local", true); + } + getQpidSession().queueDeclare(res.toString(), null, arguments, amqd.isAutoDelete() ? Option.AUTO_DELETE : Option.NO_OPTION, amqd.isDurable() ? Option.DURABLE : Option.NO_OPTION, - amqd.isExclusive() ? Option.EXCLUSIVE : Option.NO_OPTION); + !amqd.isDurable() && amqd.isExclusive() ? Option.EXCLUSIVE : Option.NO_OPTION); // passive --> false // We need to sync so that we get notify of an error. getQpidSession().sync(); @@ -519,18 +536,17 @@ public class AMQSession_0_10 extends AMQSession if (consumer.getMessageListener() != null) { getQpidSession().messageFlow(consumer.getConsumerTag().toString(), - Session.MESSAGE_FLOW_UNIT_MESSAGE, 1); + MessageCreditUnit.MESSAGE, 1); } } else { getQpidSession() - .messageFlow(consumer.getConsumerTag().toString(), Session.MESSAGE_FLOW_UNIT_MESSAGE, - ClientProperties.MAX_PREFETCH); + .messageFlow(consumer.getConsumerTag().toString(), MessageCreditUnit.MESSAGE, + ClientProperties.MAX_PREFETCH); } getQpidSession() - .messageFlow(consumer.getConsumerTag().toString(), Session.MESSAGE_FLOW_UNIT_BYTE, - 0xFFFFFFFF); + .messageFlow(consumer.getConsumerTag().toString(), MessageCreditUnit.BYTE, 0xFFFFFFFF); } catch (Exception e) { @@ -546,8 +562,8 @@ public class AMQSession_0_10 extends AMQSession public void sendRollback() throws AMQException, FailoverException { - getQpidSession().txRollback(); - // We need to sync so that we get notify of an error. + getQpidSession().txRollback(); + // We need to sync so that we get notify of an error. getQpidSession().sync(); getCurrentException(); } @@ -622,7 +638,8 @@ public class AMQSession_0_10 extends AMQSession } } - protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler) + protected AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler, + final boolean noLocal) throws AMQException { /*return new FailoverRetrySupport<AMQShortString, AMQException>(*/ @@ -636,7 +653,7 @@ public class AMQSession_0_10 extends AMQSession { amqd.setQueueName(new AMQShortString("TempQueue" + UUID.randomUUID())); } - return send0_10QueueDeclare(amqd, protocolHandler); + return send0_10QueueDeclare(amqd, protocolHandler, noLocal); } }, _connection).execute(); } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java index a087f9e02a..dd0fd9c457 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_8.java @@ -146,6 +146,8 @@ public class AMQSession_0_8 extends AMQSession public void sendRecover() throws AMQException, FailoverException { + _unacknowledgedMessageTags.clear(); + if (isStrictAMQP()) { // We can't use the BasicRecoverBody-OK method as it isn't part of the spec. @@ -162,6 +164,25 @@ public class AMQSession_0_8 extends AMQSession } } + public void releaseForRollback() + { + while (true) + { + Long tag = _deliveredMessageTags.poll(); + if (tag == null) + { + break; + } + + rejectMessage(tag, true); + } + + if (_dispatcher != null) + { + _dispatcher.rollback(); + } + } + public void rejectMessage(long deliveryTag, boolean requeue) { if ((_acknowledgeMode == CLIENT_ACKNOWLEDGE) || (_acknowledgeMode == SESSION_TRANSACTED)) diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java index 0ae282a12e..015a2ccc57 100644 --- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java +++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java @@ -131,13 +131,6 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me */ private boolean _dups_ok_acknowledge_send; - private ConcurrentLinkedQueue<Long> _unacknowledgedDeliveryTags = new ConcurrentLinkedQueue<Long>(); - - /** - * List of tags delievered, The last of which which should be acknowledged on commit in transaction mode. - */ - private ConcurrentLinkedQueue<Long> _receivedDeliveryTags = new ConcurrentLinkedQueue<Long>(); - /** * The thread that was used to call receive(). This is important for being able to interrupt that thread if a * receive() is in progress. @@ -276,10 +269,9 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me protected void preApplicationProcessing(AbstractJMSMessage jmsMsg) throws JMSException { - if (_session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) { - _unacknowledgedDeliveryTags.add(jmsMsg.getDeliveryTag()); + _session.addUnacknowledgedMessage(jmsMsg.getDeliveryTag()); } _session.setInRecovery(false); @@ -744,33 +736,13 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me } else { - _receivedDeliveryTags.add(msg.getDeliveryTag()); + _session.addDeliveredMessage(msg.getDeliveryTag()); } break; } } - /** - * Acknowledge up to last message delivered (if any). Used when commiting. - */ - void acknowledgeLastDelivered() - { - if (!_receivedDeliveryTags.isEmpty()) - { - long lastDeliveryTag = _receivedDeliveryTags.poll(); - - while (!_receivedDeliveryTags.isEmpty()) - { - lastDeliveryTag = _receivedDeliveryTags.poll(); - } - - assert _receivedDeliveryTags.isEmpty(); - - _session.acknowledgeMessage(lastDeliveryTag, true); - } - } - void notifyError(Throwable cause) { // synchronized (_closed) @@ -841,32 +813,6 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me } } - public void acknowledge() // throws JMSException - { - if (!isClosed()) - { - - Iterator<Long> tags = _unacknowledgedDeliveryTags.iterator(); - while (tags.hasNext()) - { - _session.acknowledgeMessage(tags.next(), false); - tags.remove(); - } - } - else - { - throw new IllegalStateException("Consumer is closed"); - } - } - - /** - * Called on recovery to reset the list of delivery tags - */ - public void clearUnackedMessages() - { - _unacknowledgedDeliveryTags.clear(); - } - public boolean isAutoClose() { return _autoClose; @@ -890,15 +836,6 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me public void rollback() { - clearUnackedMessages(); - - if (!_receivedDeliveryTags.isEmpty()) - { - _logger.debug("Rejecting received messages in _receivedDTs (RQ)"); - } - - rollbackReceivedMessages(); - // rollback pending messages if (_synchronousQueue.size() > 0) { @@ -944,39 +881,6 @@ public abstract class BasicMessageConsumer<H, B> extends Closeable implements Me } } - protected void rollbackReceivedMessages() - { - // rollback received but not committed messages - while (!_receivedDeliveryTags.isEmpty()) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Rejecting the messages(" + _receivedDeliveryTags - .size() + ") in _receivedDTs (RQ)" + "for consumer with tag:" + _consumerTag); - } - - Long tag = _receivedDeliveryTags.poll(); - - if (tag != null) - { - if (_logger.isTraceEnabled()) - { - _logger.trace("Rejecting tag from _receivedDTs:" + tag); - } - - _session.rejectMessage(tag, true); - } - } - - if (!_receivedDeliveryTags.isEmpty()) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Queue _receivedDTs (RQ) was not empty after rejection"); - } - } - } - public String debugIdentity() { return String.valueOf(_consumerTag); diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java index c40ec1e5cb..d7cce986aa 100644 --- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_10.java @@ -144,7 +144,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By if (isMessageListenerSet() && ClientProperties.MAX_PREFETCH == 0) { _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(), - org.apache.qpidity.nclient.Session.MESSAGE_FLOW_UNIT_MESSAGE, 1); + MessageCreditUnit.MESSAGE, 1); } _logger.debug("messageOk, trying to notify"); super.notifyMessage(jmsMessage, channelId); @@ -191,12 +191,12 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By } // if there is a replyto destination then we need to request the exchange info ReplyTo replyTo = message.getMessageProperties().getReplyTo(); - if (replyTo != null && replyTo.getExchangeName() != null && !replyTo.getExchangeName().equals("")) + if (replyTo != null && replyTo.getExchange() != null && !replyTo.getExchange().equals("")) { // <exch_class>://<exch_name>/[<destination>]/[<queue>]?<option>='<value>'[,<option>='<value>']* // the exchnage class will be set later from within the sesion thread String replyToUrl = message.getMessageProperties().getReplyTo() - .getExchangeName() + "/" + message.getMessageProperties().getReplyTo() + .getExchange() + "/" + message.getMessageProperties().getReplyTo() .getRoutingKey() + "/" + message.getMessageProperties().getReplyTo().getRoutingKey(); newMessage.setReplyToURL(replyToUrl); } @@ -227,21 +227,6 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By } } - /** - * This is invoked just before a message is delivered to the njms consumer - */ - void postDeliver(AbstractJMSMessage msg) throws JMSException - { - // notify the session - ((AMQSession_0_10) getSession()).addMessageTag(msg.getDeliveryTag()); - //if (!Boolean.getBoolean("noAck")) - //{ - super.postDeliver(msg); - //} - - - } - void notifyMessage(UnprocessedMessage messageFrame, int channelId) { // if there is a replyto destination then we need to request the exchange info @@ -279,6 +264,12 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By super.notifyMessage(messageFrame, channelId); } + protected void preApplicationProcessing(AbstractJMSMessage jmsMsg) throws JMSException + { + _session.addUnacknowledgedMessage(jmsMsg.getDeliveryTag()); + _session.setInRecovery(false); + } + public AbstractJMSMessage createJMSMessageFromUnprocessedMessage( UnprocessedMessage<Struct[], ByteBuffer> messageFrame) throws Exception { @@ -342,7 +333,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By if(ClientProperties.MAX_PREFETCH == 0) { _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(), - org.apache.qpidity.nclient.Session.MESSAGE_FLOW_UNIT_MESSAGE, 1); + MessageCreditUnit.MESSAGE, 1); } } // now we need to acquire this message if needed @@ -416,31 +407,13 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By RangeSet ranges = new RangeSet(); ranges.add(message.getDeliveryTag()); - _0_10session.getQpidSession() - .messageAcquire(ranges, org.apache.qpidity.nclient.Session.MESSAGE_ACQUIRE_ANY_AVAILABLE_MESSAGE); - - _logger.debug("acquireMessage, sent acquire message to broker"); - - _0_10session.getQpidSession().sync(); - - _logger.debug("acquireMessage, returned from sync"); - - RangeSet acquired = _0_10session.getQpidSession().getAccquiredMessages(); - - _logger.debug("acquireMessage, acquired range set " + acquired); + Acquired acq = _0_10session.getQpidSession().messageAcquire(ranges).get(); + RangeSet acquired = acq.getTransfers(); if (acquired != null && acquired.size() > 0) { result = true; } - - _logger.debug("acquireMessage, Trying to get current exception "); - - _0_10session.getCurrentException(); - - _logger.debug("acquireMessage, returned from getting current exception "); - - _logger.debug("acquireMessage, acquired range set " + acquired + " now returning " ); } return result; } @@ -452,7 +425,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By if (messageListener != null && ClientProperties.MAX_PREFETCH == 0) { _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(), - org.apache.qpidity.nclient.Session.MESSAGE_FLOW_UNIT_MESSAGE, 1); + MessageCreditUnit.MESSAGE, 1); } if (messageListener != null && !_synchronousQueue.isEmpty()) { @@ -477,7 +450,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By if (_syncReceive.get()) { _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(), - org.apache.qpidity.nclient.Session.MESSAGE_FLOW_UNIT_MESSAGE, 1); + MessageCreditUnit.MESSAGE, 1); } } @@ -500,7 +473,7 @@ public class BasicMessageConsumer_0_10 extends BasicMessageConsumer<Struct[], By if (isStrated() && ClientProperties.MAX_PREFETCH == 0 && _synchronousQueue.isEmpty()) { _0_10session.getQpidSession().messageFlow(getConsumerTag().toString(), - org.apache.qpidity.nclient.Session.MESSAGE_FLOW_UNIT_MESSAGE, 1); + MessageCreditUnit.MESSAGE, 1); } if (ClientProperties.MAX_PREFETCH == 0) { diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java index 0e166ed4c8..c3269880ad 100644 --- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java +++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer_0_10.java @@ -19,6 +19,9 @@ package org.apache.qpid.client; import java.io.IOException; import java.net.URISyntaxException; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; import javax.jms.JMSException; import javax.jms.Message; @@ -33,6 +36,9 @@ import org.apache.qpid.url.AMQBindingURL; import org.apache.qpidity.nclient.util.ByteBufferMessage; import org.apache.qpidity.njms.ExceptionHelper; import org.apache.qpidity.transport.DeliveryProperties; +import org.apache.qpidity.transport.MessageDeliveryMode; +import org.apache.qpidity.transport.MessageDeliveryPriority; +import org.apache.qpidity.transport.MessageProperties; import org.apache.qpidity.transport.ReplyTo; /** @@ -77,6 +83,7 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer } DeliveryProperties deliveryProp = message.get010Message().getDeliveryProperties(); + MessageProperties messageProps = message.get010Message().getMessageProperties(); // set the delivery properties if (!_disableTimestamps) { @@ -95,14 +102,14 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer message.setJMSTimestamp(currentTime); } - if (deliveryProp.getDeliveryMode() != deliveryMode) + if (!deliveryProp.hasDeliveryMode() || deliveryProp.getDeliveryMode().getValue() != deliveryMode) { - deliveryProp.setDeliveryMode((byte) deliveryMode); + deliveryProp.setDeliveryMode(MessageDeliveryMode.get((short) deliveryMode)); message.setJMSDeliveryMode(deliveryMode); } - if (deliveryProp.getPriority() != priority) + if (!deliveryProp.hasPriority() || deliveryProp.getPriority().getValue() != priority) { - deliveryProp.setPriority((byte) priority); + deliveryProp.setPriority(MessageDeliveryPriority.get((short) priority)); message.setJMSPriority(priority); } String excahngeName = destination.getExchangeName().toString(); @@ -131,27 +138,19 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer if (contentHeaderProperties.reset()) { // set the application properties - message.get010Message().getMessageProperties() - .setContentType(contentHeaderProperties.getContentType().toString()); + messageProps.setContentType(contentHeaderProperties.getContentType().toString()); + messageProps.setContentLength(message.getContentLength()); - /* Temp hack to get the JMS client to interoperate with the python client - as it relies on content length to determine the boundaries for - message framesets. The python client should be fixed. - */ - message.get010Message().getMessageProperties().setContentLength(message.getContentLength()); + // XXX: fixme + String mid = message.getJMSMessageID(); + messageProps.setMessageId(UUID.fromString(mid.substring(3))); - - AMQShortString type = contentHeaderProperties.getType(); - if (type != null) - { - message.get010Message().getMessageProperties().setType(type.toString()); - } - message.get010Message().getMessageProperties().setMessageId(message.getJMSMessageID()); AMQShortString correlationID = contentHeaderProperties.getCorrelationId(); if (correlationID != null) { - message.get010Message().getMessageProperties().setCorrelationId(correlationID.toString()); + messageProps.setCorrelationId(correlationID.getBytes()); } + String replyToURL = contentHeaderProperties.getReplyToAsString(); if (replyToURL != null) { @@ -172,17 +171,34 @@ public class BasicMessageProducer_0_10 extends BasicMessageProducer { throw ExceptionHelper.convertQpidExceptionToJMSException(e); } - message.get010Message().getMessageProperties() - .setReplyTo(new ReplyTo(dest.getExchangeName().toString(), dest.getRoutingKey().toString())); + messageProps.setReplyTo(new ReplyTo(dest.getExchangeName().toString(), dest.getRoutingKey().toString())); } + + Map<String,Object> map = null; + if (contentHeaderProperties.getHeaders() != null) { //JMS_QPID_DESTTYPE is always set but useles so this is a temporary fix contentHeaderProperties.getHeaders().remove(CustomJMSXProperty.JMS_QPID_DESTTYPE.getShortStringName()); - message.get010Message().getMessageProperties() - .setApplicationHeaders(FiledTableSupport.convertToMap(contentHeaderProperties.getHeaders())); + map = FiledTableSupport.convertToMap(contentHeaderProperties.getHeaders()); + } + + AMQShortString type = contentHeaderProperties.getType(); + if (type != null) + { + if (map == null) + { + map = new HashMap<String,Object>(); + } + map.put(AbstractJMSMessage.JMS_TYPE, type.toString()); + } + + if (map != null) + { + messageProps.setApplicationHeaders(map); } } + // send the message try { diff --git a/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java b/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java index 56e37797fc..fd50417fc7 100644 --- a/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java +++ b/java/client/src/main/java/org/apache/qpid/client/XAResourceImpl.java @@ -79,11 +79,11 @@ public class XAResourceImpl implements XAResource { throw new XAException(XAException.XAER_PROTO); } - Future<DtxCoordinationCommitResult> future; + Future<XaResult> future; try { future = _xaSession.getQpidSession() - .dtxCoordinationCommit(XidImpl.convertToString(xid), b ? Option.ONE_PHASE : Option.NO_OPTION); + .dtxCommit(XidImpl.convert(xid), b ? Option.ONE_PHASE : Option.NO_OPTION); } catch (QpidException e) { @@ -94,24 +94,24 @@ public class XAResourceImpl implements XAResource throw new XAException(XAException.XAER_PROTO); } // now wait on the future for the result - DtxCoordinationCommitResult result = future.get(); - int status = result.getStatus(); + XaResult result = future.get(); + DtxXaStatus status = result.getStatus(); switch (status) { - case Constant.XA_OK: + case XA_OK: // do nothing this ok break; - case Constant.XA_HEURHAZ: + case XA_HEURHAZ: throw new XAException(XAException.XA_HEURHAZ); - case Constant.XA_HEURCOM: + case XA_HEURCOM: throw new XAException(XAException.XA_HEURCOM); - case Constant.XA_HEURRB: + case XA_HEURRB: throw new XAException(XAException.XA_HEURRB); - case Constant.XA_HEURMIX: + case XA_HEURMIX: throw new XAException(XAException.XA_HEURMIX); - case Constant.XA_RBROLLBACK: + case XA_RBROLLBACK: throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: + case XA_RBTIMEOUT: throw new XAException(XAException.XA_RBTIMEOUT); default: // this should not happen @@ -149,13 +149,13 @@ public class XAResourceImpl implements XAResource { throw new XAException(XAException.XAER_PROTO); } - Future<DtxDemarcationEndResult> future; + Future<XaResult> future; try { future = _xaSession.getQpidSession() - .dtxDemarcationEnd(XidImpl.convertToString(xid), - flag == XAResource.TMFAIL ? Option.FAIL : Option.NO_OPTION, - flag == XAResource.TMSUSPEND ? Option.SUSPEND : Option.NO_OPTION); + .dtxEnd(XidImpl.convert(xid), + flag == XAResource.TMFAIL ? Option.FAIL : Option.NO_OPTION, + flag == XAResource.TMSUSPEND ? Option.SUSPEND : Option.NO_OPTION); } catch (QpidException e) { @@ -166,16 +166,16 @@ public class XAResourceImpl implements XAResource throw new XAException(XAException.XAER_PROTO); } // now wait on the future for the result - DtxDemarcationEndResult result = future.get(); - int status = result.getStatus(); + XaResult result = future.get(); + DtxXaStatus status = result.getStatus(); switch (status) { - case Constant.XA_OK: + case XA_OK: // do nothing this ok break; - case Constant.XA_RBROLLBACK: + case XA_RBROLLBACK: throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: + case XA_RBTIMEOUT: throw new XAException(XAException.XA_RBTIMEOUT); default: // this should not happen @@ -204,7 +204,8 @@ public class XAResourceImpl implements XAResource { throw new XAException(XAException.XAER_PROTO); } - _xaSession.getQpidSession().dtxCoordinationForget(new String(xid.getGlobalTransactionId())); + _xaSession.getQpidSession().dtxForget(new org.apache.qpidity.transport.Xid() + .setGlobalId((xid.getGlobalTransactionId()))); } /** @@ -223,8 +224,8 @@ public class XAResourceImpl implements XAResource { try { - Future<DtxCoordinationGetTimeoutResult> future = - _xaSession.getQpidSession().dtxCoordinationGetTimeout(XidImpl.convertToString(_xid)); + Future<GetTimeoutResult> future = + _xaSession.getQpidSession().dtxGetTimeout(XidImpl.convert(_xid)); result = (int) future.get().getTimeout(); } catch (QpidException e) @@ -273,11 +274,11 @@ public class XAResourceImpl implements XAResource { throw new XAException(XAException.XAER_PROTO); } - Future<DtxCoordinationPrepareResult> future; + Future<XaResult> future; try { future = _xaSession.getQpidSession() - .dtxCoordinationPrepare(XidImpl.convertToString(xid)); + .dtxPrepare(XidImpl.convert(xid)); } catch (QpidException e) { @@ -287,20 +288,20 @@ public class XAResourceImpl implements XAResource } throw new XAException(XAException.XAER_PROTO); } - DtxCoordinationPrepareResult result = future.get(); - int status = result.getStatus(); + XaResult result = future.get(); + DtxXaStatus status = result.getStatus(); int outcome; switch (status) { - case Constant.XA_OK: + case XA_OK: outcome = XAResource.XA_OK; break; - case Constant.XA_RDONLY: + case XA_RDONLY: outcome = XAResource.XA_RDONLY; break; - case Constant.XA_RBROLLBACK: + case XA_RBROLLBACK: throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: + case XA_RBTIMEOUT: throw new XAException(XAException.XA_RBTIMEOUT); default: // this should not happen @@ -328,26 +329,16 @@ public class XAResourceImpl implements XAResource public Xid[] recover(int flag) throws XAException { // the flag is ignored - Future<DtxCoordinationRecoverResult> future = _xaSession.getQpidSession().dtxCoordinationRecover(); - DtxCoordinationRecoverResult res = future.get(); + Future<RecoverResult> future = _xaSession.getQpidSession().dtxRecover(); + RecoverResult res = future.get(); // todo make sure that the keys of the returned map are the xids Xid[] result = new Xid[res.getInDoubt().size()]; int i = 0; - try - { - for (Object xid : res.getInDoubt()) - { - result[i] = new XidImpl((String) xid); - i++; - } - } - catch (QpidException e) + for (Object obj : res.getInDoubt()) { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert string into Xid ", e); - } - throw new XAException(XAException.XAER_PROTO); + org.apache.qpidity.transport.Xid xid = (org.apache.qpidity.transport.Xid) obj; + result[i] = new XidImpl(xid.getBranchId(), (int) xid.getFormat(), xid.getGlobalId()); + i++; } return result; } @@ -365,11 +356,11 @@ public class XAResourceImpl implements XAResource throw new XAException(XAException.XAER_PROTO); } // the flag is ignored - Future<DtxCoordinationRollbackResult> future; + Future<XaResult> future; try { future = _xaSession.getQpidSession() - .dtxCoordinationRollback(XidImpl.convertToString(xid)); + .dtxRollback(XidImpl.convert(xid)); } catch (QpidException e) { @@ -380,24 +371,24 @@ public class XAResourceImpl implements XAResource throw new XAException(XAException.XAER_PROTO); } // now wait on the future for the result - DtxCoordinationRollbackResult result = future.get(); - int status = result.getStatus(); + XaResult result = future.get(); + DtxXaStatus status = result.getStatus(); switch (status) { - case Constant.XA_OK: + case XA_OK: // do nothing this ok break; - case Constant.XA_HEURHAZ: + case XA_HEURHAZ: throw new XAException(XAException.XA_HEURHAZ); - case Constant.XA_HEURCOM: + case XA_HEURCOM: throw new XAException(XAException.XA_HEURCOM); - case Constant.XA_HEURRB: + case XA_HEURRB: throw new XAException(XAException.XA_HEURRB); - case Constant.XA_HEURMIX: + case XA_HEURMIX: throw new XAException(XAException.XA_HEURMIX); - case Constant.XA_RBROLLBACK: + case XA_RBROLLBACK: throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: + case XA_RBTIMEOUT: throw new XAException(XAException.XA_RBTIMEOUT); default: // this should not happen @@ -427,7 +418,7 @@ public class XAResourceImpl implements XAResource try { _xaSession.getQpidSession() - .dtxCoordinationSetTimeout(XidImpl.convertToString(_xid), timeout); + .dtxSetTimeout(XidImpl.convert(_xid), timeout); } catch (QpidException e) { @@ -467,13 +458,13 @@ public class XAResourceImpl implements XAResource throw new XAException(XAException.XAER_PROTO); } _xid = xid; - Future<DtxDemarcationStartResult> future; + Future<XaResult> future; try { future = _xaSession.getQpidSession() - .dtxDemarcationStart(XidImpl.convertToString(xid), - flag == XAResource.TMJOIN ? Option.JOIN : Option.NO_OPTION, - flag == XAResource.TMRESUME ? Option.RESUME : Option.NO_OPTION); + .dtxStart(XidImpl.convert(xid), + flag == XAResource.TMJOIN ? Option.JOIN : Option.NO_OPTION, + flag == XAResource.TMRESUME ? Option.RESUME : Option.NO_OPTION); } catch (QpidException e) { @@ -484,16 +475,16 @@ public class XAResourceImpl implements XAResource throw new XAException(XAException.XAER_PROTO); } // now wait on the future for the result - DtxDemarcationStartResult result = future.get(); - int status = result.getStatus(); + XaResult result = future.get(); + DtxXaStatus status = result.getStatus(); switch (status) { - case Constant.XA_OK: + case XA_OK: // do nothing this ok break; - case Constant.XA_RBROLLBACK: + case XA_RBROLLBACK: throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: + case XA_RBTIMEOUT: throw new XAException(XAException.XA_RBTIMEOUT); default: // this should not happen diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java index ddedb0e913..cfbf687401 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java @@ -53,6 +53,8 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach { private static final Map _destinationCache = Collections.synchronizedMap(new ReferenceMap()); + public static final String JMS_TYPE = "x-jms-type"; + protected boolean _redelivered; protected ByteBuffer _data; diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java index bf2a2fdd73..e04da98f39 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessageFactory.java @@ -38,6 +38,8 @@ import javax.jms.JMSException; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.UUID; public abstract class AbstractJMSMessageFactory implements MessageFactory { @@ -125,25 +127,50 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory MessageProperties mprop = (MessageProperties) contentHeader[0]; DeliveryProperties devprop = (DeliveryProperties) contentHeader[1]; props.setContentType(mprop.getContentType()); - props.setCorrelationId(mprop.getCorrelationId()); + props.setCorrelationId(asString(mprop.getCorrelationId())); String encoding = mprop.getContentEncoding(); if (encoding != null && !encoding.equals("")) { props.setEncoding(encoding); } - props.setDeliveryMode((byte) devprop.getDeliveryMode()); + if (devprop.hasDeliveryMode()) + { + props.setDeliveryMode((byte) devprop.getDeliveryMode().getValue()); + } props.setExpiration(devprop.getExpiration()); - props.setMessageId(mprop.getMessageId()); - props.setPriority((byte) devprop.getPriority()); + UUID mid = mprop.getMessageId(); + props.setMessageId(mid == null ? null : mid.toString()); + if (devprop.hasPriority()) + { + props.setPriority((byte) devprop.getPriority().getValue()); + } props.setReplyTo(replyToURL); props.setTimestamp(devprop.getTimestamp()); - props.setType(mprop.getType()); - props.setUserId(mprop.getUserId()); + String type = null; + Map<String,Object> map = mprop.getApplicationHeaders(); + if (map != null) + { + type = (String) map.get(AbstractJMSMessage.JMS_TYPE); + } + props.setType(type); + props.setUserId(asString(mprop.getUserId())); props.setHeaders(FiledTableSupport.convertToFieldTable(mprop.getApplicationHeaders())); AbstractJMSMessage message = createMessage(messageNbr, data, exchange, routingKey, props); return message; } + private static final String asString(byte[] bytes) + { + if (bytes == null) + { + return null; + } + else + { + return new String(bytes); + } + } + public AbstractJMSMessage createMessage(long messageNbr, boolean redelivered, ContentHeaderBody contentHeader, AMQShortString exchange, AMQShortString routingKey, List bodies) diff --git a/java/client/src/main/java/org/apache/qpidity/naming/PropertiesFileInitialContextFactory.java b/java/client/src/main/java/org/apache/qpidity/naming/PropertiesFileInitialContextFactory.java deleted file mode 100644 index 806ab284de..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/naming/PropertiesFileInitialContextFactory.java +++ /dev/null @@ -1,269 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.naming; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.qpid.url.BindingURLImpl; -import org.apache.qpid.url.QpidBindingURL; -import org.apache.qpidity.njms.ConnectionFactoryImpl; -import org.apache.qpidity.njms.DestinationImpl; -import org.apache.qpidity.njms.QueueImpl; -import org.apache.qpidity.njms.TopicImpl; -import org.apache.qpid.url.URLSyntaxException; -import org.apache.qpidity.QpidException; - -import javax.naming.spi.InitialContextFactory; -import javax.naming.Context; -import javax.naming.NamingException; -import javax.jms.ConnectionFactory; -import javax.jms.Destination; -import javax.jms.Queue; -import javax.jms.Topic; -import java.util.Hashtable; -import java.util.Map; -import java.util.Properties; -import java.util.Iterator; -import java.util.concurrent.ConcurrentHashMap; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.MalformedURLException; - -/** - * This is an implementation of InitialContextFactory that uses a default jndi.properties file. - * - */ -public class PropertiesFileInitialContextFactory implements InitialContextFactory -{ - protected final Logger _logger = LoggerFactory.getLogger(PropertiesFileInitialContextFactory.class); - - private String CONNECTION_FACTORY_PREFIX = "connectionfactory."; - private String DESTINATION_PREFIX = "destination."; - private String QUEUE_PREFIX = "queue."; - private String TOPIC_PREFIX = "topic."; - - public Context getInitialContext(Hashtable environment) throws NamingException - { - Map data = new ConcurrentHashMap(); - try - { - String file; - if (environment.containsKey(Context.PROVIDER_URL)) - { - file = (String) environment.get(Context.PROVIDER_URL); - } - else - { - file = System.getProperty(Context.PROVIDER_URL); - } - if (file != null) - { - _logger.info("Loading Properties from:" + file); - // Load the properties specified - Properties p = new Properties(); - p.load(new BufferedInputStream(new FileInputStream(file))); - environment.putAll(p); - _logger.info("Loaded Context Properties:" + environment.toString()); - } - else - { - _logger.info("No Provider URL specified."); - } - } - catch (IOException ioe) - { - _logger.warn( - "Unable to load property file specified in Provider_URL:" + environment.get(Context.PROVIDER_URL)); - } - createConnectionFactories(data, environment); - createDestinations(data, environment); - createQueues(data, environment); - createTopics(data, environment); - return createContext(data, environment); - } - - // Implementation methods - // ------------------------------------------------------------------------- - protected ReadOnlyContext createContext(Map data, Hashtable environment) - { - return new ReadOnlyContext(environment, data); - } - - protected void createConnectionFactories(Map data, Hashtable environment) - { - for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) - { - Map.Entry entry = (Map.Entry) iter.next(); - String key = entry.getKey().toString(); - if (key.startsWith(CONNECTION_FACTORY_PREFIX)) - { - String jndiName = key.substring(CONNECTION_FACTORY_PREFIX.length()); - ConnectionFactory cf = createFactory(entry.getValue().toString()); - if (cf != null) - { - data.put(jndiName, cf); - } - } - } - } - - protected void createDestinations(Map data, Hashtable environment) - { - for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) - { - Map.Entry entry = (Map.Entry) iter.next(); - String key = entry.getKey().toString(); - if (key.startsWith(DESTINATION_PREFIX)) - { - String jndiName = key.substring(DESTINATION_PREFIX.length()); - Destination dest = createDestination(entry.getValue().toString()); - if (dest != null) - { - data.put(jndiName, dest); - } - } - } - } - - protected void createQueues(Map data, Hashtable environment) - { - for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) - { - Map.Entry entry = (Map.Entry) iter.next(); - String key = entry.getKey().toString(); - if (key.startsWith(QUEUE_PREFIX)) - { - String jndiName = key.substring(QUEUE_PREFIX.length()); - Queue q = createQueue(entry.getValue().toString()); - if (q != null) - { - data.put(jndiName, q); - } - } - } - } - - protected void createTopics(Map data, Hashtable environment) - { - for (Iterator iter = environment.entrySet().iterator(); iter.hasNext();) - { - Map.Entry entry = (Map.Entry) iter.next(); - String key = entry.getKey().toString(); - if (key.startsWith(TOPIC_PREFIX)) - { - String jndiName = key.substring(TOPIC_PREFIX.length()); - Topic t = createTopic(entry.getValue().toString()); - if (t != null) - { - data.put(jndiName, t); - } - } - } - } - - /** - * Factory method to create new Connection Factory instances - */ - protected ConnectionFactory createFactory(String url) - { - try - { - return new ConnectionFactoryImpl(url); - } - catch (MalformedURLException urlse) - { - _logger.warn("Unable to createFactories:" + urlse); - } - return null; - } - - /** - * Factory method to create new Destination instances from an AMQP BindingURL - */ - protected Destination createDestination(String bindingURL) - { - QpidBindingURL binding; - try - { - binding = new BindingURLImpl(bindingURL); - } - catch (URLSyntaxException urlse) - { - _logger.warn("Unable to destination:" + urlse); - return null; - } - try - { - return new DestinationImpl(binding); - } - catch (QpidException iaw) - { - _logger.warn("Binding: '" + binding + "' not supported"); - return null; - } - } - - /** - * Factory method to create new Queue instances - */ - protected Queue createQueue(Object value) - { - Queue result = null; - try - { - if (value instanceof String) - { - result = new QueueImpl((String) value); - } - else if (value instanceof QpidBindingURL) - { - result = new QueueImpl((QpidBindingURL) value); - } - } - catch (QpidException e) - { - _logger.warn("Binding: '" + value + "' not supported"); - } - return result; - } - - /** - * Factory method to create new Topic instances - */ - protected Topic createTopic(Object value) - { - Topic result = null; - try - { - if (value instanceof String) - { - return new TopicImpl((String) value); - } - else if (value instanceof QpidBindingURL) - { - return new TopicImpl((QpidBindingURL) value); - } - } - catch (QpidException e) - { - _logger.warn("Binding: '" + value + "' not supported"); - } - return result; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/Client.java b/java/client/src/main/java/org/apache/qpidity/nclient/Client.java index 8b787615e4..c82fcfa4b0 100644 --- a/java/client/src/main/java/org/apache/qpidity/nclient/Client.java +++ b/java/client/src/main/java/org/apache/qpidity/nclient/Client.java @@ -1,6 +1,7 @@ package org.apache.qpidity.nclient; import java.util.List; +import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; @@ -15,10 +16,11 @@ import org.apache.qpidity.ProtocolException; import org.apache.qpidity.nclient.impl.ClientSession; import org.apache.qpidity.nclient.impl.ClientSessionDelegate; import org.apache.qpidity.transport.Channel; +import org.apache.qpidity.transport.ClientDelegate; import org.apache.qpidity.transport.Connection; import org.apache.qpidity.transport.ConnectionClose; +import org.apache.qpidity.transport.ConnectionCloseCode; import org.apache.qpidity.transport.ConnectionCloseOk; -import org.apache.qpidity.transport.ConnectionDelegate; import org.apache.qpidity.transport.ConnectionEvent; import org.apache.qpidity.transport.TransportConstants; import org.apache.qpidity.transport.ProtocolHeader; @@ -54,7 +56,7 @@ public class Client implements org.apache.qpidity.nclient.Connection closeOk = _lock.newCondition(); _lock.lock(); - ConnectionDelegate connectionDelegate = new ConnectionDelegate() + ClientDelegate connectionDelegate = new ClientDelegate() { private boolean receivedClose = false; private String _unsupportedProtocol; @@ -100,7 +102,7 @@ public class Client implements org.apache.qpidity.nclient.Connection @Override public void connectionClose(Channel context, ConnectionClose connectionClose) { - ErrorCode errorCode = ErrorCode.get(connectionClose.getReplyCode()); + ErrorCode errorCode = ErrorCode.get(connectionClose.getReplyCode().getValue()); if (_closedListner == null && errorCode != ErrorCode.NO_ERROR) { throw new RuntimeException @@ -132,10 +134,6 @@ public class Client implements org.apache.qpidity.nclient.Connection negotiationComplete.signalAll(); _lock.unlock(); } - else - { - ch.connectionStart(hdr.getMajor(), hdr.getMinor(), null, "PLAIN", "utf8"); - } } @Override public String getUnsupportedProtocol() @@ -233,7 +231,7 @@ public class Client implements org.apache.qpidity.nclient.Connection public void close() throws QpidException { Channel ch = _conn.getChannel(0); - ch.connectionClose(0, "client is closing", 0, 0); + ch.connectionClose(ConnectionCloseCode.NORMAL, "client is closing"); _lock.lock(); try { @@ -258,9 +256,10 @@ public class Client implements org.apache.qpidity.nclient.Connection public Session createSession(long expiryInSeconds) { Channel ch = _conn.getChannel(_channelNo.incrementAndGet()); - ClientSession ssn = new ClientSession(); + ClientSession ssn = new ClientSession(UUID.randomUUID().toString().getBytes()); ssn.attach(ch); - ssn.sessionOpen(expiryInSeconds); + ssn.sessionAttach(ssn.getName()); + ssn.sessionRequestTimeout(expiryInSeconds); if (Boolean.getBoolean("batch") && System.getProperty("transport").equalsIgnoreCase("nio")) { System.out.println("using batching"); @@ -272,7 +271,7 @@ public class Client implements org.apache.qpidity.nclient.Connection public DtxSession createDTXSession(int expiryInSeconds) { ClientSession clientSession = (ClientSession) createSession(expiryInSeconds); - clientSession.dtxDemarcationSelect(); + clientSession.dtxSelect(); return (DtxSession) clientSession; } diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/DtxSession.java b/java/client/src/main/java/org/apache/qpidity/nclient/DtxSession.java index 6fe019c3a1..6bf351a014 100644 --- a/java/client/src/main/java/org/apache/qpidity/nclient/DtxSession.java +++ b/java/client/src/main/java/org/apache/qpidity/nclient/DtxSession.java @@ -18,15 +18,12 @@ */ package org.apache.qpidity.nclient; -import org.apache.qpidity.transport.DtxCoordinationCommitResult; -import org.apache.qpidity.transport.DtxCoordinationGetTimeoutResult; -import org.apache.qpidity.transport.DtxCoordinationPrepareResult; -import org.apache.qpidity.transport.DtxCoordinationRecoverResult; -import org.apache.qpidity.transport.DtxCoordinationRollbackResult; -import org.apache.qpidity.transport.DtxDemarcationEndResult; -import org.apache.qpidity.transport.DtxDemarcationStartResult; import org.apache.qpidity.transport.Future; +import org.apache.qpidity.transport.GetTimeoutResult; import org.apache.qpidity.transport.Option; +import org.apache.qpidity.transport.RecoverResult; +import org.apache.qpidity.transport.XaResult; +import org.apache.qpidity.transport.Xid; /** * This session�s resources are control under the scope of a distributed transaction. @@ -47,7 +44,7 @@ public interface DtxSession extends Session * @param options Possible options are: {@link Option#JOIN} and {@link Option#RESUME}. * @return Confirms to the client that the transaction branch is started or specify the error condition. */ - public Future<DtxDemarcationStartResult> dtxDemarcationStart(String xid, Option... options); + public Future<XaResult> dtxStart(Xid xid, Option... options); /** * This method is called when the work done on behalf a transaction branch finishes or needs to @@ -65,7 +62,7 @@ public interface DtxSession extends Session * @param options Available options are: {@link Option#FAIL} and {@link Option#SUSPEND}. * @return Confirms to the client that the transaction branch is ended or specify the error condition. */ - public Future<DtxDemarcationEndResult> dtxDemarcationEnd(String xid, Option... options); + public Future<XaResult> dtxEnd(Xid xid, Option... options); /** * Commit the work done on behalf a transaction branch. This method commits the work associated @@ -79,14 +76,14 @@ public interface DtxSession extends Session * @param options Available option is: {@link Option#ONE_PHASE} * @return Confirms to the client that the transaction branch is committed or specify the error condition. */ - public Future<DtxCoordinationCommitResult> dtxCoordinationCommit(String xid, Option... options); + public Future<XaResult> dtxCommit(Xid xid, Option... options); /** * This method is called to forget about a heuristically completed transaction branch. * * @param xid Specifies the xid of the transaction branch to be forgotten. */ - public void dtxCoordinationForget(String xid); + public void dtxForget(Xid xid); /** * This method obtains the current transaction timeout value in seconds. If set-timeout was not @@ -96,7 +93,7 @@ public interface DtxSession extends Session * @param xid Specifies the xid of the transaction branch for getting the timeout. * @return The current transaction timeout value in seconds. */ - public Future<DtxCoordinationGetTimeoutResult> dtxCoordinationGetTimeout(String xid); + public Future<GetTimeoutResult> dtxGetTimeout(Xid xid); /** * This method prepares for commitment any message produced or consumed on behalf of xid. @@ -112,7 +109,7 @@ public interface DtxSession extends Session * <p/> * xa-rbtimeout: The work represented by this transaction branch took too long. */ - public Future<DtxCoordinationPrepareResult> dtxCoordinationPrepare(String xid); + public Future<XaResult> dtxPrepare(Xid xid); /** * This method is called to obtain a list of transaction branches that are in a prepared or @@ -120,7 +117,7 @@ public interface DtxSession extends Session * Todo The options ahould be removed once the xml is updated * @return a array of xids to be recovered. */ - public Future<DtxCoordinationRecoverResult> dtxCoordinationRecover(Option... options); + public Future<RecoverResult> dtxRecover(); /** * This method rolls back the work associated with xid. Any produced messages are discarded and @@ -129,7 +126,7 @@ public interface DtxSession extends Session * @param xid Specifies the xid of the transaction branch that can be rolled back. * @return Confirms to the client that the transaction branch is rolled back or specify the error condition. */ - public Future<DtxCoordinationRollbackResult> dtxCoordinationRollback(String xid); + public Future<XaResult> dtxRollback(Xid xid); /** * Sets the specified transaction branch timeout value in seconds. @@ -137,5 +134,5 @@ public interface DtxSession extends Session * @param xid Specifies the xid of the transaction branch for setting the timeout. * @param timeout The transaction timeout value in seconds. */ - public void dtxCoordinationSetTimeout(String xid, long timeout); + public void dtxSetTimeout(Xid xid, long timeout); } diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/Session.java b/java/client/src/main/java/org/apache/qpidity/nclient/Session.java index b3d3a7c12d..e2dcd53854 100644 --- a/java/client/src/main/java/org/apache/qpidity/nclient/Session.java +++ b/java/client/src/main/java/org/apache/qpidity/nclient/Session.java @@ -41,8 +41,8 @@ public interface Session { public static final short TRANSFER_ACQUIRE_MODE_NO_ACQUIRE = 1; public static final short TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE = 0; - public static final short TRANSFER_CONFIRM_MODE_REQUIRED = 1; - public static final short TRANSFER_CONFIRM_MODE_NOT_REQUIRED = 0; + public static final short TRANSFER_CONFIRM_MODE_REQUIRED = 0; + public static final short TRANSFER_CONFIRM_MODE_NOT_REQUIRED = 1; public static final short MESSAGE_FLOW_MODE_CREDIT = 0; public static final short MESSAGE_FLOW_MODE_WINDOW = 1; public static final short MESSAGE_FLOW_UNIT_MESSAGE = 0; @@ -63,17 +63,11 @@ public interface Session */ public void sync(); - /** - * Close this session and any associated resources. - */ - public void sessionClose(); + public void sessionDetach(byte[] name); - /** - * Suspend this session resulting in interrupting the traffic with the broker. - * <p> The session timer will start to tick in suspend. - * <p> When a session is suspend any operation of this session and of the associated resources are unavailable. - */ - public void sessionSuspend(); + public void sessionRequestTimeout(long expiry); + + public byte[] getName(); //------------------------------------------------------ // Messaging methods @@ -177,7 +171,7 @@ public interface Session * is acquired when the transfer starts * </ul> */ - public void messageTransfer(String destination, short confirmMode, short acquireMode); + public void messageTransfer(String destination, MessageAcceptMode acceptMode, MessageAcquireMode acquireMode); /** * Add a set of headers the following headers to the message being sent. @@ -301,7 +295,7 @@ public interface Session * @param mode <ul> <li>credit ({@link Session#MESSAGE_FLOW_MODE_CREDIT}): choose credit based flow control * <li> window ({@link Session#MESSAGE_FLOW_MODE_WINDOW}): choose window based flow control</ul> */ - public void messageFlowMode(String destination, short mode); + public void messageSetFlowMode(String destination, MessageFlowMode mode); /** @@ -322,7 +316,7 @@ public interface Session * </ul> * @param value Number of credits, a value of 0 indicates an infinite amount of credit. */ - public void messageFlow(String destination, short unit, long value); + public void messageFlow(String destination, MessageCreditUnit unit, long value); /** * Forces the broker to exhaust its credit supply. @@ -364,24 +358,7 @@ public interface Session * failed). * @param text String describing the reason for a message transfer rejection. */ - public void messageReject(RangeSet ranges, int code, String text); - - /** - * This method asks the broker to redeliver all unacknowledged messages on a specified session. - * Zero or more messages may be redelivered. This method is only allowed on non-transacted - * sessions. - * <p> Following are valid options: - * <ul> - * <li>{@link Option#REQUEUE}: <p>IIf this field is not set, the message will be redelivered to the original recipient. - * If this option is ser, the server will attempt to requeue the message, potentially then delivering it - * to an alternative subscriber. - * <p/> - * </ul> - * - * @param _options see available options - */ - public void messageRecover(Option... _options); - + public void messageReject(RangeSet ranges, MessageRejectCode code, String text); /** * As it is possible that the broker does not manage to reject some messages, after completion of @@ -407,31 +384,9 @@ public interface Session * The outcome of the acquisition is returned as an array of ranges of qcquired messages. * <p> This method should only be called on non-acquired messages. * - * @param mode One of: <ul> - * <li> any ({@link Session#MESSAGE_ACQUIRE_ANY_AVAILABLE_MESSAGE}): acquire any available - * messages for consumption - * <li> all ({@link Session#MESSAGE_ACQUIRE_MESSAGES_IF_ALL_ARE_AVAILABLE}): only acquire messages - * if all are available for consumption - * </ul> * @param ranges Ranges of messages to be acquired. */ - public void messageAcquire(RangeSet ranges, short mode); - - /** - * As it is possible that the broker does not manage to acquire some messages, after completion of - * {@link Session#messageAcquire} this method will return the ranges of acquired messages. - * <p> Note that {@link Session#messageAcquire} and this methods are asynchronous therefore for accessing to the - * previously acquired messages this method must be invoked in conjunction with {@link Session#sync()}. - * <p> A recommended invocation sequence would be: - * <ul> - * <li> {@link Session#messageAcquire} - * <li> {@link Session#sync()} - * <li> {@link Session#getAccquiredMessages()} - * </ul> - * - * @return returns the message ranges marked by the broker as acquired. - */ - public RangeSet getAccquiredMessages(); + public Future<Acquired> messageAcquire(RangeSet ranges); /** * Give up responsibility for processing ranges of messages. @@ -439,7 +394,7 @@ public interface Session * * @param ranges Ranges of messages to be released. */ - public void messageRelease(RangeSet ranges); + public void messageRelease(RangeSet ranges, Option ... options); // ----------------------------------------------- // Local transaction methods @@ -519,7 +474,7 @@ public interface Session * routing keys depends on the exchange implementation. * @param arguments Used for backward compatibility */ - public void queueBind(String queueName, String exchangeName, String routingKey, Map<String, Object> arguments); + public void exchangeBind(String queueName, String exchangeName, String routingKey, Map<String, Object> arguments); /** * Unbind a queue from an exchange. @@ -527,9 +482,8 @@ public interface Session * @param queueName Specifies the name of the queue to unbind. * @param exchangeName The name of the exchange to unbind from. * @param routingKey Specifies the routing key of the binding to unbind. - * @param arguments Used for backward compatibility */ - public void queueUnbind(String queueName, String exchangeName, String routingKey, Map<String, Object> arguments); + public void exchangeUnbind(String queueName, String exchangeName, String routingKey); /** * This method removes all messages from a queue. It does not cancel consumers. Purged messages @@ -582,8 +536,8 @@ public interface Session * @param arguments bacward compatibilties params. * @return Information on the specified binding. */ - public Future<BindingQueryResult> bindingQuery(String exchange, String queue, String routingKey, - Map<String, Object> arguments); + public Future<ExchangeBoundResult> exchangeBound(String exchange, String queue, String routingKey, + Map<String, Object> arguments); // -------------------------------------- // exhcange methods diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSession.java b/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSession.java index 5fe38889d9..f1701a6b38 100644 --- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSession.java +++ b/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSession.java @@ -10,6 +10,8 @@ import org.apache.qpidity.QpidException; import org.apache.qpidity.api.Message; import org.apache.qpidity.nclient.ClosedListener; import org.apache.qpidity.nclient.MessagePartListener; +import org.apache.qpidity.transport.MessageAcceptMode; +import org.apache.qpidity.transport.MessageAcquireMode; import org.apache.qpidity.transport.Option; import org.apache.qpidity.transport.Range; import org.apache.qpidity.transport.RangeSet; @@ -45,13 +47,17 @@ public class ClientSession extends org.apache.qpidity.transport.Session implemen private static long MAX_NOT_SYNC_DATA_LENGH; private static long MAX_NOT_FLUSH_DATA_LENGH; + private Map<String,MessagePartListener> _messageListeners = new HashMap<String,MessagePartListener>(); private ClosedListener _exceptionListner; - private RangeSet _acquiredMessages; private RangeSet _rejectedMessages; private long _currentDataSizeNotSynced; private long _currentDataSizeNotFlushed; + public ClientSession(byte[] name) + { + super(name); + } public void messageAcknowledge(RangeSet ranges) { @@ -60,20 +66,24 @@ public class ClientSession extends org.apache.qpidity.transport.Session implemen super.processed(range); } super.flushProcessed(); + messageAccept(ranges); } - public void messageSubscribe(String queue, String destination, short confirmMode, short acquireMode, MessagePartListener listener, Map<String, Object> filter, Option... options) + public void messageSubscribe(String queue, String destination, short acceptMode, short acquireMode, MessagePartListener listener, Map<String, Object> filter, Option... options) { setMessageListener(destination,listener); - super.messageSubscribe(queue, destination, confirmMode, acquireMode, filter, options); + super.messageSubscribe(queue, destination, MessageAcceptMode.get(acceptMode), + MessageAcquireMode.get(acquireMode), null, 0, filter, + options); } - public void messageTransfer(String destination, Message msg, short confirmMode, short acquireMode) throws IOException + public void messageTransfer(String destination, Message msg, short acceptMode, short acquireMode) throws IOException { // The javadoc clearly says that this method is suitable for small messages // therefore reading the content in one shot. ByteBuffer data = msg.readData(); - super.messageTransfer(destination, confirmMode, acquireMode); + super.messageTransfer(destination, MessageAcceptMode.get(acceptMode), + MessageAcquireMode.get(acquireMode)); // super.header(msg.getDeliveryProperties(),msg.getMessageProperties() ); if( msg.getHeader() == null || msg.getDeliveryProperties().isDirty() || msg.getMessageProperties().isDirty() ) { @@ -118,9 +128,10 @@ public class ClientSession extends org.apache.qpidity.transport.Session implemen super.data(bytes); } - public void messageStream(String destination, Message msg, short confirmMode, short acquireMode) throws IOException + public void messageStream(String destination, Message msg, short acceptMode, short acquireMode) throws IOException { - super.messageTransfer(destination, confirmMode, acquireMode); + super.messageTransfer(destination, MessageAcceptMode.get(acceptMode), + MessageAcquireMode.get(acquireMode)); super.header(msg.getDeliveryProperties(),msg.getMessageProperties()); boolean b = true; int count = 0; @@ -153,11 +164,6 @@ public class ClientSession extends org.apache.qpidity.transport.Session implemen }*/ } - public RangeSet getAccquiredMessages() - { - return _acquiredMessages; - } - public RangeSet getRejectedMessages() { return _rejectedMessages; @@ -177,11 +183,6 @@ public class ClientSession extends org.apache.qpidity.transport.Session implemen _exceptionListner = exceptionListner; } - void setAccquiredMessages(RangeSet acquiredMessages) - { - _acquiredMessages = acquiredMessages; - } - void setRejectedMessages(RangeSet rejectedMessages) { _rejectedMessages = rejectedMessages; diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSessionDelegate.java b/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSessionDelegate.java index f51829d834..0963ec8818 100644 --- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSessionDelegate.java +++ b/java/client/src/main/java/org/apache/qpidity/nclient/impl/ClientSessionDelegate.java @@ -9,12 +9,11 @@ import org.apache.qpidity.nclient.MessagePartListener; import org.apache.qpidity.QpidException; import org.apache.qpidity.transport.Data; import org.apache.qpidity.transport.Header; -import org.apache.qpidity.transport.MessageAcquired; import org.apache.qpidity.transport.MessageReject; import org.apache.qpidity.transport.MessageTransfer; import org.apache.qpidity.transport.Range; import org.apache.qpidity.transport.Session; -import org.apache.qpidity.transport.SessionClosed; +import org.apache.qpidity.transport.SessionDetached; import org.apache.qpidity.transport.SessionDelegate; @@ -23,9 +22,9 @@ public class ClientSessionDelegate extends SessionDelegate private MessageTransfer _currentTransfer; private MessagePartListener _currentMessageListener; - @Override public void sessionClosed(Session ssn,SessionClosed sessionClosed) + @Override public void sessionDetached(Session ssn, SessionDetached dtc) { - ((ClientSession)ssn).notifyException(new QpidException(sessionClosed.getReplyText(),ErrorCode.get(sessionClosed.getReplyCode()),null)); + ((ClientSession)ssn).notifyException(new QpidException("", ErrorCode.get(dtc.getCode().getValue()),null)); } // -------------------------------------------- @@ -76,10 +75,5 @@ public class ClientSessionDelegate extends SessionDelegate ((ClientSession)session).notifyException(new QpidException("Message Rejected",ErrorCode.MESSAGE_REJECTED,null)); session.processed(struct); } - - @Override public void messageAcquired(Session session, MessageAcquired struct) - { - ((ClientSession)session).setAccquiredMessages(struct.getTransfers()); - session.processed(struct); - } + } diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/DemoClient.java b/java/client/src/main/java/org/apache/qpidity/nclient/impl/DemoClient.java index 810082fdd3..05b99a3cf1 100644 --- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/DemoClient.java +++ b/java/client/src/main/java/org/apache/qpidity/nclient/impl/DemoClient.java @@ -9,8 +9,12 @@ import org.apache.qpidity.nclient.Session; import org.apache.qpidity.nclient.util.MessageListener; import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; import org.apache.qpidity.transport.DeliveryProperties; +import org.apache.qpidity.transport.MessageAcceptMode; +import org.apache.qpidity.transport.MessageAcquireMode; import org.apache.qpidity.transport.MessageProperties; +import java.util.UUID; + public class DemoClient { public static MessagePartListenerAdapter createAdapter() @@ -46,19 +50,20 @@ public class DemoClient } }); ssn.queueDeclare("queue1", null, null); - ssn.queueBind("queue1", "amq.direct", "queue1",null); + ssn.exchangeBind("queue1", "amq.direct", "queue1",null); ssn.sync(); ssn.messageSubscribe("queue1", "myDest", (short)0, (short)0,createAdapter(), null); // queue - ssn.messageTransfer("amq.direct", (short) 0, (short) 1); - ssn.header(new DeliveryProperties().setRoutingKey("queue1"),new MessageProperties().setMessageId("123")); + ssn.messageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED); + ssn.header(new DeliveryProperties().setRoutingKey("queue1"), + new MessageProperties().setMessageId(UUID.randomUUID())); ssn.data("this is the data"); ssn.endData(); //reject - ssn.messageTransfer("amq.direct", (short) 0, (short) 1); + ssn.messageTransfer("amq.direct", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED); ssn.data("this should be rejected"); ssn.header(new DeliveryProperties().setRoutingKey("stocks")); ssn.endData(); @@ -71,17 +76,18 @@ public class DemoClient ssn.sync(); ssn.queueDeclare("topic1", null, null); - ssn.queueBind("topic1", "amq.topic", "stock.*",null); + ssn.exchangeBind("topic1", "amq.topic", "stock.*",null); ssn.queueDeclare("topic2", null, null); - ssn.queueBind("topic2", "amq.topic", "stock.us.*",null); + ssn.exchangeBind("topic2", "amq.topic", "stock.us.*",null); ssn.queueDeclare("topic3", null, null); - ssn.queueBind("topic3", "amq.topic", "stock.us.rh",null); + ssn.exchangeBind("topic3", "amq.topic", "stock.us.rh",null); ssn.sync(); // topic - ssn.messageTransfer("amq.topic", (short) 0, (short) 1); + ssn.messageTransfer("amq.topic", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED); ssn.data("Topic message"); - ssn.header(new DeliveryProperties().setRoutingKey("stock.us.ibm"),new MessageProperties().setMessageId("456")); + ssn.header(new DeliveryProperties().setRoutingKey("stock.us.ibm"), + new MessageProperties().setMessageId(UUID.randomUUID())); ssn.endData(); } diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/impl/LargeMsgDemoClient.java b/java/client/src/main/java/org/apache/qpidity/nclient/impl/LargeMsgDemoClient.java index 6a80575f4b..64ffe17fe0 100644 --- a/java/client/src/main/java/org/apache/qpidity/nclient/impl/LargeMsgDemoClient.java +++ b/java/client/src/main/java/org/apache/qpidity/nclient/impl/LargeMsgDemoClient.java @@ -14,6 +14,8 @@ import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; import org.apache.qpidity.transport.DeliveryProperties; import org.apache.qpidity.transport.MessageProperties; +import java.util.UUID; + public class LargeMsgDemoClient { public static MessagePartListenerAdapter createAdapter() @@ -49,7 +51,7 @@ public class LargeMsgDemoClient } }); ssn.queueDeclare("queue1", null, null); - ssn.queueBind("queue1", "amq.direct", "queue1",null); + ssn.exchangeBind("queue1", "amq.direct", "queue1",null); ssn.sync(); ssn.messageSubscribe("queue1", "myDest", (short)0, (short)0,createAdapter(), null); @@ -59,7 +61,7 @@ public class LargeMsgDemoClient FileMessage msg = new FileMessage(new FileInputStream("/home/rajith/TestFile"), 1024, new DeliveryProperties().setRoutingKey("queue1"), - new MessageProperties().setMessageId("123")); + new MessageProperties().setMessageId(UUID.randomUUID())); // queue ssn.messageStream("amq.direct",msg, (short) 0, (short) 1); diff --git a/java/client/src/main/java/org/apache/qpidity/nclient/interop/BasicInteropTest.java b/java/client/src/main/java/org/apache/qpidity/nclient/interop/BasicInteropTest.java index 3ddded2051..0a15189b48 100644 --- a/java/client/src/main/java/org/apache/qpidity/nclient/interop/BasicInteropTest.java +++ b/java/client/src/main/java/org/apache/qpidity/nclient/interop/BasicInteropTest.java @@ -13,6 +13,10 @@ import org.apache.qpidity.nclient.Session; import org.apache.qpidity.nclient.util.MessageListener; import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; import org.apache.qpidity.transport.DeliveryProperties; +import org.apache.qpidity.transport.MessageAcceptMode; +import org.apache.qpidity.transport.MessageAcquireMode; +import org.apache.qpidity.transport.MessageCreditUnit; +import org.apache.qpidity.transport.MessageFlowMode; import org.apache.qpidity.transport.MessageProperties; import org.apache.qpidity.transport.RangeSet; @@ -66,14 +70,14 @@ public class BasicInteropTest implements ClosedListener System.out.println("------- Queue created --------"); System.out.println("------- Binding a queue --------"); - session.queueBind("testQueue", "test", "testKey", null); + session.exchangeBind("testQueue", "test", "testKey", null); session.sync(); System.out.println("------- Queue bound --------"); } public void testSendMessage(){ System.out.println("------- Sending a message --------"); - session.messageTransfer("test", Session.TRANSFER_CONFIRM_MODE_REQUIRED, Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE); + session.messageTransfer("test", MessageAcceptMode.NONE, MessageAcquireMode.PRE_ACQUIRED); Map<String,Object> props = new HashMap<String,Object>(); props.put("name", "rajith"); @@ -111,11 +115,10 @@ public class BasicInteropTest implements ClosedListener null); System.out.println("------- Setting Credit mode --------"); - session.messageFlowMode("myDest", Session.MESSAGE_FLOW_MODE_WINDOW); + session.messageSetFlowMode("myDest", MessageFlowMode.WINDOW); System.out.println("------- Setting Credit --------"); - session.messageFlow("myDest", Session.MESSAGE_FLOW_UNIT_MESSAGE, 1); - //session.messageFlow("myDest", Session.MESSAGE_FLOW_UNIT_BYTE, 0xFFFFFFFF); - session.messageFlow("myDest", Session.MESSAGE_FLOW_UNIT_BYTE, -1); + session.messageFlow("myDest", MessageCreditUnit.MESSAGE, 1); + session.messageFlow("myDest", MessageCreditUnit.BYTE, -1); } public void testMessageFlush() diff --git a/java/client/src/main/java/org/apache/qpidity/njms/ConnectionFactoryImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/ConnectionFactoryImpl.java deleted file mode 100644 index c1d7c07209..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/ConnectionFactoryImpl.java +++ /dev/null @@ -1,521 +0,0 @@ -package org.apache.qpidity.njms; - -import javax.jms.*; -import javax.naming.*; -import javax.naming.spi.ObjectFactory; - -import org.apache.qpid.url.BindingURLImpl; -import org.apache.qpid.url.QpidURL; -import org.apache.qpid.url.QpidURLImpl; -import org.apache.qpidity.QpidException; -import org.apache.qpidity.BrokerDetails; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Hashtable; -import java.net.MalformedURLException; - -/** - * Implements all the JMS connection factories. - * <p> In all the implementations in our code base - * when we create a Reference we pass in <code>ConnectionFactoryImpl</code> as the - * factory for creating the objects. This is the factory (or - * {@link ObjectFactory}) that is used to turn the description in to a real object. - * <p>In our construction of the Reference the last param. is null, - * we could put a url to a jar that contains our {@link ObjectFactory} so that - * any of our objects stored in JNDI can be recreated without even having - * the classes locally. As it is the <code>ConnectionFactoryImpl</code> must be on the - * classpath when you do a lookup in a JNDI context.. else you'll get a - * ClassNotFoundEx. - */ -public class ConnectionFactoryImpl implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory, - XATopicConnectionFactory, XAQueueConnectionFactory, XAConnectionFactory, - ObjectFactory, Referenceable -{ - /** - * this ConnectionFactoryImpl's logger - */ - private static final Logger _logger = LoggerFactory.getLogger(ConnectionFactoryImpl.class); - - /** - * The virtual host on which the broker is deployed. - */ - private String _host; - /** - * The port on which the broker is listening for connection. - */ - private int _port; - /** - * The default user name used of user identification. - */ - private String _defaultUsername; - /** - * The default password used of user identification. - */ - private String _defaultPassword; - /** - * The virtual host on which the broker is deployed. - */ - private String _virtualHost; - /** - * The URL used to build this factory, (not yet supported) - */ - private QpidURL _qpidURL; - - // Undefined at the moment - public ConnectionFactoryImpl(QpidURL url) - { - _qpidURL = url; - } - - public ConnectionFactoryImpl(String url) throws MalformedURLException - { - _qpidURL = new QpidURLImpl(url); - BrokerDetails bd = _qpidURL.getAllBrokerDetails().get(0); - _host = bd.getHost(); - _port = bd.getPort(); - _defaultUsername = bd.getUserName(); - _defaultPassword = bd.getPassword(); - _virtualHost = bd.getVirtualHost(); - } - - /** - * Create a connection Factory - * - * @param host The broker host name. - * @param port The port on which the broker is listening for connection. - * @param virtualHost The virtual host on which the broker is deployed. - * @param defaultUsername The user name used of user identification. - * @param defaultPassword The password used of user identification. - */ - public ConnectionFactoryImpl(String host, int port, String virtualHost, String defaultUsername, - String defaultPassword) - { - _host = host; - _port = port; - _defaultUsername = defaultUsername; - _defaultPassword = defaultPassword; - _virtualHost = virtualHost; - } - - //-- Interface ConnectionFactory - - /** - * Creates a connection with the default user identity. - * <p> The connection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @return A newly created connection. - * @throws JMSException If creating the connection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public Connection createConnection() throws JMSException - { - try - { - return new ConnectionImpl(_host, _port, _virtualHost, _defaultUsername, _defaultPassword); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Creates a connection with the specified user identity. - * <p> The connection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @param username the caller's user name - * @param password the caller's password - * @return A newly created connection. - * @throws JMSException If creating the connection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public Connection createConnection(String username, String password) throws JMSException - { - try - { - return new ConnectionImpl(_host, _port, _virtualHost, username, password); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - // ---------------------------------------- - // Support for JMS 1.0 classes - // ---------------------------------------- - //--- Interface QueueConnection - /** - * Creates a queueConnection with the default user identity. - * <p> The queueConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @return A newly created queueConnection - * @throws JMSException If creating the queueConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public QueueConnection createQueueConnection() throws JMSException - { - try - { - return new QueueConnectionImpl(_host, _port, _virtualHost, _defaultUsername, _defaultPassword); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Creates a queueConnection with the specified user identity. - * <p> The queueConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @param username the caller's user name - * @param password the caller's password - * @return A newly created queueConnection. - * @throws JMSException If creating the queueConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public QueueConnection createQueueConnection(String username, String password) throws JMSException - { - try - { - return new QueueConnectionImpl(_host, _port, _virtualHost, username, password); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - //--- Interface TopicConnection - /** - * Creates a topicConnection with the default user identity. - * <p> The topicConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @return A newly created topicConnection - * @throws JMSException If creating the topicConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public TopicConnection createTopicConnection() throws JMSException - { - try - { - return new TopicConnectionImpl(_host, _port, _virtualHost, _defaultUsername, _defaultPassword); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Creates a topicConnection with the specified user identity. - * <p> The topicConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @param username the caller's user name - * @param password the caller's password - * @return A newly created topicConnection. - * @throws JMSException If creating the topicConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public TopicConnection createTopicConnection(String username, String password) throws JMSException - { - try - { - return new TopicConnectionImpl(_host, _port, _virtualHost, username, password); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - // --------------------------------------------------------------------------------------------------- - // the following methods are provided for XA compatibility - // --------------------------------------------------------------------------------------------------- - - /** - * Creates a XAConnection with the default user identity. - * <p> The XAConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @return A newly created XAConnection - * @throws JMSException If creating the XAConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public XAConnection createXAConnection() throws JMSException - { - try - { - return new XAConnectionImpl(_host, _port, _virtualHost, _defaultUsername, _defaultPassword); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Creates a XAConnection with the specified user identity. - * <p> The XAConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @param username the caller's user name - * @param password the caller's password - * @return A newly created XAConnection. - * @throws JMSException If creating the XAConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public XAConnection createXAConnection(String username, String password) throws JMSException - { - try - { - return new XAConnectionImpl(_host, _port, _virtualHost, username, password); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - - /** - * Creates a XATopicConnection with the default user identity. - * <p> The XATopicConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @return A newly created XATopicConnection - * @throws JMSException If creating the XATopicConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public XATopicConnection createXATopicConnection() throws JMSException - { - try - { - return new XATopicConnectionImpl(_host, _port, _virtualHost, _defaultUsername, _defaultPassword); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Creates a XATopicConnection with the specified user identity. - * <p> The XATopicConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @param username the caller's user name - * @param password the caller's password - * @return A newly created XATopicConnection. - * @throws JMSException If creating the XATopicConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public XATopicConnection createXATopicConnection(String username, String password) throws JMSException - { - try - { - return new XATopicConnectionImpl(_host, _port, _virtualHost, username, password); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Creates a XAQueueConnection with the default user identity. - * <p> The XAQueueConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @return A newly created XAQueueConnection - * @throws JMSException If creating the XAQueueConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public XAQueueConnection createXAQueueConnection() throws JMSException - { - try - { - return new XAQueueConnectionImpl(_host, _port, _virtualHost, _defaultUsername, _defaultPassword); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Creates a XAQueueConnection with the specified user identity. - * <p> The XAQueueConnection is created in stopped mode. No messages - * will be delivered until the <code>Connection.start</code> method - * is explicitly called. - * - * @param username the caller's user name - * @param password the caller's password - * @return A newly created XAQueueConnection. - * @throws JMSException If creating the XAQueueConnection fails due to some internal error. - * @throws JMSSecurityException If client authentication fails due to an invalid user name or password. - */ - public XAQueueConnection createXAQueueConnection(String username, String password) throws JMSException - { - try - { - return new XAQueueConnectionImpl(_host, _port, _virtualHost, username, password); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("PRoblem when creating connection", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - // ---------------------------------------- - // Support for JNDI - // ---------------------------------------- - - /** - * Creates an object using the location or reference information - * specified. - * - * @param obj The possibly null object containing location or reference - * information that can be used in creating an object. - * @param name The name of this object relative to <code>nameCtx</code>, - * or null if no name is specified. - * @param nameCtx The context relative to which the <code>name</code> - * parameter is specified, or null if <code>name</code> is - * relative to the default initial context. - * @param environment The possibly null environment that is used in - * creating the object. - * @return The object created; null if an object cannot be created. - * @throws Exception if this object factory encountered an exception - * while attempting to create an object, and no other object factories are - * to be tried. - */ - public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable environment) throws Exception - { - if (obj instanceof Reference) - { - Reference ref = (Reference) obj; - - if (ref.getClassName().equals(QueueImpl.class.getName())) - { - RefAddr addr = ref.get(QueueImpl.class.getName()); - - if (addr != null) - { - return new QueueImpl(new BindingURLImpl((String) addr.getContent())); - } - } - - if (ref.getClassName().equals(TopicImpl.class.getName())) - { - RefAddr addr = ref.get(TopicImpl.class.getName()); - - if (addr != null) - { - return new TopicImpl(new BindingURLImpl((String) addr.getContent())); - } - } - - if (ref.getClassName().equals(DestinationImpl.class.getName())) - { - RefAddr addr = ref.get(DestinationImpl.class.getName()); - - if (addr != null) - { - return new DestinationImpl(new BindingURLImpl((String) addr.getContent())); - } - } - - if (ref.getClassName().equals(ConnectionFactoryImpl.class.getName())) - { - RefAddr addr = ref.get(ConnectionFactoryImpl.class.getName()); - if (addr != null) - { - return new ConnectionFactoryImpl(new QpidURLImpl((String) addr.getContent())); - } - } - - } - return null; - } - - //-- interface Reference - /** - * Retrieves the Reference of this object. - * - * @return The non-null Reference of this object. - * @throws NamingException If a naming exception was encountered while retrieving the reference. - */ - public Reference getReference() throws NamingException - { - return new Reference(ConnectionFactoryImpl.class.getName(), - new StringRefAddr(ConnectionFactoryImpl.class.getName(), _qpidURL.getURL()), - ConnectionFactoryImpl.class.getName(), null); - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/ConnectionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/ConnectionImpl.java deleted file mode 100644 index de313e7bed..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/ConnectionImpl.java +++ /dev/null @@ -1,503 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import java.util.Vector; - -import javax.jms.Connection; -import javax.jms.ConnectionConsumer; -import javax.jms.ConnectionMetaData; -import javax.jms.Destination; -import javax.jms.ExceptionListener; -import javax.jms.IllegalStateException; -import javax.jms.JMSException; -import javax.jms.Queue; -import javax.jms.QueueSession; -import javax.jms.ServerSessionPool; -import javax.jms.Session; -import javax.jms.Topic; -import javax.jms.TopicSession; - -import org.apache.qpid.url.QpidURL; -import org.apache.qpidity.QpidException; -import org.apache.qpidity.nclient.Client; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -/** - * Implements javax.njms.Connection, javax.njms.QueueConnection and javax.njms.TopicConnection - */ -public class ConnectionImpl implements Connection -{ - /** - * This class's logger - */ - private static final Logger _logger = LoggerFactory.getLogger(ConnectionImpl.class); - - /** - * Maps from session id (Integer) to SessionImpl instance - */ - protected final Vector<SessionImpl> _sessions = new Vector<SessionImpl>(); - - /** - * This is the clientID - */ - private String _clientID; - - /** - * The Exception listenr get informed when a serious problem is detected - */ - private ExceptionListener _exceptionListener; - - /** - * Whether this connection is started, i.e. whether messages are flowing to consumers. - * It has no meaning for message publication. - */ - private boolean _started; - - /** - * set to true if this Connection has been closed. - * <p/> - * A closed Connection cannot accept invocations to any of its methods with the exception - * of close(). All other methods should throw javax.njms.IllegalStateExceptions if the - * Connection has been closed. - * <p/> - * A Connection is open after creation, but not started. Once it has been closed, a Connection - * cannot be reused any more. - */ - private boolean _isClosed = false; - - - /** - * The QpidConeection instance that is mapped with thie JMS connection - */ - org.apache.qpidity.nclient.Connection _qpidConnection; - - /** - * This is the exception listener for this qpid connection. - * The njms exception listener is registered with this listener. - */ - QpidExceptionListenerImpl _qpidExceptionListener; - - //------ Constructors ---// - /** - * Create a connection. - * - * @param host The broker host name. - * @param port The port on which the broker is listening for connection. - * @param virtualHost The virtual host on which the broker is deployed. - * @param username The user name used of user identification. - * @param password The password name used of user identification. - * @throws QpidException If creating a connection fails due to some internal error. - */ - protected ConnectionImpl(String host, int port, String virtualHost, String username, String password) - throws QpidException - { - _qpidConnection = Client.createConnection(); - _qpidConnection.connect(host, port, virtualHost, username, password); - } - - /** - * Create a connection from a QpidURL - * - * @param qpidURL The url used to create this connection - * @throws QpidException If creating a connection fails due to some internal error. - */ - protected ConnectionImpl(QpidURL qpidURL) throws QpidException - { - _qpidConnection = Client.createConnection(); - //_qpidConnection.connect(qpidURL); - } - - //---- Interface javax.njms.Connection ---// - /** - * Creates a Session - * - * @param transacted Indicates whether the session is transacted. - * @param acknowledgeMode ignored if the session is transacted. Legal values are <code>Session.AUTO_ACKNOWLEDGE</code>, - * <code>Session.CLIENT_ACKNOWLEDGE</code>, and <code>Session.DUPS_OK_ACKNOWLEDGE</code>. - * @return A newly created session - * @throws JMSException If the Connection object fails to create a session due to some internal error. - */ - public synchronized Session createSession(boolean transacted, int acknowledgeMode) throws JMSException - { - checkNotClosed(); - SessionImpl session; - try - { - session = new SessionImpl(this, transacted, acknowledgeMode, false); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - // add this session with the list of session that are handled by this connection - _sessions.add(session); - return session; - } - - /** - * Gets the client identifier for this connection. - * <P>It is either preconfigured as a JNDI property or assigned dynamically by the application - * by calling the <code>setClientID</code> method. - * <p/> - * TODO: Make sure that the client identifier can be set on the <CODE>ConnectionFactory</CODE> - * - * @return The unique client identifier. - * @throws JMSException If this connection is closed. - */ - public String getClientID() throws JMSException - { - checkNotClosed(); - return _clientID; - } - - /** - * Sets the client identifier for this connection. - * <P>The preferred way to assign a JMS client's client identifier is for - * it to be configured in a client-specific <CODE>ConnectionFactory</CODE> - * object and transparently assigned to the <CODE>Connection</CODE> object - * it creates. - * <p> In Qpid it is not possible to change the client ID. If one is not specified - * upon connection construction, an id is generated automatically. Therefore - * we can always throw an exception. - * TODO: Make sure that the client identifier can be set on the <CODE>ConnectionFactory</CODE> - * - * @param clientID the unique client identifier - * @throws JMSException Always as clientID is always set at construction time. - */ - public void setClientID(String clientID) throws JMSException - { - checkNotClosed(); - throw new IllegalStateException("Client name cannot be changed after being set"); - } - - /** - * Gets the metadata for this connection. - * - * @return The connection metadata - * @throws JMSException If there ie a problem getting the connection metadata for this connection. - * @see javax.jms.ConnectionMetaData - */ - public ConnectionMetaData getMetaData() throws JMSException - { - checkNotClosed(); - return ConnectionMetaDataImpl.getInstance(); - } - - /** - * Gets the <CODE>ExceptionListener</CODE> object for this connection. - * - * @return the <CODE>ExceptionListener</CODE> for this connection - * @throws JMSException In case of unforeseen problem - */ - public synchronized ExceptionListener getExceptionListener() throws JMSException - { - checkNotClosed(); - return _exceptionListener; - } - - /** - * Sets an exception listener for this connection. - * <p/> - * <p> The JMS specification says: - * <P>If a JMS provider detects a serious problem with a connection, it - * informs the connection's <CODE>ExceptionListener</CODE>, if one has been - * registered. It does this by calling the listener's - * <CODE>onException</CODE> method, passing it a <CODE>JMSException</CODE> - * object describing the problem. - * <p/> - * <P>A connection serializes execution of its - * <CODE>ExceptionListener</CODE>. - * <p/> - * <P>A JMS provider should attempt to resolve connection problems - * itself before it notifies the client of them. - * - * @param exceptionListener The connection listener. - * @throws JMSException If the connection is closed. - */ - public synchronized void setExceptionListener(ExceptionListener exceptionListener) throws JMSException - { - checkNotClosed(); - _exceptionListener = exceptionListener; - _qpidExceptionListener.setJMSExceptionListner(_exceptionListener); - } - - /** - * Starts (or restarts) a connection's delivery of incoming messages. - * A call to start on a connection that has already been - * started is ignored. - * - * @throws JMSException In case of a problem due to some internal error. - */ - public synchronized void start() throws JMSException - { - checkNotClosed(); - if (!_started) - { - // start all the sessions - for (SessionImpl session : _sessions) - { - try - { - session.start(); - } - catch (Exception e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - _started = true; - } - } - - /** - * Temporarily stops a connection's delivery of incoming messages. - * <p> The JMS specification says: - * <p> Delivery can be restarted using the connection's <CODE>start</CODE> - * method. When the connection is stopped, delivery to all the connection's message consumers is inhibited: - * synchronous receives block, and messages are not delivered to message listeners. - * <P>This call blocks until receives and/or message listeners in progress have completed. - * - * @throws JMSException In case of a problem due to some internal error. - */ - public synchronized void stop() throws JMSException - { - checkNotClosed(); - if (_started) - { - // stop all the sessions - for (SessionImpl session : _sessions) - { - try - { - session.stop(); - } - catch (Exception e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - _started = false; - } - } - - /** - * Closes the connection. - * <p/> - * <p> The JMS specification says: - * <P>Since a provider typically allocates significant resources outside - * the JVM on behalf of a connection, clients should close these resources - * when they are not needed. Relying on garbage collection to eventually - * reclaim these resources may not be timely enough. - * <P>There is no need to close the sessions, producers, and consumers of a closed connection. - * <P>Closing a connection causes all temporary destinations to be deleted. - * <P>When this method is invoked, it should not return until message - * processing has been shut down in an orderly fashion. - * - * @throws JMSException In case of a problem due to some internal error. - */ - public synchronized void close() throws JMSException - { - checkNotClosed(); - if (!_isClosed) - { - _isClosed = true; - _started = false; - // close all the sessions - for (SessionImpl session : _sessions) - { - session.close(); - } - // close the underlaying Qpid connection - try - { - _qpidConnection.close(); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - } - - /** - * Creates a connection consumer for this connection (optional operation). - * This is an expert facility for App server integration. - * - * @param destination The destination to access. - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @param sessionPool The session pool to associate with this connection consumer. - * @param maxMessages The maximum number of messages that can be assigned to a server session at one time. - * @return Null for the moment. - * @throws JMSException In case of a problem due to some internal error. - */ - public ConnectionConsumer createConnectionConsumer(Destination destination, String messageSelector, - ServerSessionPool sessionPool, int maxMessages) - throws JMSException - { - checkNotClosed(); - return null; - } - - /** - * Create a durable connection consumer for this connection (optional operation). - * - * @param topic The topic to access. - * @param subscriptionName Durable subscription name. - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @param sessionPool The server session pool to associate with this durable connection consumer. - * @param maxMessages The maximum number of messages that can be assigned to a server session at one time. - * @return Null for the moment. - * @throws JMSException In case of a problem due to some internal error. - */ - public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName, - String messageSelector, ServerSessionPool sessionPool, - int maxMessages) throws JMSException - { - checkNotClosed(); - return null; - } - - //-------------- QueueConnection API - - /** - * Create a QueueSession. - * - * @param transacted Indicates whether the session is transacted. - * @param acknowledgeMode Indicates whether the consumer or the - * client will acknowledge any messages it receives; ignored if the session - * is transacted. Legal values are <code>Session.AUTO_ACKNOWLEDGE</code>, - * <code>Session.CLIENT_ACKNOWLEDGE</code> and <code>Session.DUPS_OK_ACKNOWLEDGE</code>. - * @return A queueSession object/ - * @throws JMSException If creating a QueueSession fails due to some internal error. - */ - public synchronized QueueSession createQueueSession(boolean transacted, int acknowledgeMode) throws JMSException - { - checkNotClosed(); - QueueSessionImpl queueSession; - try - { - queueSession = new QueueSessionImpl(this, transacted, acknowledgeMode); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - // add this session to the list of handled sessions. - _sessions.add(queueSession); - return queueSession; - } - - /** - * Creates a connection consumer for this connection (optional operation). - * This is an expert facility for App server integration. - * - * @param queue The queue to access. - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @param sessionPool The session pool to associate with this connection consumer. - * @param maxMessages The maximum number of messages that can be assigned to a server session at one time. - * @return Null for the moment. - * @throws JMSException In case of a problem due to some internal error. - */ - public ConnectionConsumer createConnectionConsumer(Queue queue, String messageSelector, - ServerSessionPool sessionPool, int maxMessages) - throws JMSException - { - return createConnectionConsumer((Destination) queue, messageSelector, sessionPool, maxMessages); - } - - //-------------- TopicConnection API - /** - * Create a TopicSession. - * - * @param transacted Indicates whether the session is transacted - * @param acknowledgeMode Legal values are <code>Session.AUTO_ACKNOWLEDGE</code>, <code>Session.CLIENT_ACKNOWLEDGE</code>, and - * <code>Session.DUPS_OK_ACKNOWLEDGE</code>. - * @return a newly created topic session - * @throws JMSException If creating the session fails due to some internal error. - */ - public synchronized TopicSession createTopicSession(boolean transacted, int acknowledgeMode) throws JMSException - { - checkNotClosed(); - TopicSessionImpl session; - try - { - session = new TopicSessionImpl(this, transacted, acknowledgeMode); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - // add the session with this Connection's sessions - // important for when the Connection is closed. - _sessions.add(session); - return session; - } - - /** - * Creates a connection consumer for this connection (optional operation). - * This is an expert facility for App server integration. - * - * @param topic The topic to access. - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @param sessionPool The session pool to associate with this connection consumer. - * @param maxMessages The maximum number of messages that can be assigned to a server session at one time. - * @return Null for the moment. - * @throws JMSException In case of a problem due to some internal error. - */ - public ConnectionConsumer createConnectionConsumer(Topic topic, String messageSelector, - ServerSessionPool sessionPool, int maxMessages) - throws JMSException - { - return createConnectionConsumer((Destination) topic, messageSelector, sessionPool, maxMessages); - } - - //-------------- protected and private methods - /** - * Validate that the Connection is not closed. - * <p/> - * If the Connection has been closed, throw a IllegalStateException. This behaviour is - * required by the JMS specification. - * - * @throws IllegalStateException If the session is closed. - */ - protected synchronized void checkNotClosed() throws IllegalStateException - { - if (_isClosed) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Connection has been closed. Cannot invoke any further operations."); - } - throw new javax.jms.IllegalStateException( - "Connection has been closed. Cannot invoke any further operations."); - } - } - - /** - * Provide access to the underlying qpid Connection. - * - * @return This JMS connection underlying Qpid Connection. - */ - protected org.apache.qpidity.nclient.Connection getQpidConnection() - { - return _qpidConnection; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/ConnectionMetaDataImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/ConnectionMetaDataImpl.java deleted file mode 100644 index 9f2e9104e6..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/ConnectionMetaDataImpl.java +++ /dev/null @@ -1,165 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import org.apache.qpid.common.QpidProperties; - -import javax.jms.ConnectionMetaData; -import javax.jms.JMSException; -import java.util.Enumeration; - -/** - * Implements javax.njms.ConnectionMetaData - * A ConnectionMetaDataImpl provides information describing the JMS <code>Connection</code>. - */ -public class ConnectionMetaDataImpl implements ConnectionMetaData -{ - - /** - * A singleton instance. - */ - static ConnectionMetaDataImpl _singleton = new ConnectionMetaDataImpl(); - - // ------------------------ The metadata - // JMS major version - private static final int JMS_MAJOR_VERSION = 1; - // JMS minor version - private static final int JMS_MINOR_VERSION = 1; - // JMS version - private static final String JMS_VERSION = "1.1"; - // Provider name - private static final String PROVIDER_NAME = "Apache " + QpidProperties.getProductName(); - // Provider major version - private static final int PROVIDER_MAJOR_VERSION = 0; - // Provider minor version - private static final int PROVIDER_MINOR_VERSION = 10; - // Provider version - private static final String PROVIDER_VERSION = QpidProperties.getProductName() + " (Client: [" + QpidProperties.getBuildVersion() + "] ; Protocol: [ 0.10 ] )"; - - /** - * Prevent instantiation. - */ - private ConnectionMetaDataImpl() - { - } - - /** - * Get the singleton instance of ConnectionMetaDataImpl. - * - * @return the singleton instance of ConnectionMetaDataImpl. - */ - public static ConnectionMetaDataImpl getInstance() - { - return _singleton; - } - - //-- Connection MetaData API - - /** - * Gets the JMS API version. - * - * @return the JMS API version - * @throws JMSException Never - */ - public String getJMSVersion() throws JMSException - { - return JMS_VERSION; - } - - - /** - * Gets the JMS major version number. - * - * @return the JMS API major version number - * @throws JMSException Never - */ - public int getJMSMajorVersion() throws JMSException - { - return JMS_MAJOR_VERSION; - } - - - /** - * Gets the JMS minor version number. - * - * @return the JMS API minor version number - * @throws JMSException Never - */ - public int getJMSMinorVersion() throws JMSException - { - return JMS_MINOR_VERSION; - } - - - /** - * Gets Qpid name. - * - * @return Qpid name - * @throws JMSException Never - */ - public String getJMSProviderName() throws JMSException - { - return PROVIDER_NAME; - } - - /** - * Gets Qpid version. - * - * @return Qpid version - * @throws JMSException Never - */ - public String getProviderVersion() throws JMSException - { - return PROVIDER_VERSION; - // TODO: We certainly can dynamically get the server version. - } - - /** - * Gets Qpid major version number. - * - * @return Qpid major version number - * @throws JMSException Never - */ - public int getProviderMajorVersion() throws JMSException - { - return PROVIDER_MAJOR_VERSION; - } - - /** - * Gets Qpid minor version number. - * - * @return Qpid minor version number - * @throws JMSException Never - */ - public int getProviderMinorVersion() throws JMSException - { - return PROVIDER_MINOR_VERSION; - } - - /** - * Gets an enumeration of the JMSX property names. - * - * @return an Enumeration of JMSX property names - * @throws JMSException if cannot retrieve metadata due to some internal error. - */ - public Enumeration getJMSXPropertyNames() throws JMSException - { - return CustomJMSXProperty.asEnumeration(); - } - -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/CustomJMSXProperty.java b/java/client/src/main/java/org/apache/qpidity/njms/CustomJMSXProperty.java deleted file mode 100644 index c2a3af1c9b..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/CustomJMSXProperty.java +++ /dev/null @@ -1,47 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms; - -import java.util.Enumeration; -import java.util.ArrayList; -import java.util.Collections; - -public enum CustomJMSXProperty -{ - JMS_AMQP_NULL, - JMS_QPID_DESTTYPE, - JMSXGroupID, - JMSXGroupSeq; - - private static Enumeration _names; - - public static synchronized Enumeration asEnumeration() - { - if (_names == null) - { - CustomJMSXProperty[] properties = values(); - ArrayList<String> nameList = new ArrayList<String>(properties.length); - for (CustomJMSXProperty property : properties) - { - nameList.add(property.toString()); - } - _names = Collections.enumeration(nameList); - } - return _names; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/DestinationImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/DestinationImpl.java deleted file mode 100644 index c4111db790..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/DestinationImpl.java +++ /dev/null @@ -1,259 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import org.apache.qpidity.QpidException; -import org.apache.qpid.url.URLSyntaxException; -import org.apache.qpid.url.QpidBindingURL; -import org.apache.qpid.url.BindingURLImpl; -import org.apache.qpid.url.URLHelper; - -import javax.jms.Destination; -import javax.naming.Reference; -import javax.naming.NamingException; -import javax.naming.StringRefAddr; -import javax.naming.Referenceable; - -/** - * Implementation of the JMS Destination interface - */ -public class DestinationImpl implements Destination, Referenceable -{ - /** - * The destination's name - */ - protected String _destinationName = null; - - /** - * The excahnge name - */ - protected String _exchangeName; - - /** - * The excahnge class - */ - protected String _exchangeType; - - /** - * The queue name - */ - protected String _queueName; - - /** - * Indicate whether this destination is exclusive - */ - protected boolean _isExclusive; - - /** - * Indicates whether this destination is auto delete. - */ - protected boolean _isAutoDelete; - - /** - * Indicates whether this destination is durable - */ - protected boolean _isDurable; - - protected String _routingKey; - - /** - * The biding URL used to create this destiantion - */ - protected QpidBindingURL _url; - - //--- Constructor - - protected DestinationImpl(String name) throws QpidException - { - _queueName = name; - _routingKey = name; - } - - /** - * Create a destiantion from a binding URL - * - * @param binding The URL - * @throws QpidException If the URL is not valid - */ - public DestinationImpl(QpidBindingURL binding) throws QpidException - { - _exchangeName = binding.getExchangeName(); - _exchangeType = binding.getExchangeClass(); - _destinationName = binding.getDestinationName(); - _isExclusive = Boolean.parseBoolean(binding.getOption(QpidBindingURL.OPTION_EXCLUSIVE)); - _isAutoDelete = Boolean.parseBoolean(binding.getOption(QpidBindingURL.OPTION_AUTODELETE)); - _isDurable = Boolean.parseBoolean(binding.getOption(QpidBindingURL.OPTION_DURABLE)); - _queueName = binding.getQueueName(); - _routingKey = binding.getQueueName(); - _url = binding; - } - - //---- Getters and Setters - /** - * Overrides Object.toString(); - * - * @return Stringified destination representation. - */ - public String toString() - { - return _destinationName; - } - - /** - * Get the destination name. - * - * @return The destination name - */ - public String getDestinationName() - { - return _destinationName; - } - - - /** - * The exchange name - * - * @return The exchange name - */ - public String getExchangeName() - { - return _exchangeName; - } - - /** - * The exchange type. - * - * @return The exchange type. - */ - public String getExchangeType() - { - return _exchangeType; - } - - /** - * The queue name. - * - * @return The queue name. - */ - public String getQpidQueueName() - { - return _queueName; - } - - /** - * Indicates whether this destination is exclusive. - * - * @return true if this destination is exclusive. - */ - public boolean isExclusive() - { - return _isExclusive; - } - - /** - * Indicates whether this destination is AutoDelete. - * - * @return true if this destination is AutoDelete. - */ - public boolean isAutoDelete() - { - return _isAutoDelete; - } - - public String getRoutingKey() - { - return _routingKey; - } - - /** - * Indicates whether this destination is Durable. - * - * @return true if this destination is Durable. - */ - public boolean isDurable() - { - return _isDurable; - } - - //----- Interface Referenceable - public Reference getReference() throws NamingException - { - return new Reference(this.getClass().getName(), new StringRefAddr(this.getClass().getName(), toURL()), - ConnectionFactoryImpl.class.getName(), // factory - null); // factory location - } - - //--- non public method s - - /** - * Get the URL used to create this destiantion - * - * @return The URL used to create this destiantion - */ - public String toURL() - { - if (_url == null) - { - StringBuffer sb = new StringBuffer(); - sb.append(_exchangeType); - sb.append("://"); - sb.append(_exchangeName); - sb.append('/'); - if (_destinationName != null) - { - sb.append(_destinationName); - } - sb.append('/'); - if (_queueName != null) - { - sb.append(_queueName); - } - sb.append('?'); - if (_isDurable) - { - sb.append(org.apache.qpid.url.QpidBindingURL.OPTION_DURABLE); - sb.append("='true'"); - sb.append(URLHelper.DEFAULT_OPTION_SEPERATOR); - } - if (_isExclusive) - { - sb.append(org.apache.qpid.url.QpidBindingURL.OPTION_EXCLUSIVE); - sb.append("='true'"); - sb.append(URLHelper.DEFAULT_OPTION_SEPERATOR); - } - if (_isAutoDelete) - { - sb.append(org.apache.qpid.url.QpidBindingURL.OPTION_AUTODELETE); - sb.append("='true'"); - sb.append(URLHelper.DEFAULT_OPTION_SEPERATOR); - } - //removeKey the last char '?' if there is no options , ',' if there are. - sb.deleteCharAt(sb.length() - 1); - try - { - _url = new BindingURLImpl(sb.toString()); - } - catch (URLSyntaxException e) - { - // this should not happen. - } - } - return _url.getURL(); - } -} - diff --git a/java/client/src/main/java/org/apache/qpidity/njms/ExceptionHelper.java b/java/client/src/main/java/org/apache/qpidity/njms/ExceptionHelper.java deleted file mode 100644 index e00f9008d3..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/ExceptionHelper.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.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.JMSException; -import javax.transaction.xa.XAException; - -/** - * Helper class for handling exceptions - */ -public class ExceptionHelper -{ - static public JMSException convertQpidExceptionToJMSException(Exception exception) - { - JMSException jmsException = null; - if (!(exception instanceof JMSException)) - { - if (exception instanceof QpidException) - { - jmsException = new JMSException(exception.getMessage(), String.valueOf(((QpidException) exception).getErrorCode())); - } - else - { - jmsException = new JMSException(exception.getMessage()); - } - jmsException.setLinkedException(exception); - jmsException.initCause(exception); - } - else - { - jmsException = (JMSException) exception; - } - return jmsException; - } - - static public XAException convertQpidExceptionToXAException(QpidException exception) - { - String qpidErrorCode = String.valueOf(exception.getErrorCode()); - // todo map this error to an XA code - int xaCode = XAException.XAER_PROTO; - return new XAException(xaCode); - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/MessageActor.java b/java/client/src/main/java/org/apache/qpidity/njms/MessageActor.java deleted file mode 100644 index 698bccdeb5..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/MessageActor.java +++ /dev/null @@ -1,176 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.jms.IllegalStateException; -import javax.jms.JMSException; - -/** - * MessageActor is the superclass for MessageProducerImpl and MessageProducerImpl. - */ -public abstract class MessageActor -{ - /** - * Used for debugging. - */ - protected static final Logger _logger = LoggerFactory.getLogger(MessageActor.class); - - /** - * Indicates whether this MessageActor is closed. - */ - protected boolean _isClosed = false; - - /** - * This messageActor's session - */ - private SessionImpl _session; - - /** - * The JMS destination this actor is set for. - */ - DestinationImpl _destination; - - /** - * Indicates that this actor is stopped - */ - protected boolean _isStopped; - - /** - * The ID of this actor for the session. - */ - private String _messageActorID; - - //-- Constructor - - //TODO define the parameters - - protected MessageActor(String messageActorID) - { - _messageActorID = messageActorID; - } - - protected MessageActor(SessionImpl session, DestinationImpl destination,String messageActorID) - { - _session = session; - _destination = destination; - _messageActorID = messageActorID; - } - - //--- public methods (part of the njms public API) - /** - * Closes the MessageActor and deregister it from its session. - * - * @throws JMSException if the MessaeActor cannot be closed due to some internal error. - */ - public void close() throws JMSException - { - if (!_isClosed) - { - closeMessageActor(); - getSession().getQpidSession().messageCancel(getMessageActorID()); - //todo: We need to unset the qpid message listener - // notify the session that this message actor is closing - _session.closeMessageActor(this); - } - } - - //-- protected methods - - /** - * Stop this message actor - * - * @throws Exception If the consumer cannot be stopped due to some internal error. - */ - protected void stop() throws Exception - { - _isStopped = true; - } - - /** - * Start this message Actor - * - * @throws Exception If the consumer cannot be started due to some internal error. - */ - protected void start() throws Exception - { - - _isStopped = false; - - } - - /** - * Check if this MessageActor is not closed. - * <p> If the MessageActor is closed, throw a javax.njms.IllegalStateException. - * <p> The method is not synchronized, since MessageProducers can only be used by a single thread. - * - * @throws IllegalStateException if the MessageActor is closed - */ - protected void checkNotClosed() throws IllegalStateException - { - if (_isClosed || _session == null) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Actor " + this + " is already closed"); - } - throw new IllegalStateException("Actor " + this + " is already closed"); - } - _session.checkNotClosed(); - } - - /** - * Closes a MessageActor. - * <p> This method is invoked when the session is closing or when this - * messageActor is closing. - * - * @throws JMSException If the MessaeActor cannot be closed due to some internal error. - */ - protected void closeMessageActor() throws JMSException - { - if (!_isClosed) - { - getSession().getQpidSession().messageCancel(getMessageActorID()); - _isClosed = true; - } - } - - /** - * Get the associated session object. - * - * @return This Actor's Session. - */ - public SessionImpl getSession() - { - return _session; - } - - /** - * Get the ID of this actor within its session. - * - * @return This actor ID. - */ - protected String getMessageActorID() - { - return _messageActorID; - } - - -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/MessageConsumerImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/MessageConsumerImpl.java deleted file mode 100644 index 0b0b794135..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/MessageConsumerImpl.java +++ /dev/null @@ -1,672 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.TimeUnit; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.Queue; - -import org.apache.qpidity.QpidException; -import org.apache.qpidity.nclient.MessagePartListener; -import org.apache.qpidity.nclient.Session; -import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; -import org.apache.qpidity.exchange.ExchangeDefaults; -import org.apache.qpidity.filter.JMSSelectorFilter; -import org.apache.qpidity.filter.MessageFilter; -import org.apache.qpidity.njms.message.MessageFactory; -import org.apache.qpidity.njms.message.QpidMessage; -import org.apache.qpidity.transport.Option; -import org.apache.qpidity.transport.RangeSet; - -/** - * Implementation of JMS message consumer - */ -public class MessageConsumerImpl extends MessageActor - implements MessageConsumer, org.apache.qpidity.nclient.util.MessageListener -{ - // we can receive up to 100 messages for an asynchronous listener - public static final int MAX_MESSAGE_TRANSFERRED = 100; - - /** - * This MessageConsumer's messageselector. - */ - private String _messageSelector = null; - - /** - * The message selector filter associated with this consumer message selector - */ - private MessageFilter _filter = null; - - /** - * NoLocal - * If true, and the destination is a topic then inhibits the delivery of messages published - * by its own connection. The behavior for NoLocal is not specified if the destination is a queue. - */ - protected boolean _noLocal; - - /** - * The subscription name - */ - protected String _subscriptionName; - - /** - * Indicates whether this consumer receives pre-acquired messages - */ - private boolean _preAcquire = true; - - /** - * A MessagePartListener set up for this consumer. - */ - private MessageListener _messageListener; - - /** - * A lcok on the syncrhonous message - */ - private final Object _incomingMessageLock = new Object(); - - - /** - * Number of mesages received asynchronously - * Nether exceed MAX_MESSAGE_TRANSFERRED - */ - private int _messageAsyncrhonouslyReceived = 0; - - private LinkedBlockingQueue<QpidMessage> _queue = new LinkedBlockingQueue<QpidMessage>(); - - //----- Constructors - /** - * Create a new MessageProducerImpl. - * - * @param session The session from which the MessageProducerImpl is instantiated - * @param destination The default destination for this MessageProducerImpl - * @param messageSelector The message selector for this QueueReceiverImpl. - * @param noLocal If true inhibits the delivery of messages published by its own connection. - * @param subscriptionName Name of the subscription if this is to be created as a durable subscriber. - * If this value is null, a non-durable subscription is created. - * @param consumerTag Thi actor ID - * @throws Exception If the MessageProducerImpl cannot be created due to some internal error. - */ - protected MessageConsumerImpl(SessionImpl session, DestinationImpl destination, String messageSelector, - boolean noLocal, String subscriptionName, String consumerTag) throws Exception - { - super(session, destination, consumerTag); - if (messageSelector != null) - { - _messageSelector = messageSelector; - _filter = new JMSSelectorFilter(messageSelector); - } - _noLocal = noLocal; - _subscriptionName = subscriptionName; - _isStopped = getSession().isStopped(); - // let's create a message part assembler - - MessagePartListener messageAssembler = new MessagePartListenerAdapter(this); - - if (destination instanceof Queue) - { - // this is a queue we expect that this queue exists - getSession().getQpidSession() - .messageSubscribe(destination.getQpidQueueName(), // queue - getMessageActorID(), // destination - org.apache.qpidity.nclient.Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED, - // When the message selctor is set we do not acquire the messages - _messageSelector != null ? org.apache.qpidity.nclient.Session.TRANSFER_ACQUIRE_MODE_NO_ACQUIRE : org.apache.qpidity.nclient.Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE, - messageAssembler, null, _noLocal ? Option.NO_LOCAL : Option.NO_OPTION); - if (_messageSelector != null) - { - _preAcquire = false; - } - } - else - { - // this is a topic we need to create a temporary queue for this consumer - // unless this is a durable subscriber - String queueName; - if (subscriptionName != null) - { - // this ia a durable subscriber - // create a persistent queue for this subscriber - queueName = "topic-" + subscriptionName; - getSession().getQpidSession() - .queueDeclare(queueName, null, null, Option.EXCLUSIVE, Option.DURABLE); - } - else - { - // this is a non durable subscriber - queueName = destination.getQpidQueueName(); - getSession().getQpidSession() - .queueDeclare(queueName, null, null, Option.AUTO_DELETE, Option.EXCLUSIVE); - } - // bind this queue with the topic exchange - getSession().getQpidSession() - .queueBind(queueName, ExchangeDefaults.TOPIC_EXCHANGE_NAME, destination.getRoutingKey(), null); - // subscribe to this topic - getSession().getQpidSession() - .messageSubscribe(queueName, getMessageActorID(), - org.apache.qpidity.nclient.Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED, - // We always acquire the messages - org.apache.qpidity.nclient.Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE, - messageAssembler, null, _noLocal ? Option.NO_LOCAL : Option.NO_OPTION, - // Request exclusive subscription access, meaning only this subscription - // can access the queue. - Option.EXCLUSIVE); - - } - // set the flow mode - getSession().getQpidSession() - .messageFlowMode(getMessageActorID(), org.apache.qpidity.nclient.Session.MESSAGE_FLOW_MODE_CREDIT); - // Set unlimited byte credits - getSession().getQpidSession().messageFlow(getMessageActorID(), Session.MESSAGE_FLOW_UNIT_BYTE, -1); - - // this will prevent the broker from sending more than one message - // When a messageListener is set the flow will be adjusted. - // until then we assume it's for synchronous message consumption - requestCredit(1); - try - { - requestSync(); - } - catch(Exception e) - { - e.printStackTrace(); - } - // check for an exception - if (getSession().getCurrentException() != null) - { - throw getSession().getCurrentException(); - } - } - - //----- Message consumer API - /** - * Gets this MessageConsumer's message selector. - * - * @return This MessageConsumer's message selector, or null if no - * message selector exists for the message consumer (that is, if - * the message selector was not set or was set to null or the - * empty string) - * @throws JMSException if getting the message selector fails due to some internal error. - */ - public String getMessageSelector() throws JMSException - { - checkNotClosed(); - return _messageSelector; - } - - /** - * Gets this MessageConsumer's <CODE>MessagePartListener</CODE>. - * - * @return The listener for the MessageConsumer, or null if no listener is set - * @throws JMSException if getting the message listener fails due to some internal error. - */ - public MessageListener getMessageListener() throws JMSException - { - checkNotClosed(); - return _messageListener; - } - - /** - * Sets the MessageConsumer's <CODE>MessagePartListener</CODE>. - * <p> The JMS specification says: - * <P>Setting the message listener to null is the equivalent of - * unsetting the message listener for the message consumer. - * <P>The effect of calling <CODE>MessageConsumer.setMessageListener</CODE> - * while messages are being consumed by an existing listener - * or the consumer is being used to consume messages synchronously - * is undefined. - * - * @param messageListener The listener to which the messages are to be delivered - * @throws JMSException If setting the message listener fails due to some internal error. - */ - public synchronized void setMessageListener(MessageListener messageListener) throws JMSException - { - // this method is synchronized as onMessage also access _messagelistener - // onMessage, getMessageListener and this method are the only synchronized methods - checkNotClosed(); - try - { - _messageListener = messageListener; - if (messageListener != null) - { - resetAsynchMessageReceived(); - } - } - catch (Exception e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Contact the broker and ask for the delivery of MAX_MESSAGE_TRANSFERRED messages - * - * @throws QpidException If there is a communication error - */ - private void resetAsynchMessageReceived() throws QpidException - { - if (!_isStopped && _messageAsyncrhonouslyReceived >= MAX_MESSAGE_TRANSFERRED) - { - getSession().getQpidSession().messageStop(getMessageActorID()); - } - _messageAsyncrhonouslyReceived = 0; - requestCredit(MAX_MESSAGE_TRANSFERRED); - } - - /** - * Receive the next message produced for this message consumer. - * <P>This call blocks indefinitely until a message is produced or until this message consumer is closed. - * - * @return The next message produced for this message consumer, or - * null if this message consumer is concurrently closed - * @throws JMSException If receiving the next message fails due to some internal error. - */ - public Message receive() throws JMSException - { - // Check if we can get a message immediately - Message result; - result = receiveNoWait(); - if (result != null) - { - return result; - } - try - { - // Now issue a credit and wait for the broker to send a message - // IMO no point doing a credit() flush() and sync() in a loop. - // This will only overload the broker. After the initial try we can wait - // for the broker to send a message when it gets one - requestCredit(1); - return (Message) _queue.take(); - } - catch (Exception e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Receive the next message that arrives within the specified timeout interval. - * <p> This call blocks until a message arrives, the timeout expires, or this message consumer - * is closed. - * <p> A timeout of zero never expires, and the call blocks indefinitely. - * <p> A timeout less than 0 throws a JMSException. - * - * @param timeout The timeout value (in milliseconds) - * @return The next message that arrives within the specified timeout interval. - * @throws JMSException If receiving the next message fails due to some internal error. - */ - public Message receive(long timeout) throws JMSException - { - checkClosed(); - checkIfListenerSet(); - if (timeout < 0) - { - throw new JMSException("Invalid timeout value: " + timeout); - } - - Message result; - try - { - // first check if we have any in the queue already - result = (Message) _queue.poll(); - if (result == null) - { - requestCredit(1); - requestFlush(); - // We shouldn't do a sync(). Bcos the timeout can happen - // before the sync() returns - return (Message) _queue.poll(timeout, TimeUnit.MILLISECONDS); - } - else - { - return result; - } - } - catch (Exception e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Receive the next message if one is immediately available. - * - * @return the next message or null if one is not available. - * @throws JMSException If receiving the next message fails due to some internal error. - */ - public Message receiveNoWait() throws JMSException - { - checkClosed(); - checkIfListenerSet(); - Message result; - try - { - // first check if we have any in the queue already - result = (Message) _queue.poll(); - if (result == null) - { - requestCredit(1); - requestFlush(); - requestSync(); - return (Message) _queue.poll(); - } - else - { - return result; - } - } - catch (Exception e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - // not public methods - /** - * Upon receipt of this method, the broker adds "value" - * number of messages to the available credit balance for this consumer. - * - * @param value Number of credits, a value of 0 indicates an infinite amount of credit. - */ - private void requestCredit(int value) - { - getSession().getQpidSession() - .messageFlow(getMessageActorID(), org.apache.qpidity.nclient.Session.MESSAGE_FLOW_UNIT_MESSAGE, value); - } - - /** - * Forces the broker to exhaust its credit supply. - * <p> The broker's credit will always be zero when - * this method completes. - */ - private void requestFlush() - { - getSession().getQpidSession().messageFlush(getMessageActorID()); - } - - /** - * Sync method will block until all outstanding broker - * commands - * are executed. - */ - private void requestSync() - { - getSession().getQpidSession().sync(); - } - - /** - * Check whether this consumer is closed. - * - * @throws JMSException If this consumer is closed. - */ - private void checkClosed() throws JMSException - { - if (_isStopped) - { - throw new JMSException("Session is closed"); - } - } - - /** - * Stop the delivery of messages to this consumer. - * <p>For asynchronous receiver, this operation blocks until the message listener - * finishes processing the current message, - * - * @throws Exception If the consumer cannot be stopped due to some internal error. - */ - protected void stop() throws Exception - { - getSession().getQpidSession().messageStop(getMessageActorID()); - _isStopped = true; - } - - /** - * Start the delivery of messages to this consumer. - * - * @throws Exception If the consumer cannot be started due to some internal error. - */ - protected void start() throws Exception - { - synchronized (_incomingMessageLock) - { - _isStopped = false; - } - } - - /** - * This method notifies this consumer that a message has been delivered - * @param message The received message. - */ - public void onMessage(org.apache.qpidity.api.Message message) - { - try - { - QpidMessage jmsMessage = MessageFactory.getQpidMessage(message); - if (checkPreConditions(jmsMessage)) - { - preApplicationProcessing(jmsMessage); - - if (_messageListener == null) - { - _queue.offer(jmsMessage); - } - else - { - // I still think we don't need that additional thread in SessionImpl - // if the Application blocks on a message thats fine - // getSession().dispatchMessage(getMessageActorID(), jmsMessage); - notifyMessageListener(jmsMessage); - } - } - } - catch (Exception e) - { - throw new RuntimeException(e.getMessage()); - } - } - - - public void notifyMessageListener(QpidMessage message) throws RuntimeException - { - try - { - _messageAsyncrhonouslyReceived++; - if (_messageAsyncrhonouslyReceived >= MAX_MESSAGE_TRANSFERRED) - { - // ask the server for the delivery of MAX_MESSAGE_TRANSFERRED more messages - resetAsynchMessageReceived(); - } - - // The JMS specs says: - /* The result of a listener throwing a RuntimeException depends on the session?s - * acknowledgment mode. - ? --- AUTO_ACKNOWLEDGE or DUPS_OK_ACKNOWLEDGE - the message - * will be immediately redelivered. The number of times a JMS provider will - * redeliver the same message before giving up is provider-dependent. - ? --- CLIENT_ACKNOWLEDGE - the next message for the listener is delivered. - * --- Transacted Session - the next message for the listener is delivered. - * - * The number of time we try redelivering the message is 0 - **/ - try - { - - _messageListener.onMessage((Message) message); - } - catch (RuntimeException re) - { - // do nothing as this message will not be redelivered - } - - - } - catch (Exception e) - { - throw new RuntimeException(e.getMessage()); - } - } - - /** - * Check whether this consumer is asynchronous - * - * @throws javax.jms.IllegalStateException If this consumer is asynchronous. - */ - private void checkIfListenerSet() throws javax.jms.IllegalStateException - { - - if (_messageListener != null) - { - throw new javax.jms.IllegalStateException("A listener has already been set."); - } - } - - /** - * pre process a received message. - * - * @param message The message to pre-process. - * @throws Exception If the message cannot be pre-processed due to some internal error. - */ - private void preApplicationProcessing(QpidMessage message) throws Exception - { - getSession().preProcessMessage(message); - // If the session is transacted we need to ack the message first - // This is because a message is associated with its tx only when acked - if (getSession().getTransacted()) - { - getSession().acknowledgeMessage(message); - } - message.afterMessageReceive(); - } - - /** - * Check whether a message can be delivered to this consumer. - * - * @param message The message to be checked. - * @return true if the message matches the selector and can be acquired, false otherwise. - * @throws QpidException If the message preConditions cannot be checked due to some internal error. - */ - private boolean checkPreConditions(QpidMessage message) throws QpidException - { - boolean messageOk = true; - if (_messageSelector != null) - { - messageOk = false; //_filter.matches(message); - } - if (_logger.isDebugEnabled()) - { - _logger.debug("messageOk " + messageOk); - _logger.debug("_preAcquire " + _preAcquire); - } - if (!messageOk && _preAcquire) - { - // this is the case for topics - // We need to ack this message - if (_logger.isDebugEnabled()) - { - _logger.debug("filterMessage - trying to ack message"); - } - acknowledgeMessage(message); - } - else if (!messageOk) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Message not OK, releasing"); - } - releaseMessage(message); - } - // now we need to acquire this message if needed - // this is the case of queue with a message selector set - if (!_preAcquire && messageOk) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("filterMessage - trying to acquire message"); - } - messageOk = acquireMessage(message); - } - return messageOk; - } - - /** - * Release a message - * - * @param message The message to be released - * @throws QpidException If the message cannot be released due to some internal error. - */ - private void releaseMessage(QpidMessage message) throws QpidException - { - if (_preAcquire) - { - RangeSet ranges = new RangeSet(); - ranges.add(message.getMessageTransferId()); - getSession().getQpidSession().messageRelease(ranges); - getSession().testQpidException(); - } - } - - /** - * Acquire a message - * - * @param message The message to be acquired - * @return true if the message has been acquired, false otherwise. - * @throws QpidException If the message cannot be acquired due to some internal error. - */ - private boolean acquireMessage(QpidMessage message) throws QpidException - { - boolean result = false; - if (!_preAcquire) - { - RangeSet ranges = new RangeSet(); - ranges.add(message.getMessageTransferId()); - - getSession().getQpidSession() - .messageAcquire(ranges, org.apache.qpidity.nclient.Session.MESSAGE_ACQUIRE_ANY_AVAILABLE_MESSAGE); - getSession().getQpidSession().sync(); - RangeSet acquired = getSession().getQpidSession().getAccquiredMessages(); - if (acquired.size() > 0) - { - result = true; - } - getSession().testQpidException(); - } - return result; - } - - /** - * Acknowledge a message - * - * @param message The message to be acknowledged - * @throws QpidException If the message cannot be acquired due to some internal error. - */ - private void acknowledgeMessage(QpidMessage message) throws QpidException - { - if (!_preAcquire) - { - RangeSet ranges = new RangeSet(); - ranges.add(message.getMessageTransferId()); - getSession().getQpidSession().messageAcknowledge(ranges); - getSession().testQpidException(); - } - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/MessageProducerImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/MessageProducerImpl.java deleted file mode 100644 index a61f4f1431..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/MessageProducerImpl.java +++ /dev/null @@ -1,384 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import org.apache.qpidity.njms.message.MessageHelper; -import org.apache.qpidity.njms.message.MessageImpl; -import org.apache.qpidity.QpidException; - -import javax.jms.*; -import java.util.UUID; -import java.io.IOException; - -/** - * Implements MessageProducer - */ -public class MessageProducerImpl extends MessageActor implements MessageProducer -{ - /** - * If true, messages will not get a timestamp. - */ - private boolean _disableTimestamps = false; - - /** - * Priority of messages created by this producer. - */ - private int _messagePriority = Message.DEFAULT_PRIORITY; - - /** - * Time to live of messages. Specified in milliseconds but AMQ has 1 second resolution. - */ - private long _timeToLive; - - /** - * Delivery mode used for this producer. - */ - private int _deliveryMode = DeliveryMode.PERSISTENT; - - /** - * Speicify whether the messageID is disable - */ - private boolean _disableMessageId = false; - - //-- constructors - public MessageProducerImpl(SessionImpl session, DestinationImpl destination) - { - super(session, destination,""); - } - - //--- Interface javax.njms.MessageProducer - /** - * Sets whether message IDs are disabled. - * - * @param value Specify whether the MessageID must be disabled - * @throws JMSException If disabling messageID fails due to some internal error. - */ - public void setDisableMessageID(boolean value) throws JMSException - { - checkNotClosed(); - _disableMessageId = value; - } - - /** - * Gets an indication of whether message IDs are disabled. - * - * @return true is messageID is disabled, false otherwise - * @throws JMSException If getting whether messagID is disabled fails due to some internal error. - */ - public boolean getDisableMessageID() throws JMSException - { - checkNotClosed(); - return _disableMessageId; - } - - /** - * Sets whether message timestamps are disabled. - * <P> JMS spec says: - * <p> Since timestamps take some effort to create and increase a - * message's size, some JMS providers may be able to optimize message - * overhead if they are given a hint that the timestamp is not used by an - * application.... - * these messages must have the timestamp set to zero; if the provider - * ignores the hint, the timestamp must be set to its normal value. - * <p>Message timestamps are enabled by default. - * - * @param value Indicates if message timestamps are disabled - * @throws JMSException if disabling the timestamps fails due to some internal error. - */ - public void setDisableMessageTimestamp(boolean value) throws JMSException - { - checkNotClosed(); - _disableTimestamps = value; - } - - /** - * Gets an indication of whether message timestamps are disabled. - * - * @return an indication of whether message timestamps are disabled - * @throws JMSException if getting whether timestamps are disabled fails due to some internal error. - */ - public boolean getDisableMessageTimestamp() throws JMSException - { - checkNotClosed(); - return _disableTimestamps; - } - - /** - * Sets the producer's default delivery mode. - * <p> JMS specification says: - * <p>Delivery mode is set to {@link DeliveryMode#PERSISTENT} by default. - * - * @param deliveryMode The message delivery mode for this message producer; legal - * values are {@link DeliveryMode#NON_PERSISTENT} - * and {@link DeliveryMode#PERSISTENT}. - * @throws JMSException if setting the delivery mode fails due to some internal error. - */ - public void setDeliveryMode(int deliveryMode) throws JMSException - { - checkNotClosed(); - if ((deliveryMode != DeliveryMode.NON_PERSISTENT) && (deliveryMode != DeliveryMode.PERSISTENT)) - { - throw new JMSException( - "DeliveryMode must be either NON_PERSISTENT or PERSISTENT. Value of " + deliveryMode + " is illegal"); - } - _deliveryMode = deliveryMode; - } - - /** - * Gets the producer's delivery mode. - * - * @return The message delivery mode for this message producer - * @throws JMSException If getting the delivery mode fails due to some internal error. - */ - public int getDeliveryMode() throws JMSException - { - checkNotClosed(); - return _deliveryMode; - } - - /** - * Sets the producer's message priority. - * <p> The njms spec says: - * <p> The JMS API defines ten levels of priority value, with 0 as the - * lowest priority and 9 as the highest. Clients should consider priorities - * 0-4 as gradations of normal priority and priorities 5-9 as gradations - * of expedited priority. - * <p> Priority is set to 4 by default. - * - * @param priority The message priority for this message producer; must be a value between 0 and 9 - * @throws JMSException if setting this producer priority fails due to some internal error. - */ - public void setPriority(int priority) throws JMSException - { - checkNotClosed(); - if ((priority < 0) || (priority > 9)) - { - throw new IllegalArgumentException( - "Priority of " + priority + " is illegal. Value must be in range 0 to 9"); - } - _messagePriority = priority; - } - - /** - * Gets the producer's message priority. - * - * @return The message priority for this message producer. - * @throws JMSException If getting this producer message priority fails due to some internal error. - */ - public int getPriority() throws JMSException - { - checkNotClosed(); - return _messagePriority; - } - - /** - * Sets the default length of time in milliseconds from its dispatch time - * that a produced message should be retained by the message system. - * <p> The JMS spec says that time to live must be set to zero by default. - * - * @param timeToLive The message time to live in milliseconds; zero is unlimited - * @throws JMSException If setting the default time to live fails due to some internal error. - */ - public void setTimeToLive(long timeToLive) throws JMSException - { - checkNotClosed(); - if (timeToLive < 0) - { - throw new IllegalArgumentException("Time to live must be non-negative - supplied value was " + timeToLive); - } - _timeToLive = timeToLive; - } - - /** - * Gets the default length of time in milliseconds from its dispatch time - * that a produced message should be retained by the message system. - * - * @return The default message time to live in milliseconds; zero is unlimited - * @throws JMSException if getting the default time to live fails due to some internal error. - * @see javax.jms.MessageProducer#setTimeToLive - */ - public long getTimeToLive() throws JMSException - { - checkNotClosed(); - return _timeToLive; - } - - /** - * Gets the destination associated with this producer. - * - * @return This producer's destination. - * @throws JMSException If getting the destination for this producer fails - * due to some internal error. - */ - public Destination getDestination() throws JMSException - { - checkNotClosed(); - return _destination; - } - - /** - * Sends a message using the producer's default delivery mode, priority, destination - * and time to live. - * - * @param message the message to be sent - * @throws JMSException If sending the message fails due to some internal error. - * @throws MessageFormatException If an invalid message is specified. - * @throws InvalidDestinationException If this producer destination is invalid. - * @throws java.lang.UnsupportedOperationException - * If a client uses this method with a producer that did - * not specify a destination at creation time. - */ - public void send(Message message) throws JMSException - { - send(message, _deliveryMode, _messagePriority, _timeToLive); - } - - /** - * Sends a message to this producer default destination, specifying delivery mode, - * priority, and time to live. - * - * @param message The message to send - * @param deliveryMode The delivery mode to use - * @param priority The priority for this message - * @param timeToLive The message's lifetime (in milliseconds) - * @throws JMSException If sending the message fails due to some internal error. - * @throws MessageFormatException If an invalid message is specified. - * @throws InvalidDestinationException If this producer's destination is invalid. - * @throws java.lang.UnsupportedOperationException - * If a client uses this method with a producer that did - * not specify a destination at creation time. - */ - public void send(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException - { - send(_destination, message, deliveryMode, priority, timeToLive); - } - - /** - * Sends a message to a specified destination using this producer's default - * delivery mode, priority and time to live. - * <p/> - * <P>Typically, a message producer is assigned a destination at creation - * time; however, the JMS API also supports unidentified message producers, - * which require that the destination be supplied every time a message is - * sent. - * - * @param destination The destination to send this message to - * @param message The message to send - * @throws JMSException If sending the message fails due to some internal error. - * @throws MessageFormatException If an invalid message is specified. - * @throws InvalidDestinationException If an invalid destination is specified. - */ - public void send(Destination destination, Message message) throws JMSException - { - send(destination, message, _deliveryMode, _messagePriority, _timeToLive); - } - - /** - * Sends a message to a destination specifying delivery mode, priority and time to live. - * - * @param destination The destination to send this message to. - * @param message The message to be sent. - * @param deliveryMode The delivery mode to use. - * @param priority The priority for this message. - * @param timeToLive The message's lifetime (in milliseconds) - * @throws JMSException If sending the message fails due to some internal error. - * @throws MessageFormatException If an invalid message is specified. - * @throws InvalidDestinationException If an invalid destination is specified. - */ - public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive) - throws JMSException - { - checkNotClosed(); - getSession().checkDestination(destination); - // Do not allow negative timeToLive values - if (timeToLive < 0) - { - throw new IllegalArgumentException("Time to live must be non-negative - supplied value was " + timeToLive); - } - // Only get current time if required - long currentTime = Long.MIN_VALUE; - if (!((timeToLive == 0) && _disableTimestamps)) - { - currentTime = System.currentTimeMillis(); - } - // the messae UID - String uid = (_disableMessageId) ? "MSG_ID_DISABLED" : UUID.randomUUID().toString(); - MessageImpl qpidMessage; - // check that the message is not a foreign one - try - { - qpidMessage = (MessageImpl) message; - } - catch (ClassCastException cce) - { - // this is a foreign message - qpidMessage = MessageHelper.transformMessage(message); - // set message's properties in case they are queried after send. - message.setJMSDestination(destination); - message.setJMSDeliveryMode(deliveryMode); - message.setJMSPriority(priority); - message.setJMSMessageID(uid); - if (timeToLive != 0) - { - message.setJMSExpiration(timeToLive + currentTime); - _logger.debug("Setting JMSExpiration:" + message.getJMSExpiration()); - } - else - { - message.setJMSExpiration(timeToLive); - } - message.setJMSTimestamp(currentTime); - } - // set the message properties - qpidMessage.setJMSDestination(destination); - qpidMessage.setJMSMessageID(uid); - qpidMessage.setJMSDeliveryMode(deliveryMode); - qpidMessage.setJMSPriority(priority); - if (timeToLive != 0) - { - qpidMessage.setJMSExpiration(timeToLive + currentTime); - } - else - { - qpidMessage.setJMSExpiration(timeToLive); - } - qpidMessage.setJMSTimestamp(currentTime); - qpidMessage.setRoutingKey(((DestinationImpl) destination).getDestinationName()); - qpidMessage.setExchangeName(((DestinationImpl) destination).getExchangeName()); - // call beforeMessageDispatch - try - { - qpidMessage.beforeMessageDispatch(); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - try - { - getSession().getQpidSession().messageTransfer(qpidMessage.getExchangeName(), - qpidMessage.getQpidityMessage(), - org.apache.qpidity.nclient.Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED, - org.apache.qpidity.nclient.Session.TRANSFER_ACQUIRE_MODE_PRE_ACQUIRE); - } - catch (IOException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/QpidBrowserListener.java b/java/client/src/main/java/org/apache/qpidity/njms/QpidBrowserListener.java deleted file mode 100644 index 59e772db85..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/QpidBrowserListener.java +++ /dev/null @@ -1,70 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.qpidity.api.Message; -import org.apache.qpidity.nclient.util.MessageListener; - -/** - * This listener idspatches messaes to its browser. - */ -public class QpidBrowserListener implements MessageListener -{ - /** - * Used for debugging. - */ - private static final Logger _logger = LoggerFactory.getLogger(SessionImpl.class); - - /** - * This message listener's browser. - */ - QueueBrowserImpl _browser = null; - - //---- constructor - /** - * Create a message listener wrapper for a given browser - * - * @param browser The browser of this listener - */ - public QpidBrowserListener(QueueBrowserImpl browser) - { - _browser = browser; - } - - //---- org.apache.qpidity.MessagePartListener API - /** - * Deliver a message to the listener. - * - * @param message The message delivered to the listner. - */ - public void onMessage(Message message) - { - try - { - //convert this message into a JMS one - javax.jms.Message jmsMessage = null; // todo - _browser.receiveMessage(jmsMessage); - } - catch (Exception e) - { - throw new RuntimeException(e.getMessage()); - } - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/QpidExceptionListenerImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/QpidExceptionListenerImpl.java deleted file mode 100644 index 0b6068f05d..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/QpidExceptionListenerImpl.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.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.JMSException; - -/** - * An exception listner - */ -public class QpidExceptionListenerImpl //implements ExceptionListener -{ - private javax.jms.ExceptionListener _jmsExceptionListener; - - public QpidExceptionListenerImpl() - { - } - - void setJMSExceptionListner(javax.jms.ExceptionListener jmsExceptionListener) - { - _jmsExceptionListener = jmsExceptionListener; - } - //----- ExceptionListener API - - public void onException(QpidException exception) - { - // convert this exception in a JMS exception - JMSException jmsException = ExceptionHelper.convertQpidExceptionToJMSException(exception); - // propagate to the njms exception listener - if (_jmsExceptionListener != null) - { - _jmsExceptionListener.onException(jmsException); - } - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/QueueBrowserImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/QueueBrowserImpl.java deleted file mode 100644 index 4478048528..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/QueueBrowserImpl.java +++ /dev/null @@ -1,256 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import java.util.Enumeration; -import java.util.NoSuchElementException; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.Queue; -import javax.jms.QueueBrowser; - -import org.apache.qpidity.nclient.MessagePartListener; -import org.apache.qpidity.nclient.util.MessagePartListenerAdapter; -import org.apache.qpidity.filter.JMSSelectorFilter; -import org.apache.qpidity.filter.MessageFilter; - -/** - * Implementation of the JMS QueueBrowser interface - */ -public class QueueBrowserImpl extends MessageActor implements QueueBrowser -{ - /** - * The browsers MessageSelector. - */ - private String _messageSelector = null; - - /** - * The message selector filter associated with this browser - */ - private MessageFilter _filter = null; - - /** - * The batch of messages to browse. - */ - private Message[] _messages; - - /** - * The number of messages read from current batch. - */ - private int _browsed = 0; - - /** - * The number of messages received from current batch. - */ - private int _received = 0; - - /** - * Indicates whether the last message has been received. - */ - private int _batchLength; - - /** - * The batch max size - */ - private final int _maxbatchlength = 10; - - //--- constructor - - /** - * Create a QueueBrowser for a specific queue and a given message selector. - * - * @param session The session of this browser. - * @param queue The queue name for this browser - * @param messageSelector only messages with properties matching the message selector expression are delivered. - * @throws Exception In case of internal problem when creating this browser. - */ - protected QueueBrowserImpl(SessionImpl session, Queue queue, String messageSelector,String consumerTag) throws Exception - { - super(session, (DestinationImpl) queue,consumerTag); - // this is an array representing a batch of messages for this browser. - _messages = new Message[_maxbatchlength]; - if (messageSelector != null) - { - _messageSelector = messageSelector; - _filter = new JMSSelectorFilter(messageSelector); - } - MessagePartListener messageAssembler = new MessagePartListenerAdapter(new QpidBrowserListener(this)); - // this is a queue we expect that this queue exists - getSession().getQpidSession() - .messageSubscribe(queue.getQueueName(), getMessageActorID(), - org.apache.qpidity.nclient.Session.TRANSFER_CONFIRM_MODE_NOT_REQUIRED, - // We do not acquire those messages - org.apache.qpidity.nclient.Session.TRANSFER_ACQUIRE_MODE_NO_ACQUIRE, messageAssembler, null); - - } - - //--- javax.njms.QueueBrowser API - /** - * Get an enumeration for browsing the current queue messages in the order they would be received. - * - * @return An enumeration for browsing the messages - * @throws JMSException If getting the enumeration for this browser fails due to some internal error. - */ - public Enumeration getEnumeration() throws JMSException - { - requestMessages(); - return new MessageEnumeration(); - } - - - /** - * Get the queue associated with this queue browser. - * - * @return The queue associated with this queue browser. - * @throws JMSException If getting the queue associated with this browser failts due to some internal error. - */ - public Queue getQueue() throws JMSException - { - checkNotClosed(); - return (Queue) _destination; - } - - /** - * Get this queue browser's message selector expression. - * - * @return This queue browser's message selector, or null if no message selector exists. - * @throws JMSException if getting the message selector for this browser fails due to some internal error. - */ - public String getMessageSelector() throws JMSException - { - checkNotClosed(); - return _messageSelector; - } - - //-- overwritten methods. - /** - * Closes the browser and deregister it from its session. - * - * @throws JMSException if the MessaeActor cannot be closed due to some internal error. - */ - public void close() throws JMSException - { - synchronized (_messages) - { - _received = 0; - _browsed = 0; - _batchLength = 0; - _messages.notify(); - } - super.close(); - } - - //-- nonpublic methods - /** - * Request _maxbatchlength messages - * - * @throws JMSException If requesting more messages fails due to some internal error. - */ - private void requestMessages() throws JMSException - { - _browsed = 0; - _received = 0; - // request messages - int received = 0; - getSession().getQpidSession() - .messageFlow(getMessageActorID(), org.apache.qpidity.nclient.Session.MESSAGE_FLOW_UNIT_MESSAGE, - _maxbatchlength); - _batchLength = 0; //getSession().getQpidSession().messageFlush(getMessageActorID()); - } - - /** - * This method is invoked by the listener when a message is dispatched to this browser. - * - * @param m A received message - */ - protected void receiveMessage(Message m) - { - synchronized (_messages) - { - _messages[_received] = m; - _received++; - _messages.notify(); - } - } - - //-- inner class - /** - * This is an implementation of the Enumeration interface. - */ - private class MessageEnumeration implements Enumeration - { - /* - * Whether this enumeration has any more elements. - * - * @return True if there any more elements. - */ - public boolean hasMoreElements() - { - boolean result = false; - // Try to work out whether there are any more messages available. - try - { - if (_browsed >= _maxbatchlength) - { - requestMessages(); - } - synchronized (_messages) - { - while (_received == _browsed && _batchLength > _browsed) - { - // we expect more messages - _messages.wait(); - } - if (_browsed < _received && _batchLength != _browsed) - { - result = true; - } - } - } - catch (Exception e) - { - // If no batch could be returned, the result should be false, therefore do nothing - } - return result; - } - - /** - * Get the next message element - * - * @return The next element. - */ - public Object nextElement() - { - if (hasMoreElements()) - { - synchronized (_messages) - { - Message message = _messages[_browsed]; - _browsed = _browsed + 1; - return message; - } - } - else - { - throw new NoSuchElementException(); - } - } - } - -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/QueueConnectionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/QueueConnectionImpl.java deleted file mode 100644 index cab683b0a4..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/QueueConnectionImpl.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.njms; - -import org.apache.qpidity.njms.ConnectionImpl; -import org.apache.qpidity.QpidException; - -import javax.jms.QueueConnection; - -/** - * - * Implements javax.njms.QueueConnection - */ -public class QueueConnectionImpl extends ConnectionImpl implements QueueConnection -{ - //-- constructor - public QueueConnectionImpl(String host,int port,String virtualHost,String username,String password) throws QpidException - { - super(host, port, virtualHost, username, password); - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/QueueImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/QueueImpl.java deleted file mode 100644 index 678a350c35..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/QueueImpl.java +++ /dev/null @@ -1,136 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import org.apache.qpid.url.QpidBindingURL; -import org.apache.qpidity.QpidException; -import org.apache.qpidity.transport.Option; -import org.apache.qpidity.exchange.ExchangeDefaults; - -import javax.jms.Queue; -import javax.jms.JMSException; - -/** - * Implementation of the JMS Queue interface - */ -public class QueueImpl extends DestinationImpl implements Queue -{ - //--- Constructor - /** - * Create a new QueueImpl with a given name. - * - * @param name The name of this queue. - * @param session The session used to create this queue. - * @throws QpidException If the queue name is not valid - */ - protected QueueImpl(SessionImpl session, String name) throws QpidException - { - super(name); - _queueName = name; - _destinationName = name; - _exchangeName = ExchangeDefaults.DIRECT_EXCHANGE_NAME; - _exchangeType = ExchangeDefaults.DIRECT_EXCHANGE_CLASS; - _isAutoDelete = false; - _isDurable = true; - _isExclusive = false; - registerQueue(session, false); - } - - /** - * Create a destiantion from a binding URL - * - * @param session The session used to create this queue. - * @param binding The URL - * @throws QpidException If the URL is not valid - */ - protected QueueImpl(SessionImpl session, QpidBindingURL binding) throws QpidException - { - super(binding); - registerQueue(session, false); - } - - /** - * Create a destiantion from a binding URL - * - * @param binding The URL - * @throws QpidException If the URL is not valid - */ - public QueueImpl(QpidBindingURL binding) throws QpidException - { - super(binding); - } - - /** - * Create a new QueueImpl with a given name. - * - * @param name The name of this queue. - * @throws QpidException If the queue name is not valid - */ - public QueueImpl(String name) throws QpidException - { - super(name); - _queueName = name; - _destinationName = name; - _exchangeName = ExchangeDefaults.DIRECT_EXCHANGE_NAME; - _exchangeType = ExchangeDefaults.DIRECT_EXCHANGE_CLASS; - _isAutoDelete = false; - _isDurable = true; - _isExclusive = false; - } - - //---- Interface javax.njms.Queue - /** - * Gets the name of this queue. - * - * @return This queue's name. - */ - public String getQueueName() throws JMSException - { - return _queueName; - } - - //---Private methods - /** - * Check that this queue exists and declare it if required. - * - * @param session The session used to create this destination - * @param declare Specify whether the queue should be declared - * @throws QpidException If this queue does not exists on the broker. - */ - protected void registerQueue(SessionImpl session, boolean declare) throws QpidException - { - // test if this exchange exist on the broker - //todo we can also specify if the excahnge is autodlete and durable - session.getQpidSession().exchangeDeclare(_exchangeName, _exchangeType, null, null, Option.PASSIVE); - // wait for the broker response - session.getQpidSession().sync(); - // If this exchange does not exist then we will get an Expection 404 does notexist - //todo check for an execption - // now check if the queue exists - session.getQpidSession().queueDeclare(_queueName, null, null, _isDurable ? Option.DURABLE : Option.NO_OPTION, - _isAutoDelete ? Option.AUTO_DELETE : Option.NO_OPTION, - _isExclusive ? Option.EXCLUSIVE : Option.NO_OPTION, - declare ? Option.PASSIVE : Option.NO_OPTION); - // wait for the broker response - session.getQpidSession().sync(); - // If this queue does not exist then we will get an Expection 404 does notexist - session.getQpidSession().queueBind(_queueName, _exchangeName, _destinationName, null); - // we don't have to sync as we don't expect an error - } - -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/QueueReceiverImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/QueueReceiverImpl.java deleted file mode 100644 index 67db7e5001..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/QueueReceiverImpl.java +++ /dev/null @@ -1,55 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import javax.jms.QueueReceiver; -import javax.jms.JMSException; -import javax.jms.Queue; - -/** - * Implements javax.njms.QueueReceiver - */ -public class QueueReceiverImpl extends MessageConsumerImpl implements QueueReceiver -{ - //--- Constructor - /** - * create a new QueueReceiverImpl. - * - * @param session The session from which the QueueReceiverImpl is instantiated. - * @param queue The default queue for this QueueReceiverImpl. - * @param messageSelector the message selector for this QueueReceiverImpl. - * @throws Exception If the QueueReceiverImpl cannot be created due to some internal error. - */ - protected QueueReceiverImpl(SessionImpl session, Queue queue, String messageSelector,String consumerTag) throws Exception - { - super(session, (DestinationImpl) queue, messageSelector, false, null,consumerTag); - } - - //--- Interface QueueReceiver - /** - * Get the Queue associated with this queue receiver. - * - * @return this receiver's Queue - * @throws JMSException If getting the queue for this queue receiver fails due to some internal error. - */ - public Queue getQueue() throws JMSException - { - checkNotClosed(); - return (QueueImpl) _destination; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/QueueSenderImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/QueueSenderImpl.java deleted file mode 100644 index d03bb3a6b7..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/QueueSenderImpl.java +++ /dev/null @@ -1,131 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms; - -import javax.jms.QueueSender; -import javax.jms.JMSException; -import javax.jms.Queue; -import javax.jms.Message; - -/** - * Implements javax.njms.QueueSender - */ -public class QueueSenderImpl extends MessageProducerImpl implements QueueSender -{ - //--- Constructor - /** - * Create a new QueueSenderImpl. - * - * @param session the session from which the QueueSenderImpl is instantiated - * @param queue the default queue for this QueueSenderImpl - * @throws JMSException If the QueueSenderImpl cannot be created due to some internal error. - */ - protected QueueSenderImpl(SessionImpl session, QueueImpl queue) throws JMSException - { - super(session, queue); - } - - //--- Interface javax.njms.QueueSender - /** - * Get the queue associated with this QueueSender. - * - * @return This QueueSender's queue - * @throws JMSException If getting the queue for this QueueSender fails due to some internal error. - */ - public Queue getQueue() throws JMSException - { - return (Queue) getDestination(); - } - - /** - * Sends a message to the queue. Uses the <CODE>QueueSender</CODE>'s default delivery mode, priority, - * and time to live. - * - * @param message The message to send. - * @throws JMSException if sending the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If an invalid message is specified. - * @throws javax.jms.InvalidDestinationException - * If the queue is invalid. - * @throws java.lang.UnsupportedOperationException - * If invoked on QueueSender that did not specify a queue at creation time. - */ - public void send(Message message) throws JMSException - { - super.send(message); - } - - /** - * Send a message to the queue, specifying delivery mode, priority, and time to live. - * - * @param message The message to send - * @param deliveryMode The delivery mode to use - * @param priority The priority for this message - * @param timeToLive The message's lifetime (in milliseconds) - * - * @throws JMSException if sending the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If an invalid message is specified. - * @throws javax.jms.InvalidDestinationException - * If the queue is invalid. - * @throws java.lang.UnsupportedOperationException - * If invoked on QueueSender that did not specify a queue at creation time. - */ - public void send(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException - { - super.send(message, deliveryMode, priority, timeToLive); - } - - /** - * Send a message to a queue for an unidentified message producer. - * Uses the <CODE>QueueSender</CODE>'s default delivery mode, priority, - * and time to live. - * - * @param queue The queue to send this message to - * @param message The message to send - * @throws JMSException if sending the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If an invalid message is specified. - * @throws javax.jms.InvalidDestinationException - * If the queue is invalid. - */ - public void send(Queue queue, Message message) throws JMSException - { - super.send(queue, message); - } - - /** - * Sends a message to a queue for an unidentified message producer, - * specifying delivery mode, priority and time to live. - * - * @param queue The queue to send this message to - * @param message The message to send - * @param deliveryMode The delivery mode to use - * @param priority The priority for this message - * @param timeToLive The message's lifetime (in milliseconds) - * @throws JMSException if sending the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If an invalid message is specified. - * @throws javax.jms.InvalidDestinationException - * If the queue is invalid. - */ - public void send(Queue queue, Message message, int deliveryMode, int priority, long timeToLive) throws JMSException - { - super.send(queue, message, deliveryMode, priority, timeToLive); - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/QueueSessionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/QueueSessionImpl.java deleted file mode 100644 index 9ae0725f00..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/QueueSessionImpl.java +++ /dev/null @@ -1,154 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import javax.jms.*; -import javax.jms.IllegalStateException; - -import org.apache.qpidity.QpidException; - -/** - * Implementation of javax.njms.QueueSession - */ -public class QueueSessionImpl extends SessionImpl implements QueueSession -{ - //--- constructor - /** - * Create a JMS Session - * - * @param connection The ConnectionImpl object from which the Session is created. - * @param transacted Indicates if the session transacted. - * @param acknowledgeMode The session's acknowledgement mode. This value is ignored and set to - * {@link javax.jms.Session#SESSION_TRANSACTED} if the <code>transacted</code> - * parameter is true. - * @throws javax.jms.JMSSecurityException If the user could not be authenticated. - * @throws javax.jms.JMSException In case of internal error. - */ - protected QueueSessionImpl(ConnectionImpl connection, boolean transacted, int acknowledgeMode) throws QpidException, JMSException - { - super(connection, transacted, acknowledgeMode,false); - } - - //-- Overwritten methods - /** - * Creates a durable subscriber to the specified topic, - * - * @param topic The non-temporary <CODE>Topic</CODE> to subscribe to. - * @param name The name used to identify this subscription. - * @return Always throws an exception - * @throws IllegalStateException Always - */ - @Override - public TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException - { - throw new IllegalStateException("Cannot invoke createDurableSubscriber from QueueSession"); - } - - /** - * Create a TemporaryTopic. - * - * @return Always throws an exception - * @throws IllegalStateException Always - */ - @Override - public TemporaryTopic createTemporaryTopic() throws JMSException - { - throw new IllegalStateException("Cannot invoke createTemporaryTopic from QueueSession"); - } - - /** - * Creates a topic identity given a Topicname. - * - * @param topicName The name of this <CODE>Topic</CODE> - * @return Always throws an exception - * @throws IllegalStateException Always - */ - @Override - public Topic createTopic(String topicName) throws JMSException - { - throw new IllegalStateException("Cannot invoke createTopic from QueueSession"); - } - - /** - * Unsubscribes a durable subscription that has been created by a client. - * - * @param name the name used to identify this subscription - * @throws IllegalStateException Always - */ - @Override - public void unsubscribe(String name) throws JMSException - { - throw new IllegalStateException("Cannot invoke unsubscribe from QueueSession"); - } - - //--- Interface javax.njms.QueueSession - /** - * Create a QueueReceiver to receive messages from the specified queue. - * - * @param queue the <CODE>Queue</CODE> to access - * @return A QueueReceiver - * @throws JMSException If creating a receiver fails due to some internal error. - * @throws InvalidDestinationException If an invalid queue is specified. - */ - public QueueReceiver createReceiver(Queue queue) throws JMSException - { - return createReceiver(queue, null); - } - - /** - * Create a QueueReceiver to receive messages from the specified queue for a given message selector. - * - * @param queue the Queue to access - * @param messageSelector A value of null or an empty string indicates that - * there is no message selector for the message consumer. - * @return A QueueReceiver - * @throws JMSException If creating a receiver fails due to some internal error. - * @throws InvalidDestinationException If an invalid queue is specified. - * @throws InvalidSelectorException If the message selector is invalid. - */ - public QueueReceiver createReceiver(Queue queue, String messageSelector) throws JMSException - { - checkNotClosed(); - checkDestination(queue); - QueueReceiver receiver; - try - { - receiver = new QueueReceiverImpl(this, queue, messageSelector,String.valueOf(_consumerTag.incrementAndGet())); - } - catch (Exception e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - return receiver; - } - - /** - * Create a QueueSender object to send messages to the specified queue. - * - * @param queue the Queue to access, or null if this is an unidentified producer - * @return A QueueSender - * @throws JMSException If creating the sender fails due to some internal error. - * @throws InvalidDestinationException If an invalid queue is specified. - */ - public QueueSender createSender(Queue queue) throws JMSException - { - checkNotClosed(); - // we do not check the destination since unidentified producers are allowed (no default destination). - return new QueueSenderImpl(this, (QueueImpl) queue); - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/SessionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/SessionImpl.java deleted file mode 100644 index 5694075ef4..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/SessionImpl.java +++ /dev/null @@ -1,1325 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.qpidity.njms.message.*; -import org.apache.qpidity.ErrorCode; -import org.apache.qpidity.QpidException; -import org.apache.qpidity.transport.RangeSet; - -import javax.jms.*; -import javax.jms.IllegalStateException; -import java.io.Serializable; -import java.util.LinkedList; -import java.util.HashMap; -import java.util.ArrayList; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Implementation of the JMS Session interface - */ -public class SessionImpl implements Session -{ - /** - * this session's logger - */ - private static final Logger _logger = LoggerFactory.getLogger(SessionImpl.class); - - /** - * A queue for incoming asynch messages. - */ - private final LinkedList<IncomingMessage> _incomingAsynchronousMessages = new LinkedList<IncomingMessage>(); - - //--- MessageDispatcherThread and Session locking - /** - * indicates that the MessageDispatcherThread has stopped - */ - private boolean _hasStopped = false; - - /** - * lock for the MessageDispatcherThread to wait until the session is stopped - */ - private final Object _stoppingLock = new Object(); - - /** - * lock for the stopper thread to wait on when the MessageDispatcherThread is stopping - */ - private final Object _stoppingJoin = new Object(); - - /** - * thread to dispatch messages to async consumers - */ - private MessageDispatcherThread _messageDispatcherThread = null; - //----END - - /** - * The messageActors of this session. - */ - private final HashMap<String, MessageActor> _messageActors = new HashMap<String, MessageActor>(); - - /** - * All the not yet acknoledged messages - */ - private final ArrayList<QpidMessage> _unacknowledgedMessages = new ArrayList<QpidMessage>(); - - /** - * Indicates whether this session is closed. - */ - private boolean _isClosed = false; - - /** - * Indicates whether this session is closing. - */ - private boolean _isClosing = false; - - /** - * Indicates whether this session is stopped. - */ - private boolean _isStopped = false; - - /** - * Used to indicate whether or not this is a transactional session. - */ - private boolean _transacted; - - /** - * Holds the sessions acknowledgement mode. - */ - private int _acknowledgeMode; - - /** - * The underlying QpidSession - */ - private org.apache.qpidity.nclient.Session _qpidSession; - - /** - * The latest qpid Exception that has been reaised. - */ - private QpidException _currentException; - - /** - * Indicates whether this session is recovering - */ - private boolean _inRecovery = false; - - /** - * This session connection - */ - private ConnectionImpl _connection; - - /** - * This will be used as the message actor id - * This in turn will be set as the destination - */ - protected AtomicInteger _consumerTag = new AtomicInteger(); - - //--- Constructor - /** - * Create a JMS Session - * - * @param connection The ConnectionImpl object from which the Session is created. - * @param transacted Indicates if the session transacted. - * @param acknowledgeMode The session's acknowledgement mode. This value is ignored and set to - * {@link Session#SESSION_TRANSACTED} if the <code>transacted</code> parameter is true. - * @param isXA Indicates whether this session is an XA session. - * @throws QpidException In case of internal error. - */ - protected SessionImpl(ConnectionImpl connection, boolean transacted, int acknowledgeMode, boolean isXA) - throws QpidException - { - _connection = connection; - _transacted = transacted; - // for transacted sessions we ignore the acknowledgeMode and use GenericAckMode.SESSION_TRANSACTED - if (_transacted) - { - acknowledgeMode = Session.SESSION_TRANSACTED; - } - _acknowledgeMode = acknowledgeMode; - - // create the qpid session with an expiry <= 0 so that the session does not expire - _qpidSession = _connection.getQpidConnection().createSession(0); - // set the exception listnere for this session - _qpidSession.setClosedListener(new QpidSessionExceptionListener()); - // set transacted if required - if (_transacted && !isXA) - { - _qpidSession.txSelect(); - } - testQpidException(); - // init the message dispatcher. - initMessageDispatcherThread(); - } - - //--- javax.njms.Session API - /** - * Creates a <CODE>BytesMessage</CODE> object used to send a message - * containing a stream of uninterpreted bytes. - * - * @return A BytesMessage. - * @throws JMSException If Creating a BytesMessage object fails due to some internal error. - */ - public BytesMessage createBytesMessage() throws JMSException - { - checkNotClosed(); - return new BytesMessageImpl(); - } - - /** - * Creates a <CODE>MapMessage</CODE> object used to send a self-defining set - * of name-value pairs, where names are Strings and values are primitive values. - * - * @return A MapMessage. - * @throws JMSException If Creating a MapMessage object fails due to some internal error. - */ - public MapMessage createMapMessage() throws JMSException - { - checkNotClosed(); - return new MapMessageImpl(); - } - - /** - * Creates a <code>Message</code> object that holds all the standard message header information. - * It can be sent when a message containing only header information is sufficient. - * We simply return a ByteMessage - * - * @return A Message. - * @throws JMSException If Creating a Message object fails due to some internal error. - */ - public Message createMessage() throws JMSException - { - return new MessageImpl(); - } - - /** - * Creates an <code>ObjectMessage</code> used to send a message - * that contains a serializable Java object. - * - * @return An ObjectMessage. - * @throws JMSException If Creating an ObjectMessage object fails due to some internal error. - */ - public ObjectMessage createObjectMessage() throws JMSException - { - checkNotClosed(); - return new ObjectMessageImpl(); - } - - /** - * Creates an initialized <code>ObjectMessage</code> used to send a message that contains - * a serializable Java object. - * - * @param serializable The object to use to initialize this message. - * @return An initialised ObjectMessage. - * @throws JMSException If Creating an initialised ObjectMessage object fails due to some internal error. - */ - public ObjectMessage createObjectMessage(Serializable serializable) throws JMSException - { - ObjectMessage msg = createObjectMessage(); - msg.setObject(serializable); - return msg; - } - - /** - * Creates a <code>StreamMessage</code> used to send a - * self-defining stream of primitive values in the Java programming - * language. - * - * @return A StreamMessage - * @throws JMSException If Creating an StreamMessage object fails due to some internal error. - */ - public StreamMessage createStreamMessage() throws JMSException - { - checkNotClosed(); - return new StreamMessageImpl(); - } - - /** - * Creates a <code>TextMessage</code> object used to send a message containing a String. - * - * @return A TextMessage object - * @throws JMSException If Creating an TextMessage object fails due to some internal error. - */ - public TextMessage createTextMessage() throws JMSException - { - checkNotClosed(); - return new TextMessageImpl(); - } - - /** - * Creates an initialized <code>TextMessage</code> used to send - * a message containing a String. - * - * @param text The string used to initialize this message. - * @return An initialized TextMessage - * @throws JMSException If Creating an initialised TextMessage object fails due to some internal error. - */ - public TextMessage createTextMessage(String text) throws JMSException - { - TextMessage msg = createTextMessage(); - msg.setText(text); - return msg; - } - - /** - * Indicates whether the session is in transacted mode. - * - * @return true if the session is in transacted mode - * @throws JMSException If geting the transaction mode fails due to some internal error. - */ - public boolean getTransacted() throws JMSException - { - checkNotClosed(); - return _transacted; - } - - /** - * Returns the acknowledgement mode of this session. - * <p> The acknowledgement mode is set at the time that the session is created. - * If the session is transacted, the acknowledgement mode is ignored. - * - * @return If the session is not transacted, returns the current acknowledgement mode for the session. - * else returns SESSION_TRANSACTED. - * @throws JMSException if geting the acknowledgement mode fails due to some internal error. - */ - public int getAcknowledgeMode() throws JMSException - { - checkNotClosed(); - return _acknowledgeMode; - } - - /** - * Commits all messages done in this transaction. - * - * @throws JMSException If committing the transaction fails due to some internal error. - * @throws TransactionRolledBackException If the transaction is rolled back due to some internal error during commit. - * @throws javax.jms.IllegalStateException - * If the method is not called by a transacted session. - */ - public void commit() throws JMSException - { - checkNotClosed(); - //make sure the Session is a transacted one - if (!_transacted) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot commit non-transacted session, throwing IllegalStateException"); - } - throw new IllegalStateException("Cannot commit non-transacted session", "Session is not transacted"); - } - // commit the underlying Qpid Session - _qpidSession.txCommit(); - try - { - testQpidException(); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Rolls back any messages done in this transaction. - * - * @throws JMSException If rolling back the session fails due to some internal error. - * @throws javax.jms.IllegalStateException - * If the method is not called by a transacted session. - */ - public void rollback() throws JMSException - { - checkNotClosed(); - //make sure the Session is a transacted one - if (!_transacted) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot rollback non-transacted session, throwing IllegalStateException"); - } - throw new IllegalStateException("Cannot rollback non-transacted session", "Session is not transacted"); - } - // rollback the underlying Qpid Session - _qpidSession.txRollback(); - try - { - testQpidException(); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Closes this session. - * <p> The JMS specification says - * <P> This call will block until a <code>receive</code> call or message - * listener in progress has completed. A blocked message consumer - * <code>receive</code> call returns <code>null</code> when this session is closed. - * <P>Closing a transacted session must roll back the transaction in progress. - * <P>This method is the only <code>Session</code> method that can be called concurrently. - * <P>Invoking any other <code>Session</code> method on a closed session - * must throw a <code>javax.njms.IllegalStateException</code>. - * <p> Closing a closed session must <I>not</I> throw an exception. - * - * @throws JMSException If closing the session fails due to some internal error. - */ - public synchronized void close() throws JMSException - { - if (!_isClosed) - { - _messageDispatcherThread.interrupt(); - if (!_isClosing) - { - _isClosing = true; - // if the session is stopped then restart it before notifying on the lock - // that will stop the sessionThread - if (_isStopped) - { - startDispatchThread(); - } - //notify the sessionThread - synchronized (_incomingAsynchronousMessages) - { - _incomingAsynchronousMessages.notifyAll(); - } - - try - { - _messageDispatcherThread.join(); - _messageDispatcherThread = null; - } - catch (InterruptedException ie) - { - /* ignore */ - } - } - // from now all the session methods will throw a IllegalStateException - _isClosed = true; - // close all the actors - closeAllMessageActors(); - _messageActors.clear(); - // We may have a thread trying to add a message - synchronized (_incomingAsynchronousMessages) - { - _incomingAsynchronousMessages.clear(); - _incomingAsynchronousMessages.notifyAll(); - } - // close the underlaying QpidSession - _qpidSession.sessionClose(); - try - { - testQpidException(); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - } - - /** - * Stops message delivery in this session, and restarts message delivery with - * the oldest unacknowledged message. - * <p>Recovering a session causes it to take the following actions: - * <ul> - * <li>Stop message delivery. - * <li>Mark all messages that might have been delivered but not acknowledged as "redelivered". - * <li>Restart the delivery sequence including all unacknowledged messages that had been - * previously delivered. - * Redelivered messages do not have to be delivered in exactly their original delivery order. - * </ul> - * - * @throws JMSException If the JMS provider fails to stop and restart message delivery due to some internal error. - * Not that this does not necessarily mean that the recovery has failed, but simply that it is - * not possible to tell if it has or not. - */ - public void recover() throws JMSException - { - // Ensure that the session is open. - checkNotClosed(); - // we are recovering - _inRecovery = true; - // Ensure that the session is not transacted. - if (getTransacted()) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Trying to recover a transacted Session, throwing IllegalStateException"); - } - throw new IllegalStateException("Session is transacted"); - } - // release all unack messages - RangeSet ranges = new RangeSet(); - for (QpidMessage message : _unacknowledgedMessages) - { - // release this message - ranges.add(message.getMessageTransferId()); - } - getQpidSession().messageRelease(ranges); - } - - /** - * Returns the session's distinguished message listener (optional). - * <p>This is an expert facility used only by Application Servers. - * <p> This is an optional operation that is not yet supported - * - * @return The message listener associated with this session. - * @throws JMSException If getting the message listener fails due to an internal error. - */ - public MessageListener getMessageListener() throws JMSException - { - checkNotClosed(); - if (_logger.isDebugEnabled()) - { - _logger.debug( - "Getting session's distinguished message listener, not supported," + " throwing UnsupportedOperationException"); - } - throw new UnsupportedOperationException(); - } - - /** - * Sets the session's distinguished message listener. - * <p>This is an expert facility used only by Application Servers. - * <p> This is an optional operation that is not yet supported - * - * @param messageListener The message listener to associate with this session - * @throws JMSException If setting the message listener fails due to an internal error. - */ - public void setMessageListener(MessageListener messageListener) throws JMSException - { - checkNotClosed(); - if (_logger.isDebugEnabled()) - { - _logger.debug( - "Setting the session's distinguished message listener, not supported," + " throwing UnsupportedOperationException"); - } - throw new UnsupportedOperationException(); - } - - /** - * Optional operation, intended to be used only by Application Servers, - * not by ordinary JMS clients. - * <p> This is an optional operation that is not yet supported - */ - public void run() - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Running this session, not supported," + " throwing UnsupportedOperationException"); - } - throw new UnsupportedOperationException(); - } - - /** - * Creates a MessageProducer to send messages to the specified destination. - * - * @param destination the Destination to send messages to, or null if this is a producer - * which does not have a specified destination. - * @return A new MessageProducer - * @throws JMSException If the session fails to create a MessageProducer - * due to some internal error. - * @throws InvalidDestinationException If an invalid destination is specified. - */ - public MessageProducer createProducer(Destination destination) throws JMSException - { - checkNotClosed(); - MessageProducerImpl producer = new MessageProducerImpl(this, (DestinationImpl) destination); - // register this actor with the session - _messageActors.put(producer.getMessageActorID(), producer); - return producer; - } - - /** - * Creates a MessageConsumer for the specified destination. - * - * @param destination The <code>Destination</code> to access - * @return A new MessageConsumer for the specified destination. - * @throws JMSException If the session fails to create a MessageConsumer due to some internal error. - * @throws InvalidDestinationException If an invalid destination is specified. - */ - public MessageConsumer createConsumer(Destination destination) throws JMSException - { - return createConsumer(destination, null); - } - - /** - * Creates a MessageConsumer for the specified destination, using a message selector. - * - * @param destination The <code>Destination</code> to access - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @return A new MessageConsumer for the specified destination. - * @throws JMSException If the session fails to create a MessageConsumer due to some internal error. - * @throws InvalidDestinationException If an invalid destination is specified. - * @throws InvalidSelectorException If the message selector is invalid. - */ - public MessageConsumer createConsumer(Destination destination, String messageSelector) throws JMSException - { - return createConsumer(destination, messageSelector, false); - } - - /** - * Creates MessageConsumer for the specified destination, using a message selector. - * <p> This method can specify whether messages published by its own connection should - * be delivered to it, if the destination is a topic. - * <p/> - * <P>In some cases, a connection may both publish and subscribe to a topic. The consumer - * NoLocal attribute allows a consumer to inhibit the delivery of messages published by its - * own connection. The default value for this attribute is False. - * - * @param destination The <code>Destination</code> to access - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @param noLocal If true, and the destination is a topic, inhibits the delivery of messages published - * by its own connection. - * @return A new MessageConsumer for the specified destination. - * @throws JMSException If the session fails to create a MessageConsumer due to some internal error. - * @throws InvalidDestinationException If an invalid destination is specified. - * @throws InvalidSelectorException If the message selector is invalid. - */ - public MessageConsumer createConsumer(Destination destination, String messageSelector, boolean noLocal) - throws JMSException - { - checkNotClosed(); - checkDestination(destination); - MessageConsumerImpl consumer; - try - { - consumer = new MessageConsumerImpl(this, (DestinationImpl) destination, messageSelector, noLocal, null, - String.valueOf(_consumerTag.incrementAndGet())); - } - catch (Exception e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Problem when creating consumer.", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - // register this actor with the session - _messageActors.put(consumer.getMessageActorID(), consumer); - return consumer; - } - - /** - * Creates a queue identity by a given name. - * <P>This facility is provided for the rare cases where clients need to - * dynamically manipulate queue identity. It allows the creation of a - * queue identity with a provider-specific name. Clients that depend - * on this ability are not portable. - * <P>Note that this method is not for creating the physical queue. - * The physical creation of queues is an administrative task and is not - * to be initiated by the JMS API. The one exception is the - * creation of temporary queues, which is accomplished with the - * <code>createTemporaryQueue</code> method. - * - * @param queueName the name of this <code>Queue</code> - * @return a <code>Queue</code> with the given name - * @throws JMSException If the session fails to create a queue due to some internal error. - */ - public Queue createQueue(String queueName) throws JMSException - { - checkNotClosed(); - Queue result; - try - { - result = new QueueImpl(this, queueName); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Problem when creating Queue.", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - return result; - } - - /** - * Creates a topic identity given a Topicname. - * <P>This facility is provided for the rare cases where clients need to - * dynamically manipulate queue identity. It allows the creation of a - * queue identity with a provider-specific name. Clients that depend - * on this ability are not portable. - * <P>Note that this method is not for creating the physical queue. - * The physical creation of queues is an administrative task and is not - * to be initiated by the JMS API. The one exception is the - * creation of temporary queues, which is accomplished with the - * <code>createTemporaryTopic</code> method. - * - * @param topicName The name of this <code>Topic</code> - * @return a <code>Topic</code> with the given name - * @throws JMSException If the session fails to create a topic due to some internal error. - */ - public Topic createTopic(String topicName) throws JMSException - { - checkNotClosed(); - Topic result; - try - { - result = new TopicImpl(this, topicName); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Problem when creating Topic.", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - return result; - } - - /** - * Creates a durable subscriber to the specified topic, - * - * @param topic The non-temporary <code>Topic</code> to subscribe to. - * @param name The name used to identify this subscription. - * @return A durable subscriber to the specified topic, - * @throws JMSException If creating a subscriber fails due to some internal error. - * @throws InvalidDestinationException If an invalid topic is specified. - * @throws InvalidSelectorException If the message selector is invalid. - */ - public TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException - { - // by default, use a null messageselector and set noLocal to falsen - return createDurableSubscriber(topic, name, null, false); - } - - /** - * Creates a durable subscriber to the specified topic, using a message selector and specifying whether messages - * published by its - * own connection should be delivered to it. - * <p> A client can change an existing durable subscription by creating a durable <code>TopicSubscriber</code> with - * the same name and a new topic and/or message selector. Changing a durable subscriber is equivalent to - * unsubscribing (deleting) the old one and creating a new one. - * - * @param topic The non-temporary <code>Topic</code> to subscribe to. - * @param name The name used to identify this subscription. - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @param noLocal If set, inhibits the delivery of messages published by its own connection - * @return A durable subscriber to the specified topic, - * @throws JMSException If creating a subscriber fails due to some internal error. - * @throws InvalidDestinationException If an invalid topic is specified. - * @throws InvalidSelectorException If the message selector is invalid. - */ - public TopicSubscriber createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal) - throws JMSException - { - checkNotClosed(); - checkDestination(topic); - TopicSubscriberImpl subscriber; - try - { - subscriber = new TopicSubscriberImpl(this, topic, messageSelector, noLocal, - _connection.getClientID() + ":" + name, - String.valueOf(_consumerTag.incrementAndGet())); - } - catch (Exception e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Problem when creating Durable Subscriber.", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - _messageActors.put(subscriber.getMessageActorID(), subscriber); - return subscriber; - } - - /** - * Create a QueueBrowser to peek at the messages on the specified queue. - * - * @param queue The <code>Queue</code> to browse. - * @return A QueueBrowser. - * @throws JMSException If creating a browser fails due to some internal error. - * @throws InvalidDestinationException If an invalid queue is specified. - */ - public QueueBrowser createBrowser(Queue queue) throws JMSException - { - return createBrowser(queue, null); - } - - /** - * Create a QueueBrowser to peek at the messages on the specified queue using a message selector. - * - * @param queue The <code>Queue</code> to browse. - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @return A QueueBrowser. - * @throws JMSException If creating a browser fails due to some internal error. - * @throws InvalidDestinationException If an invalid queue is specified. - * @throws InvalidSelectorException If the message selector is invalid. - */ - public QueueBrowser createBrowser(Queue queue, String messageSelector) throws JMSException - { - checkNotClosed(); - checkDestination(queue); - QueueBrowserImpl browser; - try - { - browser = - new QueueBrowserImpl(this, queue, messageSelector, String.valueOf(_consumerTag.incrementAndGet())); - } - catch (Exception e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Problem when creating Durable Browser.", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - // register this actor with the session - _messageActors.put(browser.getMessageActorID(), browser); - return browser; - } - - /** - * Create a TemporaryQueue. Its lifetime will be the Connection unless it is deleted earlier. - * - * @return A temporary queue. - * @throws JMSException If creating the temporary queue fails due to some internal error. - */ - public TemporaryQueue createTemporaryQueue() throws JMSException - { - TemporaryQueue result; - try - { - result = new TemporaryQueueImpl(this); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Problem when creating Durable Temporary Queue.", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - return result; - } - - /** - * Create a TemporaryTopic. Its lifetime will be the Connection unless it is deleted earlier. - * - * @return A temporary topic. - * @throws JMSException If creating the temporary topic fails due to some internal error. - */ - public TemporaryTopic createTemporaryTopic() throws JMSException - { - TemporaryTopic result; - try - { - result = new TemporaryTopicImpl(this); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Problem when creating Durable Temporary Topic.", e); - } - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - return result; - } - - /** - * Unsubscribes a durable subscription that has been created by a client. - * <p/> - * <P>This method deletes the state being maintained on behalf of the - * subscriber by its provider. - * <p/> - * <P>It is erroneous for a client to delete a durable subscription - * while there is an active <code>TopicSubscriber</code> for the - * subscription, or while a consumed message is part of a pending - * transaction or has not been acknowledged in the session. - * - * @param name the name used to identify this subscription - * @throws JMSException if the session fails to unsubscribe to the durable subscription due to some internal error. - * @throws InvalidDestinationException if an invalid subscription name - * is specified. - */ - public void unsubscribe(String name) throws JMSException - { - checkNotClosed(); - } - - /** - * Get the latest thrown exception. - * - * @return The latest thrown exception. - */ - public synchronized QpidException getCurrentException() - { - QpidException result = _currentException; - _currentException = null; - return result; - } - //----- Protected methods - - /** - * Remove a message actor form this session - * <p> This method is called when an actor is independently closed. - * - * @param messageActor The closed actor. - */ - protected void closeMessageActor(MessageActor messageActor) - { - _messageActors.remove(messageActor.getMessageActorID()); - } - - /** - * Idincates whether this session is stopped. - * - * @return True is this session is stopped, false otherwise. - */ - protected boolean isStopped() - { - return _isStopped; - } - - /** - * Start the flow of message to this session. - * - * @throws Exception If starting the session fails due to some communication error. - */ - protected synchronized void start() throws Exception - { - if (_isStopped) - { - // start all the MessageActors - for (MessageActor messageActor : _messageActors.values()) - { - messageActor.start(); - } - startDispatchThread(); - } - } - - /** - * Restart delivery of asynch messages - */ - private void startDispatchThread() - { - synchronized (_stoppingLock) - { - _isStopped = false; - _stoppingLock.notify(); - } - synchronized (_stoppingJoin) - { - _hasStopped = false; - } - } - - /** - * Stop the flow of message to this session. - * - * @throws Exception If stopping the session fails due to some communication error. - */ - protected synchronized void stop() throws Exception - { - if (!_isClosing && !_isStopped) - { - // stop all the MessageActors - for (MessageActor messageActor : _messageActors.values()) - { - messageActor.stop(); - } - synchronized (_incomingAsynchronousMessages) - { - _isStopped = true; - // unlock the sessionThread that will then wait on _stoppingLock - _incomingAsynchronousMessages.notifyAll(); - } - // wait for the sessionThread to stop processing messages - synchronized (_stoppingJoin) - { - while (!_hasStopped) - { - try - { - _stoppingJoin.wait(); - } - catch (InterruptedException e) - { - /* ignore */ - } - } - } - } - } - - /** - * Notify this session that a message is processed - * - * @param message The processed message. - */ - protected void preProcessMessage(QpidMessage message) - { - _inRecovery = false; - } - - /** - * Dispatch this message to this session asynchronous consumers - * - * @param consumerID The consumer ID. - * @param message The message to be dispatched. - */ - public void dispatchMessage(String consumerID, QpidMessage message) - { - synchronized (_incomingAsynchronousMessages) - { - _incomingAsynchronousMessages.addLast(new IncomingMessage(consumerID, message)); - _incomingAsynchronousMessages.notifyAll(); - } - } - - /** - * Indicate whether this session is recovering . - * - * @return true if this session is recovering. - */ - protected boolean isInRecovery() - { - return _inRecovery; - } - - /** - * Validate that the Session is not closed. - * <p/> - * If the Session has been closed, throw a IllegalStateException. This behaviour is - * required by the JMS specification. - * - * @throws IllegalStateException If the session is closed. - */ - protected void checkNotClosed() throws IllegalStateException - { - if (_isClosed) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Session has been closed. Cannot invoke any further operations."); - } - throw new javax.jms.IllegalStateException("Session has been closed. Cannot invoke any further operations."); - } - } - - /** - * Validate that the destination is valid i.e. it is not null - * - * @param dest The destination to be checked - * @throws InvalidDestinationException If the destination not valid. - */ - protected void checkDestination(Destination dest) throws InvalidDestinationException - { - if (dest == null) - { - throw new javax.jms.InvalidDestinationException("Invalid destination specified: " + dest, - "Invalid destination"); - } - } - - /** - * A session keeps the list of unack messages only when the ack mode is - * set to client ack mode. Otherwise messages are always ack. - * <p> We can use an ack heuristic for dups ok mode where bunch of messages are ack. - * This has to be done. - * - * @param message The message to be acknowledged. - * @throws JMSException If the message cannot be acknowledged due to an internal error. - */ - protected void acknowledgeMessage(QpidMessage message) throws JMSException - { - if (getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) - { - // messages will be acknowldeged by the client application. - // store this message for acknowledging it afterward - synchronized (_unacknowledgedMessages) - { - _unacknowledgedMessages.add(message); - } - } - else - { - // acknowledge this message - RangeSet ranges = new RangeSet(); - ranges.add(message.getMessageTransferId()); - getQpidSession().messageAcknowledge(ranges); - } - //tobedone: Implement DUPS OK heuristic - } - - /** - * This method is called when a message is acked. - * <p/> - * <P>Acknowledgment of a message automatically acknowledges all - * messages previously received by the session. Clients may - * individually acknowledge messages or they may choose to acknowledge - * messages in application defined groups (which is done by acknowledging - * the last received message in the group). - * - * @throws JMSException If this method is called on a closed session. - */ - public void acknowledge() throws JMSException - { - checkNotClosed(); - if (getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE) - { - synchronized (_unacknowledgedMessages) - { - for (QpidMessage message : _unacknowledgedMessages) - { - // acknowledge this message - RangeSet ranges = new RangeSet(); - ranges.add(message.getMessageTransferId()); - getQpidSession().messageAcknowledge(ranges); - } - //empty the list of unack messages - _unacknowledgedMessages.clear(); - } - } - //else there is no effect - } - - /** - * Access to the underlying Qpid Session - * - * @return The associated Qpid Session. - */ - protected org.apache.qpidity.nclient.Session getQpidSession() - { - return _qpidSession; - } - - /** - * Get this session's conneciton - * - * @return This session's connection - */ - protected ConnectionImpl getConnection() - { - return _connection; - } - - /** - * sync and return the potential exception - * - * @throws QpidException If an exception has been thrown by the broker. - */ - protected void testQpidException() throws QpidException - { - //_qpidSession.sync(); - QpidException qe = getCurrentException(); - if (qe != null) - { - throw qe; - } - } - - //------ Private Methods - /** - * Close the producer and the consumers of this session - * - * @throws JMSException If one of the MessaeActor cannot be closed due to some internal error. - */ - private void closeAllMessageActors() throws JMSException - { - for (MessageActor messageActor : _messageActors.values()) - { - messageActor.closeMessageActor(); - } - } - - /** - * create and start the MessageDispatcherThread. - */ - private synchronized void initMessageDispatcherThread() - { - // Create and start a MessageDispatcherThread - // This thread is dispatching messages to the async consumers - _messageDispatcherThread = new MessageDispatcherThread(); - _messageDispatcherThread.start(); - } - - //------ Inner classes - - /** - * Lstener for qpid protocol exceptions - */ - private class QpidSessionExceptionListener implements org.apache.qpidity.nclient.ClosedListener - { - public void onClosed(ErrorCode errorCode, String reason, Throwable t) - { - synchronized (this) - { - //todo check the error code for finding out if we need to notify the - // JMS connection exception listener - _currentException = new QpidException(reason,errorCode,null); - } - } - } - - /** - * Convenient class for storing incoming messages associated with a consumer ID. - * <p> Those messages are enqueued in _incomingAsynchronousMessages - */ - private class IncomingMessage - { - // The consumer ID - private String _consumerId; - // The message - private QpidMessage _message; - - //-- constructor - /** - * Creat a new incoming message - * - * @param consumerId The consumer ID - * @param message The message to be delivered - */ - IncomingMessage(String consumerId, QpidMessage message) - { - _consumerId = consumerId; - _message = message; - } - - // Getters - /** - * Get the consumer ID - * - * @return The consumer ID for this message - */ - public String getConsumerId() - { - return _consumerId; - } - - /** - * Get the message. - * - * @return The message. - */ - public QpidMessage getMessage() - { - return _message; - } - } - - /** - * A MessageDispatcherThread is attached to every SessionImpl. - * <p/> - * This thread is responsible for removing messages from m_incomingMessages and - * dispatching them to the appropriate MessageConsumer. - * <p> Messages have to be dispatched serially. - */ - private class MessageDispatcherThread extends Thread - { - //--- Constructor - /** - * Create a Deamon thread for dispatching messages to this session listeners. - */ - MessageDispatcherThread() - { - super("MessageDispatcher"); - // this thread is Deamon - setDaemon(true); - } - - /** - * Use to run this thread. - */ - public void run() - { - IncomingMessage message = null; - // deliver messages to asynchronous consumers until the stop flag is set. - do - { - // When this session is not closing and and stopped - // then this thread needs to wait until messages are delivered. - synchronized (_incomingAsynchronousMessages) - { - while (!_isClosing && !_isStopped && _incomingAsynchronousMessages.isEmpty()) - { - try - { - _incomingAsynchronousMessages.wait(); - } - catch (InterruptedException ie) - { - /* ignore */ - } - } - } - // If this session is stopped then we need to wait on the stoppingLock - synchronized (_stoppingLock) - { - try - { - while (_isStopped) - { - // if the session is stopped we have to notify the stopper thread - synchronized (_stoppingJoin) - { - _hasStopped = true; - _stoppingJoin.notify(); - } - _stoppingLock.wait(); - } - } - catch (Exception ie) - { - /* ignore */ - } - } - synchronized (_incomingAsynchronousMessages) - { - if (!_isClosing && !_incomingAsynchronousMessages.isEmpty()) - { - message = _incomingAsynchronousMessages.getFirst(); - } - } - - if (message != null) - { - MessageConsumerImpl mc; - synchronized (_messageActors) - { - mc = (MessageConsumerImpl) _messageActors.get(message.getConsumerId()); - } - if (mc != null) - { - try - { - // mc.onMessage(message.getMessage()); - mc.notifyMessageListener(message.getMessage()); - } - catch (RuntimeException t) - { - // the JMS specification tells us to flag that to the client! - _logger.error( - "Warning! Asynchronous message consumer" + mc + " from session " + this + " has thrown a RunTimeException " + t); - } - } - } - message = null; - } - while (!_isClosing); // repeat as long as this session is not closing - } - } - -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/TemporaryDestination.java b/java/client/src/main/java/org/apache/qpidity/njms/TemporaryDestination.java deleted file mode 100644 index 34d2cbd1b1..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/TemporaryDestination.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.njms; - -import javax.jms.JMSException; - -/** - * Interface to abstract functionalities of temporary destinations. - */ -public interface TemporaryDestination -{ - /** - * Delete this temporary destination. - * - * @throws javax.jms.JMSException If the temporary destination cannot be deleted due to some internal error. - */ - public void delete() throws JMSException; - - /** - * Indicate whether this temporary destination is deleted - * @return True is this temporary destination is deleted, false otherwise - */ - public boolean isdeleted(); - -}
\ No newline at end of file diff --git a/java/client/src/main/java/org/apache/qpidity/njms/TemporaryQueueImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/TemporaryQueueImpl.java deleted file mode 100644 index 88dae74cc1..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/TemporaryQueueImpl.java +++ /dev/null @@ -1,88 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.TemporaryQueue; -import javax.jms.JMSException; -import java.util.UUID; - -/** - * Implements TemporaryQueue - */ -public class TemporaryQueueImpl extends QueueImpl implements TemporaryQueue, TemporaryDestination -{ - /** - * Indicates whether this temporary queue is deleted. - */ - private boolean _isDeleted; - - /** - * The session used to create this destination - */ - private SessionImpl _session; - - //--- constructor - /** - * Create a new TemporaryQueueImpl. - * - * @param session The session used to create this TemporaryQueueImpl. - * @throws QpidException If creating the TemporaryQueueImpl fails due to some error. - */ - protected TemporaryQueueImpl(SessionImpl session) throws QpidException - { - super("TempQueue-" + UUID.randomUUID()); - // temporary destinations do not have names - _isAutoDelete = false; - _isDurable = false; - _isExclusive = false; - _isDeleted = false; - _session = session; - // we must create this queue - registerQueue(session, true); - } - - //-- TemporaryDestination Interface - /** - * Specify whether this temporary destination is deleted. - * - * @return true is this temporary destination is deleted. - */ - public boolean isdeleted() - { - return _isDeleted; - } - - //-- TemporaryQueue Interface - /** - * Delete this temporary destinaiton - * - * @throws JMSException If deleting this temporary queue fails due to some error. - */ - public void delete() throws JMSException - { - if (!_isDeleted) - { - _session.getQpidSession().queueDelete(_queueName); - } - _isDeleted = true; - } - -} - diff --git a/java/client/src/main/java/org/apache/qpidity/njms/TemporaryTopicImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/TemporaryTopicImpl.java deleted file mode 100644 index 63fdc68c65..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/TemporaryTopicImpl.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.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.TemporaryTopic; -import javax.jms.JMSException; -import java.util.UUID; - - -/** - * Implements TemporaryTopic - */ -public class TemporaryTopicImpl extends TopicImpl implements TemporaryTopic, TemporaryDestination -{ - /** - * Indicates whether this temporary topic is deleted. - */ - private boolean _isDeleted = false; - - /** - * The session used to create this destination - */ - private SessionImpl _session; - - //--- constructor - /** - * Create a new TemporaryTopicImpl with a given name. - * - * @param session The session used to create this TemporaryTopicImpl. - * @throws QpidException If creating the TemporaryTopicImpl fails due to some error. - */ - protected TemporaryTopicImpl(SessionImpl session) throws QpidException - { - // temporary destinations do not have names. - super(session, "TemporayTopic-" + UUID.randomUUID()); - _session = session; - } - - //-- TemporaryDestination Interface - public boolean isdeleted() - { - return _isDeleted; - } - - //-- TemporaryTopic Interface - public void delete() throws JMSException - { - if (!_isDeleted) - { - _session.getQpidSession().queueDelete(_queueName); - } - _isDeleted = true; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/TopicImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/TopicImpl.java deleted file mode 100644 index 2fcd6e4651..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/TopicImpl.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.njms; - -import org.apache.qpid.url.QpidBindingURL; -import org.apache.qpidity.QpidException; -import org.apache.qpidity.exchange.ExchangeDefaults; -import org.apache.qpidity.transport.Option; - -import javax.jms.Topic; -import java.util.UUID; - -/** - * Implementation of the javax.njms.Topic interface. - */ -public class TopicImpl extends DestinationImpl implements Topic -{ - //--- Constructor - /** - * Create a new TopicImpl with a given name. - * - * @param name The name of this topic - * @param session The session used to create this queue. - * @throws QpidException If the topic name is not valid - */ - protected TopicImpl(SessionImpl session, String name) throws QpidException - { - super(name); - _queueName = "Topic-" + UUID.randomUUID(); - _routingKey = name; - _destinationName = name; - _exchangeName = ExchangeDefaults.TOPIC_EXCHANGE_NAME; - _exchangeType = ExchangeDefaults.TOPIC_EXCHANGE_CLASS; - _isAutoDelete = true; - _isDurable = false; - _isExclusive = true; - checkTopicExists(session); - } - - /** - * Create a new TopicImpl with a given name. - * - * @param name The name of this topic - * @throws QpidException If the topic name is not valid - */ - public TopicImpl(String name) throws QpidException - { - super(name); - _queueName = "Topic-" + UUID.randomUUID(); - _routingKey = name; - _destinationName = name; - _exchangeName = ExchangeDefaults.TOPIC_EXCHANGE_NAME; - _exchangeType = ExchangeDefaults.TOPIC_EXCHANGE_CLASS; - _isAutoDelete = true; - _isDurable = false; - _isExclusive = true; - } - - /** - * Create a TopicImpl from a binding URL - * - * @param session The session used to create this Topic. - * @param binding The URL - * @throws QpidException If the URL is not valid - */ - protected TopicImpl(SessionImpl session, QpidBindingURL binding) throws QpidException - { - super(binding); - checkTopicExists(session); - } - - - /** - * Create a TopicImpl from a binding URL - * - * @param binding The URL - * @throws QpidException If the URL is not valid - */ - public TopicImpl(QpidBindingURL binding) throws QpidException - { - super(binding); - } - - //--- javax.jsm.Topic Interface - /** - * Gets the name of this topic. - * - * @return This topic's name. - */ - public String getTopicName() - { - return _destinationName; - } - - /** - * Check that this exchange exists - * - * @param session The session used to create this Topic. - * @throws QpidException If this exchange does not exists on the broker. - */ - private void checkTopicExists(SessionImpl session) throws QpidException - { - // test if this exchange exist on the broker - session.getQpidSession().exchangeDeclare(_exchangeName, _exchangeType, null, null, Option.PASSIVE); - // wait for the broker response - System.out.println("Checking for exchange"); - - session.getQpidSession().sync(); - - System.out.println("Calling sync()"); - // todo get the exception - } - -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/TopicPublisherImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/TopicPublisherImpl.java deleted file mode 100644 index 7f65261486..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/TopicPublisherImpl.java +++ /dev/null @@ -1,128 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms; - -import javax.jms.*; - -/** - * Implements TopicPublisher - */ -public class TopicPublisherImpl extends MessageProducerImpl implements TopicPublisher -{ - //--- Constructor - /** - * Create a TopicPublisherImpl. - * - * @param session The session from which the TopicPublisherImpl is instantiated - * @param topic The default topic for this TopicPublisherImpl - * @throws JMSException If the TopicPublisherImpl cannot be created due to some internal error. - */ - protected TopicPublisherImpl(SessionImpl session, Topic topic) throws JMSException - { - super(session, (DestinationImpl) topic); - } - - //--- Interface javax.njms.TopicPublisher - /** - * Get the topic associated with this TopicPublisher. - * - * @return This publisher's topic - * @throws JMSException If getting the topic fails due to some internal error. - */ - public Topic getTopic() throws JMSException - { - return (Topic) getDestination(); - } - - - /** - * Publish a message to the topic using the default delivery mode, priority and time to live. - * - * @param message The message to publish - * @throws JMSException If publishing the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If an invalid message is specified. - * @throws javax.jms.InvalidDestinationException - * If an invalid topic is specified. - * @throws java.lang.UnsupportedOperationException - * If that publisher topic was not specified at creation time. - */ - public void publish(Message message) throws JMSException - { - super.send(message); - } - - /** - * Publish a message to the topic, specifying delivery mode, priority and time to live. - * - * @param message The message to publish - * @param deliveryMode The delivery mode to use - * @param priority The priority for this message - * @param timeToLive The message's lifetime (in milliseconds) - * @throws JMSException If publishing the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If an invalid message is specified. - * @throws javax.jms.InvalidDestinationException - * If an invalid topic is specified. - * @throws java.lang.UnsupportedOperationException - * If that publisher topic was not specified at creation time. - */ - public void publish(Message message, int deliveryMode, int priority, long timeToLive) throws JMSException - { - super.send(message, deliveryMode, priority, timeToLive); - } - - - /** - * Publish a message to a topic for an unidentified message producer. - * Uses this TopicPublisher's default delivery mode, priority and time to live. - * - * @param topic The topic to publish this message to - * @param message The message to publish - * @throws JMSException If publishing the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If an invalid message is specified. - * @throws javax.jms.InvalidDestinationException - * If an invalid topic is specified. - */ - public void publish(Topic topic, Message message) throws JMSException - { - super.send(topic, message); - } - - /** - * Publishes a message to a topic for an unidentified message - * producer, specifying delivery mode, priority and time to live. - * - * @param topic The topic to publish this message to - * @param message The message to publish - * @param deliveryMode The delivery mode - * @param priority The priority for this message - * @param timeToLive The message's lifetime (in milliseconds) - * @throws JMSException If publishing the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If an invalid message is specified. - * @throws javax.jms.InvalidDestinationException - * If an invalid topic is specified. - */ - public void publish(Topic topic, Message message, int deliveryMode, int priority, long timeToLive) throws - JMSException - { - super.send(topic, message, deliveryMode, priority, timeToLive); - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/TopicSessionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/TopicSessionImpl.java deleted file mode 100644 index 74c5a2c0f7..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/TopicSessionImpl.java +++ /dev/null @@ -1,155 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import javax.jms.*; -import javax.jms.IllegalStateException; - -import org.apache.qpidity.QpidException; - -/** - * Implements TopicSession - */ -public class TopicSessionImpl extends SessionImpl implements TopicSession -{ - //-- constructor - /** - * Create a new TopicSessionImpl. - * - * @param connection The ConnectionImpl object from which the Session is created. - * @param transacted Specifiy whether this session is transacted? - * @param acknowledgeMode The session's acknowledgement mode. This value is ignored and set to - * {@link javax.jms.Session#SESSION_TRANSACTED} if the <code>transacted</code> parameter - * is true. - * @throws javax.jms.JMSSecurityException If the user could not be authenticated. - * @throws javax.jms.JMSException In case of internal error. - */ - protected TopicSessionImpl(ConnectionImpl connection, boolean transacted, int acknowledgeMode) throws QpidException, JMSException - { - super(connection, transacted, acknowledgeMode,false); - } - - //-- Overwritten methods - /** - * Create a QueueBrowser. - * - * @param queue The <CODE>Queue</CODE> to browse. - * @param messageSelector Only messages with properties matching the message selector expression are delivered. - * @return Always throws an exception - * @throws IllegalStateException Always - */ - @Override - public QueueBrowser createBrowser(Queue queue, String messageSelector) throws JMSException - { - throw new IllegalStateException("Cannot invoke createBrowser from TopicSession"); - } - - /** - * Create a QueueBrowser. - * - * @param queue The <CODE>Queue</CODE> to browse. - * @return Always throws an exception - * @throws IllegalStateException Always - */ - @Override - public QueueBrowser createBrowser(Queue queue) throws JMSException - { - throw new IllegalStateException("Cannot invoke createBrowser from TopicSession"); - } - - /** - * Creates a temporary queue. - * - * @return Always throws an exception - * @throws IllegalStateException Always - */ - @Override - public TemporaryQueue createTemporaryQueue() throws JMSException - { - throw new IllegalStateException("Cannot invoke createTemporaryQueue from TopicSession"); - } - - /** - * Creates a queue identity by a given name. - * - * @param queueName the name of this <CODE>Queue</CODE> - * @return Always throws an exception - * @throws IllegalStateException Always - */ - @Override - public Queue createQueue(String queueName) throws JMSException - { - throw new IllegalStateException("Cannot invoke createQueue from TopicSession"); - } - - //--- Interface TopicSession - /** - * Create a publisher for the specified topic. - * - * @param topic the <CODE>Topic</CODE> to publish to, or null if this is an unidentified publisher. - * @throws JMSException If the creating a publisher fails due to some internal error. - * @throws InvalidDestinationException If an invalid topic is specified. - */ - public TopicPublisher createPublisher(Topic topic) throws JMSException - { - - checkNotClosed(); - // we do not check the destination topic here, since unidentified publishers are allowed. - return new TopicPublisherImpl(this, topic); - } - - /** - * Creates a nondurable subscriber to the specified topic. - * - * @param topic The Topic to subscribe to - * @throws JMSException If creating a subscriber fails due to some internal error. - * @throws InvalidDestinationException If an invalid topic is specified. - */ - public TopicSubscriber createSubscriber(Topic topic) throws JMSException - { - return createSubscriber(topic, null, false); - } - - /** - * Creates a nondurable subscriber to the specified topic, using a - * message selector or specifying whether messages published by its - * own connection should be delivered to it. - * - * @param topic The Topic to subscribe to - * @param messageSelector A value of null or an empty string indicates that there is no message selector. - * @param noLocal If true then inhibits the delivery of messages published by this subscriber's connection. - * @throws JMSException If creating a subscriber fails due to some internal error. - * @throws InvalidDestinationException If an invalid topic is specified. - * @throws InvalidSelectorException If the message selector is invalid. - */ - public TopicSubscriber createSubscriber(Topic topic, String messageSelector, boolean noLocal) throws JMSException - { - checkNotClosed(); - checkDestination(topic); - TopicSubscriber topicSubscriber; - try - { - topicSubscriber = new TopicSubscriberImpl(this, topic, messageSelector, noLocal, null,String.valueOf(_consumerTag.incrementAndGet())); - } - catch (Exception e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - return topicSubscriber; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/TopicSubscriberImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/TopicSubscriberImpl.java deleted file mode 100644 index 73d03db055..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/TopicSubscriberImpl.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.njms; - -import javax.jms.TopicSubscriber; -import javax.jms.Topic; -import javax.jms.JMSException; - -/** - * Implementation of the JMS TopicSubscriber interface. - */ -public class TopicSubscriberImpl extends MessageConsumerImpl implements TopicSubscriber -{ - //--- Constructor - /** - * Create a new TopicSubscriberImpl. - * - * @param session The session of this topic subscriber. - * @param topic The default topic for this TopicSubscriberImpl - * @param messageSelector The MessageSelector - * @param noLocal If true inhibits the delivery of messages published by its own connection. - * @param subscriptionName Name of the subscription if this is to be created as a durable subscriber. - * If this value is null, a non-durable subscription is created. - * @throws Exception If the TopicSubscriberImpl cannot be created due to internal error. - */ - protected TopicSubscriberImpl(SessionImpl session, Topic topic, String messageSelector, boolean noLocal, - String subscriptionName,String consumerTag) throws Exception - { - super(session, (DestinationImpl) topic, messageSelector, noLocal, subscriptionName,consumerTag); - } - - //--- javax.njms.TopicSubscriber interface - /** - * Get the Topic associated with this subscriber. - * - * @return This subscriber's Topic - * @throws JMSException if getting the topic for this topicSubscriber fails due to some internal error. - */ - public Topic getTopic() throws JMSException - { - checkNotClosed(); - return (TopicImpl) _destination; - } - - - /** - * Get NoLocal for this subscriber. - * - * @return True if locally published messages are being inhibited, false otherwise - * @throws JMSException If getting NoLocal for this topic subscriber fails due to some internal error. - */ - public boolean getNoLocal() throws JMSException - { - checkNotClosed(); - return _noLocal; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/XAConnectionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/XAConnectionImpl.java deleted file mode 100644 index 3d181db1f6..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/XAConnectionImpl.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.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.XAConnection; -import javax.jms.JMSException; -import javax.jms.XASession; - -/** - * This class implements the javax.njms.XAConnection interface - */ -public class XAConnectionImpl extends ConnectionImpl implements XAConnection -{ - //-- constructor - /** - * Create a XAConnection. - * - * @param host The broker host name. - * @param port The port on which the broker is listening for connection. - * @param virtualHost The virtual host on which the broker is deployed. - * @param username The user name used of user identification. - * @param password The password name used of user identification. - * @throws QpidException If creating a connection fails due to some internal error. - */ - protected XAConnectionImpl(String host, int port, String virtualHost, String username, String password) throws QpidException - { - super(host, port, virtualHost, username, password); - } - - //-- interface XAConnection - /** - * Creates an XASession. - * - * @return A newly created XASession. - * @throws JMSException If the XAConnectiono fails to create an XASession due to - * some internal error. - */ - public synchronized XASession createXASession() throws JMSException - { - checkNotClosed(); - XASessionImpl xasession; - try - { - xasession = new XASessionImpl(this); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - // add this session with the list of session that are handled by this connection - _sessions.add(xasession); - return xasession; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/XAQueueConnectionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/XAQueueConnectionImpl.java deleted file mode 100644 index b500208036..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/XAQueueConnectionImpl.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.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.XAQueueConnection; -import javax.jms.JMSException; -import javax.jms.XAQueueSession; - -/** - * Implements XAQueueConnection - */ -public class XAQueueConnectionImpl extends XAConnectionImpl implements XAQueueConnection -{ - //-- constructor - /** - * Create a XAQueueConnection. - * - * @param host The broker host name. - * @param port The port on which the broker is listening for connection. - * @param virtualHost The virtual host on which the broker is deployed. - * @param username The user name used of user identification. - * @param password The password name used of user identification. - * @throws QpidException If creating a XAQueueConnection fails due to some internal error. - */ - public XAQueueConnectionImpl(String host, int port, String virtualHost, String username, String password) - throws QpidException - { - super(host, port, virtualHost, username, password); - } - - //-- Interface XAQueueConnection - /** - * Creates an XAQueueSession. - * - * @return A newly created XASession. - * @throws JMSException If the XAQueueConnectionImpl fails to create an XASession due to - * some internal error. - */ - public synchronized XAQueueSession createXAQueueSession() throws JMSException - { - checkNotClosed(); - XAQueueSessionImpl xaQueueSession; - try - { - xaQueueSession = new XAQueueSessionImpl(this); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - // add this session with the list of session that are handled by this connection - _sessions.add(xaQueueSession); - return xaQueueSession; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/XAQueueSessionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/XAQueueSessionImpl.java deleted file mode 100644 index 3df8a0928e..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/XAQueueSessionImpl.java +++ /dev/null @@ -1,64 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.QueueSession; -import javax.jms.JMSException; -import javax.jms.XAQueueSession; - -/** - * Imeplements javax.njms.XAQueueSessionImpl - */ -public class XAQueueSessionImpl extends XASessionImpl implements XAQueueSession -{ - /** - * The standard session - */ - private QueueSession _jmsQueueSession; - - //-- Constructors - /** - * Create a JMS XAQueueSessionImpl - * - * @param connection The ConnectionImpl object from which the Session is created. - * @throws org.apache.qpidity.QpidException - * In case of internal error. - */ - protected XAQueueSessionImpl(ConnectionImpl connection) throws QpidException - { - super(connection); - } - - //--- interface XAQueueSession - /** - * Gets the topic session associated with this <CODE>XATopicSession</CODE>. - * - * @return the topic session object - * @throws JMSException If an internal error occurs. - */ - public QueueSession getQueueSession() throws JMSException - { - if (_jmsQueueSession == null) - { - _jmsQueueSession = getConnection().createQueueSession(true, getAcknowledgeMode()); - } - return _jmsQueueSession; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/XAResourceImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/XAResourceImpl.java deleted file mode 100644 index ae6477a5a4..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/XAResourceImpl.java +++ /dev/null @@ -1,507 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; - -import javax.transaction.xa.XAException; -import javax.transaction.xa.XAResource; -import javax.transaction.xa.Xid; - -import org.apache.qpidity.QpidException; -import org.apache.qpidity.dtx.XidImpl; -import org.apache.qpidity.transport.*; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This is an implementation of javax.njms.XAResource. - */ -public class XAResourceImpl implements XAResource -{ - /** - * this XAResourceImpl's logger - */ - private static final Logger _logger = LoggerFactory.getLogger(XAResourceImpl.class); - - /** - * Reference to the associated XASession - */ - private XASessionImpl _xaSession = null; - - /** - * The XID of this resource - */ - private Xid _xid; - - //--- constructor - - /** - * Create an XAResource associated with a XASession - * - * @param xaSession The session XAresource - */ - protected XAResourceImpl(XASessionImpl xaSession) - { - _xaSession = xaSession; - } - - //--- The XAResource - /** - * Commits the global transaction specified by xid. - * - * @param xid A global transaction identifier - * @param b If true, use a one-phase commit protocol to commit the work done on behalf of xid. - * @throws XAException An error has occurred. An error has occurred. Possible XAExceptions are XA_HEURHAZ, - * XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO. - */ - public void commit(Xid xid, boolean b) throws XAException - { - if (_logger.isDebugEnabled()) - { - _logger.debug("commit ", xid); - } - if (xid == null) - { - throw new XAException(XAException.XAER_PROTO); - } - Future<DtxCoordinationCommitResult> future; - try - { - future = _xaSession.getQpidSession() - .dtxCoordinationCommit(XidImpl.convertToString(xid), b ? Option.ONE_PHASE : Option.NO_OPTION); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert Xid into String format ", e); - } - throw new XAException(XAException.XAER_PROTO); - } - // now wait on the future for the result - DtxCoordinationCommitResult result = future.get(); - int status = result.getStatus(); - switch (status) - { - case Constant.XA_OK: - // do nothing this ok - break; - case Constant.XA_HEURHAZ: - throw new XAException(XAException.XA_HEURHAZ); - case Constant.XA_HEURCOM: - throw new XAException(XAException.XA_HEURCOM); - case Constant.XA_HEURRB: - throw new XAException(XAException.XA_HEURRB); - case Constant.XA_HEURMIX: - throw new XAException(XAException.XA_HEURMIX); - case Constant.XA_RBROLLBACK: - throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: - throw new XAException(XAException.XA_RBTIMEOUT); - default: - // this should not happen - if (_logger.isDebugEnabled()) - { - _logger.debug("got unexpected status value: ", status); - } - throw new XAException(XAException.XAER_PROTO); - } - } - - /** - * Ends the work performed on behalf of a transaction branch. - * The resource manager disassociates the XA resource from the transaction branch specified - * and lets the transaction complete. - * <ul> - * <li> If TMSUSPEND is specified in the flags, the transaction branch is temporarily suspended in an incomplete state. - * The transaction context is in a suspended state and must be resumed via the start method with TMRESUME specified. - * <li> If TMFAIL is specified, the portion of work has failed. The resource manager may mark the transaction as rollback-only - * <li> If TMSUCCESS is specified, the portion of work has completed successfully. - * /ul> - * - * @param xid A global transaction identifier that is the same as the identifier used previously in the start method - * @param flag One of TMSUCCESS, TMFAIL, or TMSUSPEND. - * @throws XAException An error has occurred. An error has occurred. Possible XAException values are XAER_RMERR, - * XAER_RMFAILED, XAER_NOTA, XAER_INVAL, XAER_PROTO, or XA_RB*. - */ - public void end(Xid xid, int flag) throws XAException - { - if (_logger.isDebugEnabled()) - { - _logger.debug("end ", xid); - } - if (xid == null) - { - throw new XAException(XAException.XAER_PROTO); - } - Future<DtxDemarcationEndResult> future; - try - { - future = _xaSession.getQpidSession() - .dtxDemarcationEnd(XidImpl.convertToString(xid), - flag == XAResource.TMFAIL ? Option.FAIL : Option.NO_OPTION, - flag == XAResource.TMSUSPEND ? Option.SUSPEND : Option.NO_OPTION); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert Xid into String format ", e); - } - throw new XAException(XAException.XAER_PROTO); - } - // now wait on the future for the result - DtxDemarcationEndResult result = future.get(); - int status = result.getStatus(); - switch (status) - { - case Constant.XA_OK: - // do nothing this ok - break; - case Constant.XA_RBROLLBACK: - throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: - throw new XAException(XAException.XA_RBTIMEOUT); - default: - // this should not happen - if (_logger.isDebugEnabled()) - { - _logger.debug("got unexpected status value: ", status); - } - throw new XAException(XAException.XAER_PROTO); - } - } - - /** - * Tells the resource manager to forget about a heuristically completed transaction branch. - * - * @param xid String(xid.getGlobalTransactionId() A global transaction identifier - * @throws XAException An error has occurred. Possible exception values are XAER_RMERR, XAER_RMFAIL, - * XAER_NOTA, XAER_INVAL, or XAER_PROTO. - */ - public void forget(Xid xid) throws XAException - { - if (_logger.isDebugEnabled()) - { - _logger.debug("forget ", xid); - } - if (xid == null) - { - throw new XAException(XAException.XAER_PROTO); - } - _xaSession.getQpidSession().dtxCoordinationForget(new String(xid.getGlobalTransactionId())); - } - - /** - * Obtains the current transaction timeout value set for this XAResource instance. - * If XAResource.setTransactionTimeout was not used prior to invoking this method, - * the return value is the default timeout i.e. 0; - * otherwise, the value used in the previous setTransactionTimeout call is returned. - * - * @return The transaction timeout value in seconds. - * @throws XAException An error has occurred. Possible exception values are XAER_RMERR, XAER_RMFAIL. - */ - public int getTransactionTimeout() throws XAException - { - int result = 0; - if (_xid != null) - { - try - { - Future<DtxCoordinationGetTimeoutResult> future = - _xaSession.getQpidSession().dtxCoordinationGetTimeout(XidImpl.convertToString(_xid)); - result = (int) future.get().getTimeout(); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert Xid into String format ", e); - } - throw new XAException(XAException.XAER_PROTO); - } - } - return result; - } - - /** - * This method is called to determine if the resource manager instance represented - * by the target object is the same as the resouce manager instance represented by - * the parameter xaResource. - * - * @param xaResource An XAResource object whose resource manager instance is to - * be compared with the resource manager instance of the target object - * @return <code>true</code> if it's the same RM instance; otherwise <code>false</code>. - * @throws XAException An error has occurred. Possible exception values are XAER_RMERR, XAER_RMFAIL. - */ - public boolean isSameRM(XAResource xaResource) throws XAException - { - // TODO : get the server identity of xaResource and compare it with our own one - return false; - } - - /** - * Prepare for a transaction commit of the transaction specified in <code>Xid</code>. - * - * @param xid A global transaction identifier. - * @return A value indicating the resource manager's vote on the outcome of the transaction. - * The possible values are: XA_RDONLY or XA_OK. - * @throws XAException An error has occurred. Possible exception values are: XAER_RMERR or XAER_NOTA - */ - public int prepare(Xid xid) throws XAException - { - if (_logger.isDebugEnabled()) - { - _logger.debug("prepare ", xid); - } - if (xid == null) - { - throw new XAException(XAException.XAER_PROTO); - } - Future<DtxCoordinationPrepareResult> future; - try - { - future = _xaSession.getQpidSession() - .dtxCoordinationPrepare(XidImpl.convertToString(xid)); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert Xid into String format ", e); - } - throw new XAException(XAException.XAER_PROTO); - } - DtxCoordinationPrepareResult result = future.get(); - int status = result.getStatus(); - int outcome; - switch (status) - { - case Constant.XA_OK: - outcome = XAResource.XA_OK; - break; - case Constant.XA_RDONLY: - outcome = XAResource.XA_RDONLY; - break; - case Constant.XA_RBROLLBACK: - throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: - throw new XAException(XAException.XA_RBTIMEOUT); - default: - // this should not happen - if (_logger.isDebugEnabled()) - { - _logger.debug("got unexpected status value: ", status); - } - throw new XAException(XAException.XAER_PROTO); - } - return outcome; - } - - /** - * Obtains a list of prepared transaction branches. - * <p/> - * The transaction manager calls this method during recovery to obtain the list of transaction branches - * that are currently in prepared or heuristically completed states. - * - * @param flag One of TMSTARTRSCAN, TMENDRSCAN, TMNOFLAGS. - * TMNOFLAGS must be used when no other flags are set in the parameter. - * @return zero or more XIDs of the transaction branches that are currently in a prepared or heuristically - * completed state. - * @throws XAException An error has occurred. Possible value is XAER_INVAL. - */ - public Xid[] recover(int flag) throws XAException - { - // the flag is ignored - Future<DtxCoordinationRecoverResult> future = _xaSession.getQpidSession().dtxCoordinationRecover(); - DtxCoordinationRecoverResult res = future.get(); - // todo make sure that the keys of the returned map are the xids - Xid[] result = new Xid[res.getInDoubt().size()]; - int i = 0; - try - { - for (Object xid : res.getInDoubt()) - { - result[i] = new XidImpl((String) xid); - i++; - } - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert string into Xid ", e); - } - throw new XAException(XAException.XAER_PROTO); - } - return result; - } - - /** - * Informs the resource manager to roll back work done on behalf of a transaction branch - * - * @param xid A global transaction identifier. - * @throws XAException An error has occurred. - */ - public void rollback(Xid xid) throws XAException - { - if (xid == null) - { - throw new XAException(XAException.XAER_PROTO); - } - // the flag is ignored - Future<DtxCoordinationRollbackResult> future; - try - { - future = _xaSession.getQpidSession() - .dtxCoordinationRollback(XidImpl.convertToString(xid)); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert Xid into String format ", e); - } - throw new XAException(XAException.XAER_PROTO); - } - // now wait on the future for the result - DtxCoordinationRollbackResult result = future.get(); - int status = result.getStatus(); - switch (status) - { - case Constant.XA_OK: - // do nothing this ok - break; - case Constant.XA_HEURHAZ: - throw new XAException(XAException.XA_HEURHAZ); - case Constant.XA_HEURCOM: - throw new XAException(XAException.XA_HEURCOM); - case Constant.XA_HEURRB: - throw new XAException(XAException.XA_HEURRB); - case Constant.XA_HEURMIX: - throw new XAException(XAException.XA_HEURMIX); - case Constant.XA_RBROLLBACK: - throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: - throw new XAException(XAException.XA_RBTIMEOUT); - default: - // this should not happen - if (_logger.isDebugEnabled()) - { - _logger.debug("got unexpected status value: ", status); - } - throw new XAException(XAException.XAER_PROTO); - } - } - - /** - * Sets the current transaction timeout value for this XAResource instance. - * Once set, this timeout value is effective until setTransactionTimeout is - * invoked again with a different value. - * To reset the timeout value to the default value used by the resource manager, set the value to zero. - * - * @param timeout The transaction timeout value in seconds. - * @return true if transaction timeout value is set successfully; otherwise false. - * @throws XAException An error has occurred. Possible exception values are XAER_RMERR, XAER_RMFAIL, or XAER_INVAL. - */ - public boolean setTransactionTimeout(int timeout) throws XAException - { - boolean result = false; - if (_xid != null) - { - try - { - _xaSession.getQpidSession() - .dtxCoordinationSetTimeout(XidImpl.convertToString(_xid), timeout); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert Xid into String format ", e); - } - throw new XAException(XAException.XAER_PROTO); - } - result = true; - } - return result; - } - - /** - * Starts work on behalf of a transaction branch specified in xid. - * <ul> - * <li> If TMJOIN is specified, an exception is thrown as it is not supported - * <li> If TMRESUME is specified, the start applies to resuming a suspended transaction specified in the parameter xid. - * <li> If neither TMJOIN nor TMRESUME is specified and the transaction specified by xid has previously been seen by the - * resource manager, the resource manager throws the XAException exception with XAER_DUPID error code. - * </ul> - * - * @param xid A global transaction identifier to be associated with the resource - * @param flag One of TMNOFLAGS, TMJOIN, or TMRESUME - * @throws XAException An error has occurred. Possible exceptions - * are XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_DUPID, XAER_OUTSIDE, XAER_NOTA, XAER_INVAL, or XAER_PROTO. - */ - public void start(Xid xid, int flag) throws XAException - { - if (_logger.isDebugEnabled()) - { - _logger.debug("start ", xid); - } - if (xid == null) - { - throw new XAException(XAException.XAER_PROTO); - } - _xid = xid; - Future<DtxDemarcationStartResult> future; - try - { - future = _xaSession.getQpidSession() - .dtxDemarcationStart(XidImpl.convertToString(xid), - flag == XAResource.TMJOIN ? Option.JOIN : Option.NO_OPTION, - flag == XAResource.TMRESUME ? Option.RESUME : Option.NO_OPTION); - } - catch (QpidException e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Cannot convert Xid into String format ", e); - } - throw new XAException(XAException.XAER_PROTO); - } - // now wait on the future for the result - DtxDemarcationStartResult result = future.get(); - int status = result.getStatus(); - switch (status) - { - case Constant.XA_OK: - // do nothing this ok - break; - case Constant.XA_RBROLLBACK: - throw new XAException(XAException.XA_RBROLLBACK); - case Constant.XA_RBTIMEOUT: - throw new XAException(XAException.XA_RBTIMEOUT); - default: - // this should not happen - if (_logger.isDebugEnabled()) - { - _logger.debug("got unexpected status value: ", status); - } - throw new XAException(XAException.XAER_PROTO); - } - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/XASessionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/XASessionImpl.java deleted file mode 100644 index 65f57b528c..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/XASessionImpl.java +++ /dev/null @@ -1,126 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms; - -import org.apache.qpidity.QpidException; -import org.apache.qpidity.nclient.DtxSession; - -import javax.jms.XASession; -import javax.jms.Session; -import javax.jms.JMSException; -import javax.jms.TransactionInProgressException; -import javax.transaction.xa.XAResource; - -/** - * This is an implementation of the javax.njms.XASEssion interface. - */ -public class XASessionImpl extends SessionImpl implements XASession -{ - /** - * XAResource associated with this XASession - */ - private final XAResourceImpl _xaResource; - - /** - * This XASession Qpid DtxSession - */ - private DtxSession _qpidDtxSession; - - /** - * The standard session - */ - private Session _jmsSession; - - //-- Constructors - /** - * Create a JMS XASession - * - * @param connection The ConnectionImpl object from which the Session is created. - * @throws QpidException In case of internal error. - */ - protected XASessionImpl(ConnectionImpl connection) throws QpidException - { - super(connection, true, // this is a transacted session - Session.SESSION_TRANSACTED, // the ack mode is transacted - true); // this is an XA session so do not set tx - _qpidDtxSession = getConnection().getQpidConnection().createDTXSession(0); - _xaResource = new XAResourceImpl(this); - } - - //--- javax.njms.XASEssion API - - /** - * Gets the session associated with this XASession. - * - * @return The session object. - * @throws JMSException if an internal error occurs. - */ - public Session getSession() throws JMSException - { - if( _jmsSession == null ) - { - _jmsSession = getConnection().createSession(true, getAcknowledgeMode()); - } - return _jmsSession; - } - - /** - * Returns an XA resource. - * - * @return An XA resource. - */ - public XAResource getXAResource() - { - return _xaResource; - } - - //-- overwritten mehtods - /** - * Throws a {@link TransactionInProgressException}, since it should - * not be called for an XASession object. - * - * @throws TransactionInProgressException always. - */ - public void commit() throws JMSException - { - throw new TransactionInProgressException( - "XASession: A direct invocation of the commit operation is probibited!"); - } - - /** - * Throws a {@link TransactionInProgressException}, since it should - * not be called for an XASession object. - * - * @throws TransactionInProgressException always. - */ - public void rollback() throws JMSException - { - throw new TransactionInProgressException( - "XASession: A direct invocation of the rollback operation is probibited!"); - } - - /** - * Access to the underlying Qpid Session - * - * @return The associated Qpid Session. - */ - protected org.apache.qpidity.nclient.DtxSession getQpidSession() - { - return _qpidDtxSession; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/XATopicConnectionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/XATopicConnectionImpl.java deleted file mode 100644 index d7e56e5af9..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/XATopicConnectionImpl.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.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.XATopicConnection; -import javax.jms.JMSException; -import javax.jms.XATopicSession; - -/** - * implements javax.njms.XATopicConnection - */ -public class XATopicConnectionImpl extends XAConnectionImpl implements XATopicConnection -{ - //-- constructor - /** - * Create a XATopicConnection. - * - * @param host The broker host name. - * @param port The port on which the broker is listening for connection. - * @param virtualHost The virtual host on which the broker is deployed. - * @param username The user name used of user identification. - * @param password The password name used of user identification. - * @throws QpidException If creating a XATopicConnection fails due to some internal error. - */ - public XATopicConnectionImpl(String host, int port, String virtualHost, String username, String password) - throws QpidException - { - super(host, port, virtualHost, username, password); - } - - /** - * Creates an XATopicSession. - * - * @return A newly created XATopicSession. - * @throws JMSException If the XAConnectiono fails to create an XATopicSession due to - * some internal error. - */ - public synchronized XATopicSession createXATopicSession() throws JMSException - { - checkNotClosed(); - XATopicSessionImpl xaTopicSession; - try - { - xaTopicSession = new XATopicSessionImpl(this); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - // add this session with the list of session that are handled by this connection - _sessions.add(xaTopicSession); - return xaTopicSession; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/XATopicSessionImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/XATopicSessionImpl.java deleted file mode 100644 index bf76669470..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/XATopicSessionImpl.java +++ /dev/null @@ -1,63 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms; - -import org.apache.qpidity.QpidException; - -import javax.jms.*; - -/** - * Implements javax.njms.XATopicSession and javax.njms.TopicSession - */ -public class XATopicSessionImpl extends XASessionImpl implements XATopicSession -{ - /** - * The standard session - */ - private TopicSession _jmsTopicSession; - - //-- Constructors - /** - * Create a JMS XASession - * - * @param connection The ConnectionImpl object from which the Session is created. - * @throws org.apache.qpidity.QpidException - * In case of internal error. - */ - protected XATopicSessionImpl(ConnectionImpl connection) throws QpidException - { - super(connection); - } - - //--- interface XATopicSession - - /** - * Gets the topic session associated with this <CODE>XATopicSession</CODE>. - * - * @return the topic session object - * @throws JMSException If an internal error occurs. - */ - public TopicSession getTopicSession() throws JMSException - { - if (_jmsTopicSession == null) - { - _jmsTopicSession = getConnection().createTopicSession(true, getAcknowledgeMode()); - } - return _jmsTopicSession; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/BytesMessageImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/message/BytesMessageImpl.java deleted file mode 100644 index 8a5f910d03..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/BytesMessageImpl.java +++ /dev/null @@ -1,863 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms.message; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.qpidity.QpidException; - -import javax.jms.*; -import java.io.*; -import java.nio.ByteBuffer; - -/** - * Implements javax.njms.BytesMessage - */ -public class BytesMessageImpl extends MessageImpl implements BytesMessage -{ - /** - * this BytesMessageImpl's logger - */ - private static final Logger _logger = LoggerFactory.getLogger(BytesMessageImpl.class); - - /** - * An input stream for reading this message data - * This stream wrappes the received byteBuffer. - */ - protected DataInputStream _dataIn = null; - - /** - * Used to store written data. - */ - protected ByteArrayOutputStream _storedData = new ByteArrayOutputStream(); - - /** - * DataOutputStream used to write the data - */ - protected DataOutputStream _dataOut = new DataOutputStream(_storedData); - - //--- Constructor - /** - * Constructor used by SessionImpl. - */ - public BytesMessageImpl() - { - super(); - setMessageType(String.valueOf(MessageFactory.JAVAX_JMS_BYTESMESSAGE)); - } - - /** - * Constructor used by MessageFactory - * - * @param message The new qpid message. - * @throws QpidException In case of problem when receiving the message body. - */ - protected BytesMessageImpl(org.apache.qpidity.api.Message message) throws QpidException - { - super(message); - } - - //--- BytesMessage API - /** - * Gets the number of bytes of the message body when the message - * is in read-only mode. - * <p> The value returned is the entire length of the message - * body, regardless of where the pointer for reading the message - * is currently located. - * - * @return Number of bytes in the message - * @throws JMSException If reading the message body length fails due to some error. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public long getBodyLength() throws JMSException - { - isReadable(); - return getMessageData().capacity(); - } - - /** - * Reads a boolean. - * - * @return The boolean value read - * @throws JMSException If reading fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public boolean readBoolean() throws JMSException - { - isReadable(); - try - { - return _dataIn.readBoolean(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads a signed 8-bit. - * - * @return The signed 8-bit read - * @throws JMSException If reading a signed 8-bit fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public byte readByte() throws JMSException - { - isReadable(); - try - { - return _dataIn.readByte(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads an unsigned 8-bit. - * - * @return The signed 8-bit read - * @throws JMSException If reading an unsigned 8-bit fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public int readUnsignedByte() throws JMSException - { - isReadable(); - try - { - return _dataIn.readUnsignedByte(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads a short. - * - * @return The short read - * @throws JMSException If reading a short fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public short readShort() throws JMSException - { - isReadable(); - try - { - return _dataIn.readShort(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads an unsigned short. - * - * @return The unsigned short read - * @throws JMSException If reading an unsigned short fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public int readUnsignedShort() throws JMSException - { - isReadable(); - try - { - return _dataIn.readUnsignedShort(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads a char. - * - * @return The char read - * @throws JMSException If reading a char fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public char readChar() throws JMSException - { - isReadable(); - try - { - return _dataIn.readChar(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads an int. - * - * @return The int read - * @throws JMSException If reading an int fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public int readInt() throws JMSException - { - isReadable(); - try - { - return _dataIn.readInt(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads a long. - * - * @return The long read - * @throws JMSException If reading a long fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public long readLong() throws JMSException - { - isReadable(); - try - { - return _dataIn.readLong(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Read a float. - * - * @return The float read - * @throws JMSException If reading a float fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public float readFloat() throws JMSException - { - isReadable(); - try - { - return _dataIn.readFloat(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Read a double. - * - * @return The double read - * @throws JMSException If reading a double fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public double readDouble() throws JMSException - { - isReadable(); - try - { - return _dataIn.readDouble(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads a string that has been encoded using a modified UTF-8 format. - * - * @return The String read - * @throws JMSException If reading a String fails due to some error. - * @throws MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public String readUTF() throws JMSException - { - isReadable(); - try - { - return _dataIn.readUTF(); - } - catch (EOFException e) - { - throw new MessageEOFException("Reach end of data when reading message data"); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads a byte array from the bytes message data. - * <p> JMS sepc says: - * <P>If the length of array <code>bytes</code> is less than the number of - * bytes remaining to be read from the stream, the array should - * be filled. A subsequent call reads the next increment, and so on. - * <P>If the number of bytes remaining in the stream is less than the - * length of - * array <code>bytes</code>, the bytes should be read into the array. - * The return value of the total number of bytes read will be less than - * the length of the array, indicating that there are no more bytes left - * to be read from the stream. The next read of the stream returns -1. - * - * @param b The array into which the data is read. - * @return The total number of bytes read into the buffer, or -1 if - * there is no more data because the end of the stream has been reached - * @throws JMSException If reading a byte array fails due to some error. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public int readBytes(byte[] b) throws JMSException - { - isReadable(); - try - { - return _dataIn.read(b); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Reads a portion of the bytes message data. - * <p> The JMS spec says - * <P>If the length of array <code>b</code> is less than the number of - * bytes remaining to be read from the stream, the array should - * be filled. A subsequent call reads the next increment, and so on. - * <P>If the number of bytes remaining in the stream is less than the - * length of array <code>b</code>, the bytes should be read into the array. - * The return value of the total number of bytes read will be less than - * the length of the array, indicating that there are no more bytes left - * to be read from the stream. The next read of the stream returns -1. - * <p> If <code>length</code> is negative, or - * <code>length</code> is greater than the length of the array - * <code>b</code>, then an <code>IndexOutOfBoundsException</code> is - * thrown. No bytes will be read from the stream for this exception case. - * - * @param b The buffer into which the data is read - * @param length The number of bytes to read; must be less than or equal to length. - * @return The total number of bytes read into the buffer, or -1 if - * there is no more data because the end of the data has been reached - * @throws JMSException If reading a byte array fails due to some error. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - */ - public int readBytes(byte[] b, int length) throws JMSException - { - isReadable(); - try - { - return _dataIn.read(b, 0, length); - } - catch (IOException ioe) - { - throw new JMSException("Problem when reading data", ioe.getLocalizedMessage()); - } - } - - /** - * Writes a boolean to the bytes message. - * - * @param val The boolean value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeBoolean(boolean val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeBoolean(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a byte to the bytes message. - * - * @param val The byte value to be written - * @throws JMSException If writting a byte fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeByte(byte val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeByte(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a short to the bytes message. - * - * @param val The short value to be written - * @throws JMSException If writting a short fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeShort(short val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - - } - - /** - * Writes a char to the bytes message. - * - * @param c The char value to be written - * @throws JMSException If writting a char fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeChar(char c) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeChar(c); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes an int to the bytes message. - * - * @param val The int value to be written - * @throws JMSException If writting an int fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeInt(int val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeInt(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - - } - - /** - * Writes a long to the bytes message. - * - * @param val The long value to be written - * @throws JMSException If writting a long fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeLong(long val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeLong(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a float to the bytes message. - * - * @param val The float value to be written - * @throws JMSException If writting a float fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeFloat(float val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeFloat(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a double to the bytes message. - * - * @param val The double value to be written - * @throws JMSException If writting a double fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeDouble(double val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeDouble(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a string to the bytes message. - * - * @param val The string value to be written - * @throws JMSException If writting a string fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeUTF(String val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeUTF(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - - } - - /** - * Writes a byte array to the bytes message. - * - * @param bytes The byte array value to be written - * @throws JMSException If writting a byte array fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeBytes(byte[] bytes) throws JMSException - { - isWriteable(); - try - { - _dataOut.write(bytes); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a portion of byte array to the bytes message. - * - * @param val The byte array value to be written - * @throws JMSException If writting a byte array fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeBytes(byte[] val, int offset, int length) throws JMSException - { - isWriteable(); - try - { - _dataOut.write(val, offset, length); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes an Object to the bytes message. - * JMS spec says: - * <p>This method works only for the objectified primitive - * object types Integer, Double, Long, String and byte - * arrays. - * - * @param val The short value to be written - * @throws JMSException If writting a short fails due to some error. - * @throws NullPointerException if the parameter val is null. - * @throws MessageFormatException If the object is of an invalid type. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeObject(Object val) throws JMSException - { - if (val == null) - { - throw new NullPointerException("Cannot write null value to message"); - } - if (val instanceof byte[]) - { - writeBytes((byte[]) val); - } - else if (val instanceof String) - { - writeUTF((String) val); - } - else if (val instanceof Boolean) - { - writeBoolean(((Boolean) val).booleanValue()); - } - else if (val instanceof Number) - { - if (val instanceof Byte) - { - writeByte(((Byte) val).byteValue()); - } - else if (val instanceof Short) - { - writeShort(((Short) val).shortValue()); - } - else if (val instanceof Integer) - { - writeInt(((Integer) val).intValue()); - } - else if (val instanceof Long) - { - writeLong(((Long) val).longValue()); - } - else if (val instanceof Float) - { - writeFloat(((Float) val).floatValue()); - } - else if (val instanceof Double) - { - writeDouble(((Double) val).doubleValue()); - } - else - { - throw new MessageFormatException("Trying to write an invalid obejct type: " + val); - } - } - else if (val instanceof Character) - { - writeChar(((Character) val).charValue()); - } - else - { - throw new MessageFormatException("Trying to write an invalid obejct type: " + val); - } - } - - /** - * Puts the message body in read-only mode and repositions the stream of - * bytes to the beginning. - * - * @throws JMSException If resetting the message fails due to some internal error. - * @throws MessageFormatException If the message has an invalid format. - */ - public void reset() throws JMSException - { - _readOnly = true; - if (_dataIn == null) - { - // We were writting on this messsage so now read it - _dataIn = new DataInputStream(new ByteArrayInputStream(_storedData.toByteArray())); - } - else - { - // We were reading so reset it - try - { - _dataIn.reset(); - } - catch (IOException e) - { - if (_logger.isDebugEnabled()) - { - // we log this exception as this should not happen - _logger.debug("Problem when resetting message: ", e); - } - throw new JMSException("Problem when resetting message: " + e.getLocalizedMessage()); - } - } - } - - //-- overwritten methods - /** - * Clear out the message body. Clearing a message's body does not clear - * its header values or property entries. - * <p>If this message body was read-only, calling this method leaves - * the message body is in the same state as an empty body in a newly - * created message. - * - * @throws JMSException If clearing this message body fails to due to some error. - */ - public void clearBody() throws JMSException - { - super.clearBody(); - _dataIn = null; - _storedData = new ByteArrayOutputStream(); - _dataOut = new DataOutputStream(_storedData); - } - - - /** - * This method is invoked before a message dispatch operation. - * - * @throws org.apache.qpidity.QpidException - * If the destination is not set - */ - public void beforeMessageDispatch() throws QpidException - { - if (_dataOut.size() > 0) - { - setMessageData(ByteBuffer.wrap(_storedData.toByteArray())); - } - super.beforeMessageDispatch(); - } - - /** - * This method is invoked after this message is received. - * - * @throws QpidException - */ - @Override - public void afterMessageReceive() throws QpidException - { - super.afterMessageReceive(); - ByteBuffer messageData = getMessageData(); - if (messageData != null) - { - try - { - _dataIn = new DataInputStream(asInputStream()); - } - catch (Exception e) - { - throw new QpidException("Cannot retrieve data from message ", null, e); - } - } - } - - //-- helper mehtods - /** - * Test whether this message is readable by throwing a MessageNotReadableException if this - * message cannot be read. - * - * @throws MessageNotReadableException If this message cannot be read. - */ - protected void isReadable() throws MessageNotReadableException - { - if (_dataIn == null) - { - throw new MessageNotReadableException("Cannot read this message"); - } - } -} - diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/MapMessageImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/message/MapMessageImpl.java deleted file mode 100644 index 26012e63b3..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/MapMessageImpl.java +++ /dev/null @@ -1,628 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms.message; - -import org.apache.qpidity.QpidException; - -import javax.jms.MapMessage; -import javax.jms.JMSException; -import javax.jms.MessageFormatException; -import java.util.Enumeration; -import java.util.Map; -import java.util.HashMap; -import java.util.Vector; -import java.io.*; -import java.nio.ByteBuffer; - -/** - * Implements javax.njms.MapMessage - */ -public class MapMessageImpl extends MessageImpl implements MapMessage -{ - - /** - * The MapMessage's payload. - */ - private Map<String, Object> _map = new HashMap<String, Object>(); - - //--- Constructor - /** - * Constructor used by SessionImpl. - */ - public MapMessageImpl() - { - super(); - setMessageType(String.valueOf(MessageFactory.JAVAX_JMS_MAPMESSAGE)); - } - - /** - * Constructor used by MessageFactory - * - * @param message The new qpid message. - * @throws QpidException In case of IO problem when reading the received message. - */ - protected MapMessageImpl(org.apache.qpidity.api.Message message) throws QpidException - { - super(message); - } - - //-- Map Message API - /** - * Indicates whether an key exists in this MapMessage. - * - * @param key the name of the key to test - * @return true if the key exists - * @throws JMSException If determinein if the key exists fails due to some internal error - */ - public boolean itemExists(String key) throws JMSException - { - return _map.containsKey(key); - } - - /** - * Returns the booleanvalue with the specified key. - * - * @param key The key name. - * @return The boolean value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public boolean getBoolean(String key) throws JMSException - { - boolean result = false; - if (_map.containsKey(key)) - { - try - { - Object objValue = _map.get(key); - if (objValue != null) - { - result = MessageHelper.convertToBoolean(_map.get(key)); - } - } - catch (ClassCastException e) - { - throw new MessageFormatException("Wrong type for key: " + key); - } - } - return result; - } - - /** - * Returns the byte value with the specified name. - * - * @param key The key name. - * @return The byte value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public byte getByte(String key) throws JMSException - { - Object objValue = _map.get(key); - if (objValue == null) - { - throw new NumberFormatException("Wrong type for key: " + key); - } - return MessageHelper.convertToByte(objValue); - } - - /** - * Returns the <CODE>short</CODE> value with the specified name. - * - * @param key The key name. - * @return The <CODE>short</CODE> value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public short getShort(String key) throws JMSException - { - Object objValue = _map.get(key); - if (objValue == null) - { - throw new NumberFormatException("Wrong type for key: " + key); - } - return MessageHelper.convertToShort(objValue); - } - - /** - * Returns the Unicode character value with the specified name. - * - * @param key The key name. - * @return The Unicode charactervalue with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public char getChar(String key) throws JMSException - { - Object objValue = _map.get(key); - if (objValue == null) - { - throw new java.lang.NullPointerException(); - } - return MessageHelper.convertToChar(objValue); - } - - /** - * Returns the intvalue with the specified name. - * - * @param key The key name. - * @return The int value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public int getInt(String key) throws JMSException - { - Object objValue = _map.get(key); - if (objValue == null) - { - throw new NumberFormatException("Wrong type for key: " + key); - } - return MessageHelper.convertToInt(objValue); - } - - /** - * Returns the longvalue with the specified name. - * - * @param key The key name. - * @return The long value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public long getLong(String key) throws JMSException - { - Object objValue = _map.get(key); - if (objValue == null) - { - throw new NumberFormatException("Wrong type for key: " + key); - } - return MessageHelper.convertToLong(objValue); - } - - /** - * Returns the float value with the specified name. - * - * @param key The key name. - * @return The float value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public float getFloat(String key) throws JMSException - { - Object objValue = _map.get(key); - if (objValue == null) - { - throw new NumberFormatException("Wrong type for key: " + key); - } - return MessageHelper.convertToFloat(objValue); - } - - /** - * Returns the double value with the specified name. - * - * @param key The key name. - * @return The double value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public double getDouble(String key) throws JMSException - { - Object objValue = _map.get(key); - if (objValue == null) - { - throw new NumberFormatException("Wrong type for key: " + key); - } - return MessageHelper.convertToDouble(objValue); - } - - /** - * Returns the String value with the specified name. - * - * @param key The key name. - * @return The String value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public String getString(String key) throws JMSException - { - String result = null; - Object objValue = _map.get(key); - if (objValue != null) - { - if (objValue instanceof byte[]) - { - throw new NumberFormatException("Wrong type for key: " + key); - } - else - { - result = objValue.toString(); - } - } - return result; - } - - /** - * Returns the byte array value with the specified name. - * - * @param key The key name. - * @return The byte value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - * @throws javax.jms.MessageFormatException - * If this type conversion is invalid. - */ - public byte[] getBytes(String key) throws JMSException - { - Object objValue = _map.get(key); - if (objValue == null) - { - return null; - } - if (objValue instanceof byte[]) - { - byte[] value = (byte[]) objValue; - byte[] toReturn = new byte[value.length]; - System.arraycopy(value, 0, toReturn, 0, value.length); - return toReturn; - } - throw new MessageFormatException("Wrong type for key: " + key); - } - - /** - * Returns the value of the object with the specified name. - * - * @param key The key name. - * @return The byte value with the specified key. - * @throws JMSException If reading the message fails due to some internal error. - */ - public Object getObject(String key) throws JMSException - { - try - { - Object objValue = _map.get(key); - if (objValue == null) - { - return null; - } - else if (objValue instanceof byte[]) - { - byte[] value = (byte[]) objValue; - byte[] toReturn = new byte[value.length]; - System.arraycopy(value, 0, toReturn, 0, value.length); - return toReturn; - } - else - { - return objValue; - } - } - catch (java.lang.ClassCastException cce) - { - throw new MessageFormatException("Wrong type for key: " + key); - } - } - - /** - * Returns an Enumeration of all the keys - * - * @return an enumeration of all the keys in this MapMessage - * @throws JMSException If reading the message fails due to some internal error. - */ - public Enumeration getMapNames() throws JMSException - { - Vector<String> propVector = new Vector<String>(_map.keySet()); - return propVector.elements(); - } - - /** - * Sets a boolean value with the specified key into the Map. - * - * @param key The key name. - * @param value The boolean value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setBoolean(String key, boolean value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets a byte value with the specified name into the Map. - * - * @param key The key name. - * @param value The byte value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setByte(String key, byte value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets a shortvalue with the specified name into the Map. - * - * @param key The key name. - * @param value The short value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setShort(String key, short value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets a Unicode character value with the specified name into the Map. - * - * @param key The key name. - * @param value The character value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setChar(String key, char value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets an intvalue with the specified name into the Map. - * - * @param key The key name. - * @param value The int value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setInt(String key, int value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets a long value with the specified name into the Map. - * - * @param key The key name. - * @param value The long value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setLong(String key, long value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets a float value with the specified name into the Map. - * - * @param key The key name. - * @param value The float value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setFloat(String key, float value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets a double value with the specified name into the Map. - * - * @param key The key name. - * @param value The double value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setDouble(String key, double value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets a String value with the specified name into the Map. - * - * @param key The key name. - * @param value The String value to set in the Map. - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setString(String key, String value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - _map.put(key, value); - } - - /** - * Sets a byte array value with the specified name into the Map. - * - * @param key the name of the byte array - * @param value the byte array value to set in the Map; the array - * is copied so that the value for <CODE>name</CODE> will - * not be altered by future modifications - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setBytes(String key, byte[] value) throws JMSException, NullPointerException - { - isWriteable(); - checkNotNullKey(key); - byte[] newBytes = new byte[value.length]; - System.arraycopy(value, 0, newBytes, 0, value.length); - _map.put(key, value); - } - - /** - * Sets a portion of the byte array value with the specified name into the - * Map. - * - * @param key the name of the byte array - * @param value the byte array value to set in the Map; the array - * is copied so that the value for <CODE>name</CODE> will - * not be altered by future modifications - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setBytes(String key, byte[] value, int offset, int length) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - byte[] newBytes = new byte[length]; - System.arraycopy(value, offset, newBytes, 0, length); - _map.put(key, newBytes); - } - - /** - * Sets an object value with the specified name into the Map. - * - * @param key the name of the byte array - * @param value the byte array value to set in the Map; the array - * is copied so that the value for <CODE>name</CODE> will - * not be altered by future modifications - * @throws JMSException If writting the message fails due to some internal error. - * @throws IllegalArgumentException If the key is nul or an empty string. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setObject(String key, Object value) throws JMSException, IllegalArgumentException - { - isWriteable(); - checkNotNullKey(key); - if ((value instanceof Boolean) || (value instanceof Byte) || (value instanceof Short) || (value instanceof Integer) || (value instanceof Long) || (value instanceof Character) || (value instanceof Float) || (value instanceof Double) || (value instanceof String) || (value instanceof byte[]) || (value == null)) - { - _map.put(key, value); - } - else - { - throw new MessageFormatException("Cannot set property " + key + " to value " + value + "of type " + value - .getClass().getName() + "."); - } - } - - //-- Overwritten methods - /** - * This method is invoked before this message is dispatched. - */ - @Override - public void beforeMessageDispatch() throws QpidException - { - try - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(_map); - byte[] bytes = baos.toByteArray(); - setMessageData(ByteBuffer.wrap(bytes)); - } - catch (java.io.IOException ioe) - { - throw new QpidException("problem when dispatching message", null, ioe); - } - super.beforeMessageDispatch(); - } - - - /** - * This method is invoked after this message has been received. - */ - @Override - public void afterMessageReceive() throws QpidException - { - super.afterMessageReceive(); - ByteBuffer messageData = getMessageData(); - if (messageData != null) - { - try - { - ObjectInputStream ois = new ObjectInputStream(asInputStream()); - _map = (Map<String, Object>) ois.readObject(); - } - catch (IOException ioe) - { - throw new QpidException( - "Unexpected error during rebuild of message in afterReceive(): " + "- IO Exception", null, ioe); - } - catch (ClassNotFoundException e) - { - throw new QpidException( - "Unexpected error during rebuild of message in afterReceive(): " + "- Could not find the required class in classpath.", - null, e); - } - } - } - - //-- protected methods - /** - * This method throws an <CODE>IllegalArgumentException</CODE> if the supplied parameter is null. - * - * @param key The key to check. - * @throws IllegalArgumentException If the key is null. - */ - private void checkNotNullKey(String key) throws IllegalArgumentException - { - if (key == null || key.equals("")) - { - throw new IllegalArgumentException("Key cannot be null"); - } - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/MessageFactory.java b/java/client/src/main/java/org/apache/qpidity/njms/message/MessageFactory.java deleted file mode 100644 index fa7ebe7d1b..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/MessageFactory.java +++ /dev/null @@ -1,75 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.qpidity.njms.message; - -import org.apache.qpidity.QpidException; - -/** - * A factory for JMS messages - */ -public class MessageFactory -{ - /** - * JMS Message hierarchy. - */ - public static final byte JAVAX_JMS_MESSAGE = 1; - public static final byte JAVAX_JMS_TEXTMESSAGE = 2; - public static final byte JAVAX_JMS_STREAMMESSAGE = 3; - public static final byte JAVAX_JMS_BYTESMESSAGE = 4; - public static final byte JAVAX_JMS_OBJECTMESSAGE = 5; - public static final byte JAVAX_JMS_MAPMESSAGE = 6; - - /** - * Create a QpidMessage subclass according to the JMS message type. - * - * @param message The received qpidity messsage - * @return The newly craeted JMS message - * @throws QpidException If an appropriate Message class cannot be created. - */ - public static QpidMessage getQpidMessage(org.apache.qpidity.api.Message message) throws QpidException - { - QpidMessage result = null; - byte type = Byte.valueOf(message.getMessageProperties().getType()); - switch (type) - { - case JAVAX_JMS_MESSAGE: - result = new MessageImpl(message); - break; - case JAVAX_JMS_TEXTMESSAGE: - result = new TextMessageImpl(message); - break; - case JAVAX_JMS_STREAMMESSAGE: - result = new StreamMessageImpl(message); - break; - case JAVAX_JMS_BYTESMESSAGE: - result = new BytesMessageImpl(message); - break; - case JAVAX_JMS_OBJECTMESSAGE: - result = new ObjectMessageImpl(message); - break; - case JAVAX_JMS_MAPMESSAGE: - result = new MapMessageImpl(message); - break; - default: - throw new QpidException( - "Message type identifier is not mapped " + "to a Message class in the current factory: " + type, - null, null); - } - return result; - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/MessageHelper.java b/java/client/src/main/java/org/apache/qpidity/njms/message/MessageHelper.java deleted file mode 100644 index 0cbe188f6e..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/MessageHelper.java +++ /dev/null @@ -1,456 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms.message; - -import javax.jms.*; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Enumeration; - -/** - * This is an helper class for performing data convertion - */ -public class MessageHelper -{ - /** - * Convert an object into a boolean value - * - * @param obj object that may contain boolean value - * @return A boolean value. - * @throws MessageFormatException If this type conversion is invalid. - */ - public static boolean convertToBoolean(Object obj) throws JMSException - { - boolean result; - if (obj instanceof Boolean) - { - result = (Boolean) obj; - } - else if (obj instanceof String) - { - result = ((String) obj).equalsIgnoreCase("true"); - } - else - { - throw new MessageFormatException("boolean property type convertion error", - "Messasge property type convertion error"); - } - return result; - } - - /** - * Convert an object into a byte value - * - * @param obj The object that may contain byte value - * @return The convertToed byte value. - * @throws MessageFormatException If this type conversion is invalid. - */ - public static byte convertToByte(Object obj) throws JMSException - { - byte result; - if (obj instanceof Byte) - { - result = ((Number) obj).byteValue(); - } - else if (obj instanceof String) - { - result = Byte.parseByte((String) obj); - } - else - { - throw new MessageFormatException("byte property type convertion error", - "Messasge property type convertion error"); - } - return result; - } - - /** - * Convert an object into a short value - * - * @param obj The object that may contain short value - * @return The convertToed short value. - * @throws MessageFormatException If this type conversion is invalid. - */ - public static short convertToShort(Object obj) throws JMSException - { - short result; - if ((obj instanceof Short) || (obj instanceof Byte)) - { - result = ((Number) obj).shortValue(); - } - else if (obj instanceof String) - { - result = Short.parseShort((String) obj); - } - else - { - throw new MessageFormatException("short property type convertion error", - "Messasge property type convertion error"); - } - return result; - } - - /** - * Convert an object into a int value - * - * @param obj The object that may contain int value - * @return The convertToed int value. - * @throws MessageFormatException If this type conversion is invalid. - */ - public static int convertToInt(Object obj) throws JMSException - { - int result; - if ((obj instanceof Integer) || (obj instanceof Byte) || (obj instanceof Short)) - { - result = ((Number) obj).intValue(); - } - else if (obj instanceof String) - { - result = Integer.parseInt((String) obj); - } - else - { - throw new MessageFormatException("int property type convertion error", - "Messasge property type convertion error"); - } - return result; - } - - /** - * Convert an object into a long value - * - * @param obj The object that may contain long value - * @return The convertToed long value. - * @throws MessageFormatException If this type conversion is invalid. - */ - public static long convertToLong(Object obj) throws JMSException - { - long result; - if ((obj instanceof Number) && !((obj instanceof Float) || (obj instanceof Double))) - { - result = ((Number) obj).longValue(); - } - else if (obj instanceof String) - { - - result = Long.parseLong((String) obj); - } - else - { - throw new MessageFormatException("long property type convertion error", - "Messasge property type convertion error"); - } - return result; - } - - /** - * Convert an object into a float value - * - * @param obj The object that may contain float value - * @return The convertToed float value. - * @throws MessageFormatException If this type conversion is invalid. - */ - public static float convertToFloat(Object obj) throws JMSException - { - float result; - if (obj instanceof Float) - { - result = ((Number) obj).floatValue(); - } - else if (obj instanceof String) - { - result = Float.parseFloat((String) obj); - } - else - { - throw new MessageFormatException("float property type convertion error", - "Messasge property type convertion error"); - } - return result; - } - - /** - * Convert an object into a double value - * - * @param obj The object that may contain double value - * @return The convertToed double value. - * @throws MessageFormatException If this type conversion is invalid. - */ - public static double convertToDouble(Object obj) throws JMSException - { - double result; - if ((obj instanceof Double) || (obj instanceof Float)) - { - result = ((Number) obj).doubleValue(); - } - else if (obj instanceof String) - { - result = Double.parseDouble((String) obj); - } - else - { - throw new MessageFormatException("double property type convertion error", - "Messasge property type convertion error"); - } - return result; - } - - /** - * Convert an object into a char value - * - * @param obj The object that may contain char value - * @return The convertToed char value. - * @throws MessageFormatException If this type conversion is invalid. - */ - public static char convertToChar(Object obj) throws JMSException - { - char result; - if (obj instanceof Character) - { - result = (Character) obj; - } - else - { - throw new MessageFormatException("char property type convertion error", - "Messasge property type convertion error"); - } - return result; - } - - /** - * Convert an object into a String value - * - * @param obj The object that may contain String value - * @return The convertToed String value. - */ - public static String convertToString(Object obj) - { - String stringValue; - if (obj instanceof String) - { - stringValue = (String) obj; - } - else - { - stringValue = obj.toString(); - } - return stringValue; - } - - /** - * Check if the passed object represents Java primitive type - * - * @param value object for inspection - * @return true if object represent Java primitive type; false otherwise - */ - public static boolean isPrimitive(Object value) - { - // Innocent till proven guilty - boolean isPrimitive = true; - if (!((value instanceof String) || (value instanceof Boolean) || (value instanceof Character) || ((value instanceof Number) && !((value instanceof BigDecimal) || (value instanceof BigInteger))))) - { - isPrimitive = false; - } - return isPrimitive; - } - - /** - * Transform a foreign message into an equivalent QPID representation. - * - * @param message The foreign message to be converted. - * @return A native message. - * @throws JMSException In case of problem when converting the message. - */ - public static MessageImpl transformMessage(Message message) throws JMSException - { - MessageImpl messageImpl; - - if (message instanceof BytesMessage) - { - messageImpl = transformBytesMessage((BytesMessage) message); - } - else if (message instanceof MapMessage) - { - messageImpl = transformMapMessage((MapMessage) message); - } - else if (message instanceof ObjectMessage) - { - messageImpl = transformObjectMessage((ObjectMessage) message); - } - else if (message instanceof StreamMessage) - { - messageImpl = transformStreamMessage((StreamMessage) message); - } - else if (message instanceof TextMessage) - { - messageImpl = transformTextMessage((TextMessage) message); - } - else - { - messageImpl = new MessageImpl(); - } - transformHeaderAndProperties(message, messageImpl); - return messageImpl; - } - - //---- Private methods - /** - * Exposed JMS defined properties on converted message: - * JMSDestination - we don't set here - * JMSDeliveryMode - we don't set here - * JMSExpiration - we don't set here - * JMSPriority - we don't set here - * JMSMessageID - we don't set here - * JMSTimestamp - we don't set here - * JMSCorrelationID - set - * JMSReplyTo - set - * JMSType - set - * JMSRedlivered - we don't set here - * - * @param message The foreign message to be converted. - * @param nativeMsg A native Qpid message. - * @throws JMSException In case of problem when converting the message. - */ - private static void transformHeaderAndProperties(Message message, MessageImpl nativeMsg) throws JMSException - { - //Set the correlation ID - String correlationID = message.getJMSCorrelationID(); - if (correlationID != null) - { - nativeMsg.setJMSCorrelationID(correlationID); - } - //Set JMS ReplyTo - if (message.getJMSReplyTo() != null) - { - nativeMsg.setJMSReplyTo(message.getJMSReplyTo()); - } - //Set JMS type - String jmsType = message.getJMSType(); - if (jmsType != null) - { - nativeMsg.setJMSType(jmsType); - } - // Sets all non-JMS defined properties on converted message - Enumeration propertyNames = message.getPropertyNames(); - while (propertyNames.hasMoreElements()) - { - String propertyName = String.valueOf(propertyNames.nextElement()); - if (!propertyName.startsWith("JMSX_")) - { - Object value = message.getObjectProperty(propertyName); - nativeMsg.setObjectProperty(propertyName, value); - } - } - } - - /** - * Transform a BytesMessage. - * - * @param bytesMessage a BytesMessage to be converted. - * @return a native BytesMessage. - * @throws JMSException In case of problem when converting the message. - */ - private static BytesMessageImpl transformBytesMessage(BytesMessage bytesMessage) throws JMSException - { - //reset the BytesMessage (makes the body read-only and repositions - // the stream of bytes to the beginning - bytesMessage.reset(); - BytesMessageImpl nativeMsg = new BytesMessageImpl(); - byte[] buf = new byte[1024]; - int len; - while ((len = bytesMessage.readBytes(buf)) != -1) - { - nativeMsg.writeBytes(buf, 0, len); - } - return nativeMsg; - } - - /** - * Transform a MapMessage. - * - * @param mapMessage a MapMessage to be converted. - * @return a native MapMessage. - * @throws JMSException In case of problem when converting the message. - */ - private static MapMessageImpl transformMapMessage(MapMessage mapMessage) throws JMSException - { - MapMessageImpl nativeMsg = new MapMessageImpl(); - Enumeration mapNames = mapMessage.getMapNames(); - while (mapNames.hasMoreElements()) - { - String name = (String) mapNames.nextElement(); - nativeMsg.setObject(name, mapMessage.getObject(name)); - } - return nativeMsg; - } - - /** - * Transform an ObjectMessage. - * - * @param objectMessage a ObjectMessage to be converted. - * @return a native ObjectMessage. - * @throws JMSException In case of problem when converting the message. - */ - private static ObjectMessageImpl transformObjectMessage(ObjectMessage objectMessage) throws JMSException - { - ObjectMessageImpl nativeMsg = new ObjectMessageImpl(); - nativeMsg.setObject(objectMessage.getObject()); - return nativeMsg; - } - - /** - * Transform a StreamMessage. - * - * @param streamMessage a StreamMessage to be converted. - * @return a native StreamMessage. - * @throws JMSException In case of problem when converting the message. - */ - private static StreamMessageImpl transformStreamMessage(StreamMessage streamMessage) throws JMSException - { - StreamMessageImpl nativeMsg = new StreamMessageImpl(); - try - { - //reset the stream message - streamMessage.reset(); - while (true) - { - nativeMsg.writeObject(streamMessage.readObject()); - } - } - catch (MessageEOFException e) - { - // we're at the end so don't mind the exception - } - return nativeMsg; - } - - /** - * Transform a TextMessage. - * - * @param textMessage a TextMessage to be converted. - * @return a native TextMessage. - * @throws JMSException In case of problem when converting the message. - */ - private static TextMessageImpl transformTextMessage(TextMessage textMessage) throws JMSException - { - TextMessageImpl nativeMsg = new TextMessageImpl(); - nativeMsg.setText(textMessage.getText()); - return nativeMsg; - } - -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/MessageImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/message/MessageImpl.java deleted file mode 100644 index a2d974f9ad..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/MessageImpl.java +++ /dev/null @@ -1,1011 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms.message; - -import org.apache.qpidity.njms.ExceptionHelper; -import org.apache.qpidity.njms.MessageConsumerImpl; -import org.apache.qpidity.QpidException; - -import javax.jms.*; -import java.util.Enumeration; -import java.io.InputStream; - -/** - * Implementation of javax.njms.Message - */ -public class MessageImpl extends QpidMessage implements Message -{ - /** - * name used to store JMSType. - */ - private static final String JMS_MESSAGE_TYPE = "JMSType"; - - /** - * The ReplyTo destination for this message - */ - private Destination _replyTo; - - /** - * The destination to which the message has been sent. - * <p>When a message is sent this value is ignored. After completion - * of the send method it holds the destination specified by the send. - * <p>When a message is received, its destination value must be - * equivalent to the value assigned when it was sent. - */ - private Destination _destination; - - /** - * Indicates whether the message properties are in writeable status. - */ - protected boolean _readOnly = false; - - /** - * Indicate whether the message properties are in writeable status. - */ - protected boolean _propertiesReadOnly = false; - - /** - * The message consumer through which this message was received. - */ - private MessageConsumerImpl _messageConsumer; - - //--- Constructor - /** - * Constructor used by SessionImpl. - */ - public MessageImpl() - { - super(); - setMessageType(String.valueOf(MessageFactory.JAVAX_JMS_MESSAGE)); - } - - /** - * Constructor used by MessageFactory - * - * @param message The new qpid message. - * @throws QpidException In case of IO problem when reading the received message. - */ - protected MessageImpl(org.apache.qpidity.api.Message message) throws QpidException - { - super(message); - } - - //---- javax.njms.Message interface - /** - * Get the message ID. - * <p> The JMS sprec says: - * <p>The messageID header field contains a value that uniquely - * identifies each message sent by a provider. - * <p>When a message is sent, messageID can be ignored. When - * the send method returns it contains a provider-assigned value. - * <P>All JMSMessageID values must start with the prefix `ID:'. - * Uniqueness of message ID values across different providers is - * not required. - * - * @return The message ID - * @throws JMSException If getting the message Id fails due to internal error. - */ - public String getJMSMessageID() throws JMSException - { - String messageID = super.getMessageID(); - - if (messageID != null) - { - messageID = "ID:" + messageID; - } - return messageID; - } - - /** - * Set the message ID. - * <p> The JMS spec says: - * <P>Providers set this field when a message is sent. This operation - * can be used to change the value of a message that's been received. - * - * @param messageID The ID of the message - * @throws JMSException If setting the message Id fails due to internal error. - */ - public void setJMSMessageID(String messageID) throws JMSException - { - String qpidmessageID = null; - if (messageID != null) - { - if (messageID.substring(0, 3).equals("ID:")) - { - qpidmessageID = messageID.substring(3, messageID.length()); - } - } - super.setMessageID(qpidmessageID); - } - - /** - * Get the message timestamp. - * <p> The JMS sepc says: - * <P>The JMSTimestamp header field contains the time a message was - * handed off to a provider to be sent. It is not the time the - * message was actually transmitted because the actual send may occur - * later due to transactions or other client side queueing of messages. - * <P>When a message is sent, JMSTimestamp is ignored. When the send - * method returns it contains a a time value somewhere in the interval - * between the call and the return. It is in the format of a normal - * Java millis time value. - * <P>Since timestamps take some effort to create and increase a - * message's size, some JMS providers may be able to optimize message - * overhead if they are given a hint that timestamp is not used by an - * application. JMS message Producers provide a hint to disable - * timestamps. When a client sets a producer to disable timestamps - * they are saying that they do not depend on the value of timestamp - * for the messages it produces. These messages must either have - * timestamp set to null or, if the hint is ignored, timestamp must - * be set to its normal value. - * - * @return the message timestamp - * @throws JMSException If getting the Timestamp fails due to internal error. - */ - public long getJMSTimestamp() throws JMSException - { - return super.getTimestamp(); - } - - /** - * Set the message timestamp. - * <p> The JMS spec says: - * <P>Providers set this field when a message is sent. This operation - * can be used to change the value of a message that's been received. - * - * @param timestamp The timestamp for this message - * @throws JMSException If setting the timestamp fails due to some internal error. - */ - public void setJMSTimestamp(long timestamp) throws JMSException - { - super.setTimestamp(timestamp); - } - - /** - * Get the correlation ID as an array of bytes for the message. - * <p> JMS spec says: - * <P>The use of a byte[] value for JMSCorrelationID is non-portable. - * - * @return the correlation ID of a message as an array of bytes. - * @throws JMSException If getting correlationId fails due to some internal error. - */ - public byte[] getJMSCorrelationIDAsBytes() throws JMSException - { - String correlationID = getJMSCorrelationID(); - if (correlationID != null) - { - return correlationID.getBytes(); - } - return null; - } - - /** - * Set the correlation ID as an array of bytes for the message. - * <p> JMS spec says: - * <P>If a provider supports the native concept of correlation id, a - * JMS client may need to assign specific JMSCorrelationID values to - * match those expected by non-JMS clients. JMS providers without native - * correlation id values are not required to support this (and the - * corresponding get) method; their implementation may throw - * java.lang.UnsupportedOperationException). - * <P>The use of a byte[] value for JMSCorrelationID is non-portable. - * - * @param correlationID The correlation ID value as an array of bytes. - * @throws JMSException If setting correlationId fails due to some internal error. - */ - public void setJMSCorrelationIDAsBytes(byte[] correlationID) throws JMSException - { - setJMSCorrelationID(new String(correlationID)); - } - - /** - * Set the correlation ID for the message. - * <p> JMS spec says: - * <P>A client can use the JMSCorrelationID header field to link one - * message with another. A typically use is to link a response message - * with its request message. - * <P>Since each message sent by a JMS provider is assigned a message ID - * value it is convenient to link messages via message ID. All message ID - * values must start with the `ID:' prefix. - * <P>In some cases, an application (made up of several clients) needs to - * use an application specific value for linking messages. For instance, - * an application may use JMSCorrelationID to hold a value referencing - * some external information. Application specified values must not start - * with the `ID:' prefix; this is reserved for provider-generated message - * ID values. - * - * @param correlationID The message ID of a message being referred to. - * @throws JMSException If setting the correlationId fails due to some internal error. - */ - public void setJMSCorrelationID(String correlationID) throws JMSException - { - super.setCorrelationID(correlationID); - - } - - /** - * Get the correlation ID for the message. - * - * @return The correlation ID of a message as a String. - * @throws JMSException If getting the correlationId fails due to some internal error. - */ - public String getJMSCorrelationID() throws JMSException - { - return super.getCorrelationID(); - } - - /** - * Get where a reply to this message should be sent. - * - * @return The destination where a reply to this message should be sent. - * @throws JMSException If getting the ReplyTo Destination fails due to some internal error. - */ - public Destination getJMSReplyTo() throws JMSException - { - return _replyTo; - } - - /** - * Set where a reply to this message should be sent. - * <p> The JMS spec says: - * <P>The replyTo header field contains the destination where a reply - * to the current message should be sent. If it is null no reply is - * expected. The destination may be either a Queue or a Topic. - * <P>Messages with a null replyTo value are called JMS datagrams. - * Datagrams may be a notification of some change in the sender (i.e. - * they signal a sender event) or they may just be some data the sender - * thinks is of interest. - * <p> Messages with a replyTo value are typically expecting a response. - * A response may be optional, it is up to the client to decide. These - * messages are called JMS requests. A message sent in response to a - * request is called a reply. - * - * @param destination The destination where a reply to this message should be sent. - * @throws JMSException If setting the ReplyTo Destination fails due to some internal error. - */ - public void setJMSReplyTo(Destination destination) throws JMSException - { - _replyTo = destination; - } - - /** - * Get the destination for this message. - * <p> The JMS spec says: - * <p>The destination field contains the destination to which the - * message is being sent. - * <p>When a message is sent this value is ignored. After completion - * of the send method it holds the destination specified by the send. - * <p>When a message is received, its destination value must be - * equivalent to the value assigned when it was sent. - * - * @return The destination of this message. - * @throws JMSException If getting the JMS Destination fails due to some internal error. - */ - public Destination getJMSDestination() throws JMSException - { - return _destination; - } - - /** - * Set the destination for this message. - * <p: JMS spec says: - * <p>Providers set this field when a message is sent. This operation - * can be used to change the value of a message that's been received. - * - * @param destination The destination this message has been sent. - * @throws JMSException If setting the JMS Destination fails due to some internal error. - */ - public void setJMSDestination(Destination destination) throws JMSException - { - _destination = destination; - } - - /** - * Get the delivery mode for this message. - * - * @return the delivery mode of this message. - * @throws JMSException If getting the JMS DeliveryMode fails due to some internal error. - */ - public int getJMSDeliveryMode() throws JMSException - { - int result = DeliveryMode.NON_PERSISTENT; - short amqpDeliveryMode = super.getdeliveryMode(); - if (amqpDeliveryMode == QpidMessage.DELIVERY_MODE_PERSISTENT) - { - result = DeliveryMode.PERSISTENT; - } - else if (amqpDeliveryMode != DELIVERY_MODE_NON_PERSISTENT) - { - throw new JMSException("Problem when accessing message delivery mode"); - } - return result; - } - - /** - * Set the delivery mode for this message. - * <p> The JMS spec says: - * <p>Providers set this field when a message is sent. This operation - * can be used to change the value of a message that's been received. - * - * @param deliveryMode the delivery mode for this message. - * @throws JMSException If setting the JMS DeliveryMode fails due to some internal error. - */ - public void setJMSDeliveryMode(int deliveryMode) throws JMSException - { - short amqpDeliveryMode = DELIVERY_MODE_PERSISTENT; - if (deliveryMode == DeliveryMode.NON_PERSISTENT) - { - amqpDeliveryMode = DELIVERY_MODE_NON_PERSISTENT; - } - else if (deliveryMode != DeliveryMode.PERSISTENT) - { - throw new JMSException( - "Problem when setting message delivery mode, " + deliveryMode + " is not a valid mode"); - } - try - { - super.setDeliveryMode(amqpDeliveryMode); - } - catch (QpidException e) - { - throw ExceptionHelper.convertQpidExceptionToJMSException(e); - } - } - - /** - * Get an indication of whether this message is being redelivered. - * <p> The JMS spec says: - * <p>If a client receives a message with the redelivered indicator set, - * it is likely, but not guaranteed, that this message was delivered to - * the client earlier but the client did not acknowledge its receipt at - * that earlier time. - * - * @return true if this message is being redelivered, false otherwise - * @throws JMSException If getting the JMS Redelivered fails due to some internal error. - */ - public boolean getJMSRedelivered() throws JMSException - { - return super.getRedelivered(); - } - - /** - * Indicate whether this message is being redelivered. - * <p> The JMS spec says: - * <p>This field is set at the time the message is delivered. This - * operation can be used to change the value of a message that's - * been received. - * - * @param redelivered true indicates that the message is being redelivered. - * @throws JMSException If setting the JMS Redelivered fails due to some internal error. - */ - public void setJMSRedelivered(boolean redelivered) throws JMSException - { - super.setRedelivered(redelivered); - } - - /** - * Get the message type. - * <p> The JMS spec says: - * <p>Some JMS providers use a message repository that contains the - * definition of messages sent by applications. The type header field - * contains the name of a message's definition. - * <p>JMS does not define a standard message definition repository nor - * does it define a naming policy for the definitions it contains. JMS - * clients should use symbolic values for type that can be configured - * at installation time to the values defined in the current providers - * message repository. - * <p>JMS clients should assign a value to type whether the application - * makes use of it or not. This insures that it is properly set for - * those providers that require it. - * - * @return The message type - * @throws JMSException If getting the JMS message type fails due to some internal error. - */ - public String getJMSType() throws JMSException - { - return getStringProperty(JMS_MESSAGE_TYPE); - } - - /** - * Set this message type. - * - * @param type The type of message. - * @throws JMSException If setting the JMS message type fails due to some internal error. - */ - public void setJMSType(String type) throws JMSException - { - if (type == null) - { - throw new JMSException("Invalid message type null"); - } - else - { - super.setProperty(JMS_MESSAGE_TYPE, type); - } - } - - /** - * Get the message's expiration value. - * <p> The JMS spec says: - * <p>When a message is sent, expiration is left unassigned. After - * completion of the send method, it holds the expiration time of the - * message. This is the sum of the time-to-live value specified by the - * client and the GMT at the time of the send. - * <p>If the time-to-live is specified as zero, expiration is set to - * zero which indicates the message does not expire. - * - * @return The time the message expires. - * @throws JMSException If getting the JMS message expiration fails due to some internal error. - */ - public long getJMSExpiration() throws JMSException - { - return super.getExpiration(); - } - - /** - * Set the message's expiration value. - * - * @param expiration the message's expiration time - * @throws JMSException If setting the JMS message expiration fails due to some internal error. - */ - public void setJMSExpiration(long expiration) throws JMSException - { - super.setExpiration(expiration); - } - - - /** - * Get the message priority. - * <p> The JMS spec says: - * <p>JMS defines a ten level priority value with 0 as the lowest - * priority and 9 as the highest. In addition, clients should consider - * priorities 0-4 as gradations of normal priority and priorities 5-9 - * as gradations of expedited priority. - * - * @return The message priority. - * @throws JMSException If getting the JMS message priority fails due to some internal error. - */ - public int getJMSPriority() throws JMSException - { - return super.getMessagePriority(); - } - - /** - * Set the priority for this message. - * - * @param priority The priority of this message. - * @throws JMSException If setting the JMS message priority fails due to some internal error. - */ - public void setJMSPriority(int priority) throws JMSException - { - super.setMessagePriority((short) priority); - } - - /** - * Clear the message's properties. - * <p/> - * The message header fields and body are not cleared. - * - * @throws JMSException if clearing JMS message properties fails due to some internal error. - */ - public void clearProperties() throws JMSException - { - // The properties can now be written - // Properties are read only when the message is received. - _propertiesReadOnly = false; - super.clearMessageProperties(); - } - - /** - * Indicates whether a property value exists. - * - * @param name The name of the property to test the existence - * @return True if the property exists, false otherwise. - * @throws JMSException if checking if the property exists fails due to some internal error. - */ - public boolean propertyExists(String name) throws JMSException - { - // Access the property; if the result is null, - // then the property value does not exist - return (super.getProperty(name) != null); - } - - /** - * Access a boolean property value with the given name. - * - * @param name The name of the boolean property. - * @return The boolean property value with the given name. - * @throws JMSException if getting the boolean property fails due to some internal error. - * @throws MessageFormatException If this type conversion is invalid. - */ - public boolean getBooleanProperty(String name) throws JMSException - { - Object booleanProperty = getObjectProperty(name); - return booleanProperty != null && MessageHelper.convertToBoolean(booleanProperty); - } - - /** - * Access a byte property value with the given name. - * - * @param name The name of the byte property. - * @return The byte property value with the given name. - * @throws JMSException if getting the byte property fails due to some internal error. - * @throws MessageFormatException If this type conversion is invalid. - */ - public byte getByteProperty(String name) throws JMSException - { - Object byteProperty = getObjectProperty(name); - if (byteProperty == null) - { - throw new NumberFormatException("Proerty " + name + " is null"); - } - else - { - return MessageHelper.convertToByte(byteProperty); - } - } - - /** - * Access a short property value with the given name. - * - * @param name The name of the short property. - * @return The short property value with the given name. - * @throws JMSException if getting the short property fails due to some internal error. - * @throws MessageFormatException If this type conversion is invalid. - */ - public short getShortProperty(String name) throws JMSException - { - Object shortProperty = getObjectProperty(name); - if (shortProperty == null) - { - throw new NumberFormatException("Proerty " + name + " is null"); - } - else - { - return MessageHelper.convertToShort(shortProperty); - } - } - - /** - * Access a int property value with the given name. - * - * @param name The name of the int property. - * @return The int property value with the given name. - * @throws JMSException if getting the int property fails due to some internal error. - * @throws MessageFormatException If this type conversion is invalid. - */ - public int getIntProperty(String name) throws JMSException - { - Object intProperty = getObjectProperty(name); - if (intProperty == null) - { - throw new NumberFormatException("Proerty " + name + " is null"); - } - else - { - return MessageHelper.convertToInt(intProperty); - } - } - - /** - * Access a long property value with the given name. - * - * @param name The name of the long property. - * @return The long property value with the given name. - * @throws JMSException if getting the long property fails due to some internal error. - * @throws MessageFormatException If this type conversion is invalid. - */ - public long getLongProperty(String name) throws JMSException - { - Object longProperty = getObjectProperty(name); - if (longProperty == null) - { - throw new NumberFormatException("Proerty " + name + " is null"); - } - else - { - return MessageHelper.convertToLong(longProperty); - } - } - - /** - * Access a long property value with the given name. - * - * @param name The name of the long property. - * @return The long property value with the given name. - * @throws JMSException if getting the long property fails due to some internal error. - * @throws MessageFormatException If this type conversion is invalid. - */ - public float getFloatProperty(String name) throws JMSException - { - Object floatProperty = getObjectProperty(name); - if (floatProperty == null) - { - throw new NumberFormatException("Proerty " + name + " is null"); - } - else - { - return MessageHelper.convertToFloat(floatProperty); - } - } - - /** - * Access a double property value with the given name. - * - * @param name The name of the double property. - * @return The double property value with the given name. - * @throws JMSException if getting the double property fails due to some internal error. - * @throws MessageFormatException If this type conversion is invalid. - */ - public double getDoubleProperty(String name) throws JMSException - { - Object doubleProperty = getObjectProperty(name); - if (doubleProperty == null) - { - throw new NumberFormatException("Proerty " + name + " is null"); - } - else - { - return MessageHelper.convertToDouble(doubleProperty); - } - } - - /** - * Access a String property value with the given name. - * - * @param name The name of the String property. - * @return The String property value with the given name. - * @throws JMSException if getting the String property fails due to some internal error. - * @throws MessageFormatException If this type conversion is invalid. - */ - public String getStringProperty(String name) throws JMSException - { - Object stringProperty = getObjectProperty(name); - String result = null; - if (stringProperty != null) - { - result = MessageHelper.convertToString(stringProperty); - } - return result; - } - - /** - * Return the object property value with the given name. - * - * @param name the name of the Java object property - * @return the Java object property value with the given name, in - * objectified format (ie. if it set as an int, then a Integer is - * returned). If there is no property by this name, a null value - * is returned. - * @throws JMSException If getting the object property fails due to some internal error. - */ - public Object getObjectProperty(String name) throws JMSException - { - return super.getProperty(name); - } - - /** - * Get an Enumeration of all the property names. - * - * @return An enumeration of all the names of property values. - * @throws JMSException If getting the property names fails due to some internal JMS error. - */ - public Enumeration getPropertyNames() throws JMSException - { - return super.getAllPropertyNames(); - } - - /** - * Set a boolean property value with the given name. - * - * @param name The name of the boolean property - * @param value The boolean property value to set. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setBooleanProperty(String name, boolean value) throws JMSException - { - setObjectProperty(name, value); - } - - /** - * Set a byte property value with the given name. - * - * @param name The name of the byte property - * @param value The byte property value to set. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setByteProperty(String name, byte value) throws JMSException - { - setObjectProperty(name, value); - } - - /** - * Set a short property value with the given name. - * - * @param name The name of the short property - * @param value The short property value to set. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setShortProperty(String name, short value) throws JMSException - { - setObjectProperty(name, value); - } - - /** - * Set an int property value with the given name. - * - * @param name The name of the int property - * @param value The int property value to set. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setIntProperty(String name, int value) throws JMSException - { - setObjectProperty(name, value); - } - - /** - * Set a long property value with the given name. - * - * @param name The name of the long property - * @param value The long property value to set. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setLongProperty(String name, long value) throws JMSException - { - setObjectProperty(name, value); - } - - /** - * Set a float property value with the given name. - * - * @param name The name of the float property - * @param value The float property value to set. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setFloatProperty(String name, float value) throws JMSException - { - setObjectProperty(name, value); - } - - /** - * Set a double property value with the given name. - * - * @param name The name of the double property - * @param value The double property value to set. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setDoubleProperty(String name, double value) throws JMSException - { - setObjectProperty(name, value); - } - - /** - * Set a string property value with the given name. - * - * @param name The name of the string property - * @param value The string property value to set. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setStringProperty(String name, String value) throws JMSException - { - setObjectProperty(name, value); - } - - /** - * Set a Java object property value with the given name. - * <p> The JMS spec says: - * <p> The setObjectProperty method accepts values of class Boolean, Byte, Short, Integer, - * Long, Float, Double, and String. An attempt to use any other class must throw a JMSException. - * - * @param name the name of the Java object property. - * @param value the Java object property value to set in the Message. - * @throws JMSException If setting the property fails due to some internal JMS error. - * @throws MessageFormatException If the object is invalid - * @throws MessageNotWriteableException If the message properties are read-only. - */ - public void setObjectProperty(String name, Object value) throws JMSException - { - if (_propertiesReadOnly) - { - throw new MessageNotWriteableException("Error the message properties are read only"); - } - if (!(value instanceof String || value instanceof Byte || value instanceof Short || value instanceof Integer || value instanceof Long || value instanceof Float || value instanceof Double || value instanceof Boolean || value == null)) - { - throw new MessageFormatException("Format of object " + value + " is not supported"); - } - super.setProperty(name, value); - } - - /** - * Acknowledgment of a message automatically acknowledges all - * messages previously received by the session. Clients may - * individually acknowledge messages or they may choose to acknowledge - * messages in application defined groups (which is done by acknowledging - * the last received message in the group). - * - * @throws JMSException If this method is called on a closed session. - */ - public void acknowledge() throws JMSException - { - _messageConsumer.getSession().acknowledge(); - } - - /** - * Clear out the message body. Clearing a message's body does not clear - * its header values or property entries. - * <P>If this message body was read-only, calling this method leaves - * the message body in the same state as an empty body in a newly - * created message. - * - * @throws JMSException If clearing this message body fails to due to some error. - */ - public void clearBody() throws JMSException - { - super.clearMessageData(); - _readOnly = false; - } - - //--- Additional public methods - /** - * This method is invoked before a message dispatch operation. - * - * @throws QpidException If the destination is not set - */ - public void beforeMessageDispatch() throws QpidException - { - if (_destination == null) - { - throw new QpidException("Invalid destination null", null, null); - } - super.beforeMessageDispatch(); - } - - /** - * This method is invoked after this message is received. - * - * @throws QpidException If there is an internal error when procesing this message. - */ - @Override - public void afterMessageReceive() throws QpidException - { - // recreate a destination object for the encoded destination - // _destination = // todo - // recreate a destination object for the encoded ReplyTo destination (if it exists) - // _replyTo = // todo - - _propertiesReadOnly = true; - _readOnly = true; - } - - /** - * Test whether this message is readonly by throwing a MessageNotWriteableException if this - * message is readonly - * - * @throws MessageNotWriteableException If this message is readonly - */ - protected void isWriteable() throws MessageNotWriteableException - { - if (_readOnly) - { - throw new MessageNotWriteableException("Cannot update message"); - } - } - - /** - * Set the MessageConsumerImpl through which this message was received. - * <p> This method is called after a message is received. - * - * @param messageConsumer the MessageConsumerImpl reference through which this message was received. - */ - public void setMessageConsumer(MessageConsumerImpl messageConsumer) - { - _messageConsumer = messageConsumer; - } - - /** - * Returns an {@link java.io.InputStream} that reads the data from this mesage buffer. - * {@link java.io.InputStream#read()} returns <tt>-1</tt> if the buffer position - * reaches to the limit. - * - * @return An {@link java.io.InputStream} that reads the data from this mesage buffer. - */ - public InputStream asInputStream() - { - return new InputStream() - { - @Override - public int available() - { - return getMessageData().remaining(); - } - - @Override - public synchronized void mark(int readlimit) - { - getMessageData().mark(); - } - - @Override - public boolean markSupported() - { - return true; - } - - @Override - public int read() - { - if (getMessageData().hasRemaining()) - { - return getMessageData().get() & 0xff; - } - else - { - return -1; - } - } - - @Override - public int read(byte[] b, int off, int len) - { - int remaining = getMessageData().remaining(); - if (remaining > 0) - { - int readBytes = Math.min(remaining, len); - getMessageData().get(b, off, readBytes); - return readBytes; - } - else - { - return -1; - } - } - - @Override - public synchronized void reset() - { - getMessageData().reset(); - } - - @Override - public long skip(long n) - { - int bytes; - if (n > Integer.MAX_VALUE) - { - bytes = getMessageData().remaining(); - } - else - { - bytes = Math.min(getMessageData().remaining(), (int) n); - } - getMessageData().position(getMessageData().position() + bytes); - return bytes; - } - }; - } - - -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/ObjectMessageImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/message/ObjectMessageImpl.java deleted file mode 100644 index 70afddc9a3..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/ObjectMessageImpl.java +++ /dev/null @@ -1,178 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms.message; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.apache.qpidity.QpidException; - -import javax.jms.ObjectMessage; -import javax.jms.JMSException; -import javax.jms.MessageNotWriteableException; -import java.io.*; -import java.nio.ByteBuffer; - -/** - * Implemetns javax.njms.ObjectMessage - */ -public class ObjectMessageImpl extends MessageImpl implements ObjectMessage -{ - - /** - * this ObjectMessageImpl's logger - */ - private static final Logger _logger = LoggerFactory.getLogger(ObjectMessageImpl.class); - - /** - * The ObjectMessage's payload. - */ - private Serializable _object = null; - - //--- Constructor - /** - * Constructor used by SessionImpl. - */ - public ObjectMessageImpl() - { - super(); - setMessageType(String.valueOf(MessageFactory.JAVAX_JMS_OBJECTMESSAGE)); - } - - /** - * Constructor used by MessageFactory - * - * @param message The new qpid message. - * @throws QpidException In case of IO problem when reading the received message. - */ - protected ObjectMessageImpl(org.apache.qpidity.api.Message message) throws QpidException - { - super(message); - } - - //--- Interface ObjctMessage - /** - * Sets the serializable object containing this message's data. - * <p> JE JMS spec says: - * <p> It is important to note that an <CODE>ObjectMessage</CODE> - * contains a snapshot of the object at the time <CODE>setObject()</CODE> - * is called; subsequent modifications of the object will have no - * effect on the <CODE>ObjectMessage</CODE> body. - * - * @param object The message's data - * @throws JMSException If setting the object fails due to some error. - * @throws javax.jms.MessageFormatException - * If object serialization fails. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void setObject(Serializable object) throws JMSException - { - isWriteable(); - try - { - // Serialize the passed in object, then de-serialize it - // so that changes to it do not affect m_data (JAVA's way to perform a deep clone) - ByteArrayOutputStream bOut = new ByteArrayOutputStream(); - ObjectOutputStream objOut = new ObjectOutputStream(bOut); - objOut.writeObject(object); - byte[] bArray = bOut.toByteArray(); - ByteArrayInputStream bIn = new ByteArrayInputStream(bArray); - ObjectInputStream objIn = new ObjectInputStream(bIn); - _object = (Serializable) objIn.readObject(); - objOut.close(); - objIn.close(); - } - catch (Exception e) - { - if (_logger.isDebugEnabled()) - { - _logger.debug("Unexpected exeption when performing object deep clone", e); - } - throw new MessageNotWriteableException("Unexpected exeption when performing object deep clone", - e.getMessage()); - } - } - - /** - * Gets the serializable object containing this message's data. The - * default value is null. - * - * @return The serializable object containing this message's data - * @throws JMSException If getting the object fails due to some internal error. - */ - public Serializable getObject() throws JMSException - { - return _object; - } - - //--- Overwritten methods - /** - * This method is invoked before a message dispatch operation. - * - * @throws org.apache.qpidity.QpidException - * If the destination is not set - */ - public void beforeMessageDispatch() throws QpidException - { - try - { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(_object); - byte[] bytes = baos.toByteArray(); - setMessageData(ByteBuffer.wrap(bytes)); - } - catch (IOException e) - { - throw new QpidException("Problem when setting object of object message", null, e); - } - super.beforeMessageDispatch(); - } - - /** - * This method is invoked after this message is received. - * - * @throws QpidException - */ - @Override - public void afterMessageReceive() throws QpidException - { - super.afterMessageReceive(); - ByteBuffer messageData = getMessageData(); - if (messageData != null) - { - try - { - ObjectInputStream ois = new ObjectInputStream(asInputStream()); - _object = (Serializable) ois.readObject(); - } - catch (IOException ioe) - { - throw new QpidException( - "Unexpected error during rebuild of message in afterReceive() - " + "The Object stored in the message was not a Serializable object.", - null, ioe); - } - catch (ClassNotFoundException clnfe) - { - throw new QpidException( - "Unexpected error during rebuild of message in afterReceive() - " + "Could not find the required class in classpath.", - null, clnfe); - } - } - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/QpidMessage.java b/java/client/src/main/java/org/apache/qpidity/njms/message/QpidMessage.java deleted file mode 100644 index 2426231c15..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/QpidMessage.java +++ /dev/null @@ -1,445 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpidity.njms.message; - -import java.nio.ByteBuffer; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.Map; -import java.util.Vector; -import java.io.IOException; - -import org.apache.qpidity.ErrorCode; -import org.apache.qpidity.QpidException; -import org.apache.qpidity.nclient.util.ByteBufferMessage; -import org.apache.qpidity.transport.ReplyTo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - -public class QpidMessage -{ - /** - * this QpidMessage's logger - */ - private static final Logger _logger = LoggerFactory.getLogger(QpidMessage.class); - - /** - * The underlying qpidity message - */ - private org.apache.qpidity.api.Message _qpidityMessage; - - /** - * This message specific properties. - */ - private Map<String, Object> _messageProperties; - - /** - * This message data - */ - private ByteBuffer _messageData; - - - //--- This is required as AMQP delivery modes are different from the JMS ones - public static final short DELIVERY_MODE_PERSISTENT = 2; - public static final short DELIVERY_MODE_NON_PERSISTENT = 1; - - - //-- Constructors - /** - * Constructor used when JMS messages are created by SessionImpl. - */ - protected QpidMessage() - { - // We us a byteBufferMessage as default - _qpidityMessage = new ByteBufferMessage(); - System.out.println("Creating a bytes message"); - _messageProperties = new HashMap<String, Object>(); - // This is a newly created messsage so the data is empty - _messageData = ByteBuffer.allocate(1024); - } - - /** - * Constructor used when a Qpid message is received - * - * @param message The received message. - * @throws QpidException In case of problem when receiving the message body. - */ - protected QpidMessage(org.apache.qpidity.api.Message message) throws QpidException - { - try - { - _qpidityMessage = message; - _messageProperties = (Map<String, Object>) message.getMessageProperties().getApplicationHeaders(); - _messageData = _qpidityMessage.readData(); - } - catch (IOException ioe) - { - throw new QpidException("IO problem when creating message", ErrorCode.UNDEFINED, ioe); - } - } - - //---- getters and setters. - /** - * Get the message ID. - * - * @return The message ID - */ - public String getMessageID() - { - return _qpidityMessage.getMessageProperties().getMessageId(); - } - - /** - * Set the message ID. - * - * @param messageID The ID of the message - */ - protected void setMessageID(String messageID) - { - _qpidityMessage.getMessageProperties().setMessageId(messageID); - } - - /** - * Get the message timestamp. - * - * @return The message timestamp. - */ - protected long getTimestamp() - { - return _qpidityMessage.getDeliveryProperties().getTimestamp(); - } - - /** - * Set the message timestamp. - * - * @param timestamp the timestamp for this message - */ - protected void setTimestamp(long timestamp) - { - _qpidityMessage.getDeliveryProperties().setTimestamp(timestamp); - } - - /** - * Set the JMS correlation ID - * - * @param correlationID The JMS correlation ID. - */ - protected void setCorrelationID(String correlationID) - { - _qpidityMessage.getMessageProperties().setCorrelationId(correlationID); - } - - /** - * Get the JMS correlation ID - * - * @return The JMS correlation ID - */ - protected String getCorrelationID() - { - return _qpidityMessage.getMessageProperties().getCorrelationId(); - } - - /** - * Get the ReplyTo for this message. - * - * @return The ReplyTo for this message. - */ - protected ReplyTo getReplyTo() - { - return _qpidityMessage.getMessageProperties().getReplyTo(); - } - - /** - * Set the ReplyTo for this message. - * - * @param replyTo The ReplyTo for this message. - */ - protected void setReplyTo(ReplyTo replyTo) - { - _qpidityMessage.getMessageProperties().setReplyTo(replyTo); - } - - /** - * Get this message Delivery mode - * The delivery mode may be non-persistent (1) or persistent (2) - * - * @return the delivery mode of this message. - */ - protected short getdeliveryMode() - { - return _qpidityMessage.getDeliveryProperties().getDeliveryMode(); - } - - /** - * Set the delivery mode for this message. - * - * @param deliveryMode the delivery mode for this message. - * @throws QpidException If the delivery mode is not supported. - */ - protected void setDeliveryMode(short deliveryMode) throws QpidException - { - if (deliveryMode != DELIVERY_MODE_PERSISTENT && deliveryMode != DELIVERY_MODE_NON_PERSISTENT) - { - throw new QpidException( - "Problem when setting message delivery mode, " + deliveryMode + " is not a valid mode", - ErrorCode.UNDEFINED, null); - } - _qpidityMessage.getDeliveryProperties().setDeliveryMode(deliveryMode); - } - - /** - * Get an indication of whether this message is being redelivered. - * - * @return true if this message is redelivered, false otherwise. - */ - protected boolean getRedelivered() - { - return _qpidityMessage.getDeliveryProperties().getRedelivered(); - } - - /** - * Indicate whether this message is being redelivered. - * - * @param redelivered true indicates that the message is being redelivered. - */ - protected void setRedelivered(boolean redelivered) - { - _qpidityMessage.getDeliveryProperties().setRedelivered(redelivered); - } - - /** - * Get this message type. - * - * @return This message type. - */ - protected String getMessageType() - { - return _qpidityMessage.getMessageProperties().getType(); - } - - /** - * Set this message type. - * - * @param type The type of message. - */ - protected void setMessageType(String type) - { - _qpidityMessage.getMessageProperties().setType(type); - } - - /** - * Get the message's expiration value. - * - * @return The message's expiration value. - */ - protected long getExpiration() - { - return _qpidityMessage.getDeliveryProperties().getExpiration(); - } - - /** - * Set the message's expiration value. - * - * @param expiration The message's expiration value. - */ - protected void setExpiration(long expiration) - { - _qpidityMessage.getDeliveryProperties().setExpiration(expiration); - } - - /** - * Get the priority for this message. - * - * @return The priority for this message. - */ - protected short getMessagePriority() - { - return _qpidityMessage.getDeliveryProperties().getPriority(); - } - - /** - * Set the priority for this message. - * - * @param priority The priority for this message. - */ - protected void setMessagePriority(short priority) - { - _qpidityMessage.getDeliveryProperties().setPriority(priority); - } - - /** - * Clear this messasge specific properties. - */ - protected void clearMessageProperties() - { - _messageProperties.clear(); - } - - /** - * Access to a message specific property. - * - * @param name The property to access. - * @return The value associated with this property, mull if the value is null or the property does not exist. - */ - protected Object getProperty(String name) - { - return _messageProperties.get(name); - } - - /** - * Set a property for this message - * - * @param name The name of the property to set. - * @param value The value of the rpoperty. - */ - protected void setProperty(String name, Object value) - { - _messageProperties.put(name, value); - } - - /** - * Get an Enumeration of all the property names - * - * @return An Enumeration of all the property names. - */ - protected Enumeration<String> getAllPropertyNames() - { - Vector<String> vec = new Vector<String>(_messageProperties.keySet()); - return vec.elements(); - } - - /** - * Set this message body - * - * @param messageBody The buffer containing this message data - */ - protected void setMessageData(ByteBuffer messageBody) - { - _messageData = messageBody; // we shouldn't need that .duplicate(); - } - - /** - * Access this messaage data. - * - * @return This message data. - */ - protected ByteBuffer getMessageData() - { - return _messageData; - } - - /** - * Clear this message data - */ - protected void clearMessageData() - { - _messageData = ByteBuffer.allocate(1024); - } - - /** - * Set this message AMQP routingkey - * - * @param routingKey This message AMQP routingkey - */ - public void setRoutingKey(String routingKey) - { - _qpidityMessage.getDeliveryProperties().setRoutingKey(routingKey); - } - - /** - * Set this message AMQP exchange name. - * - * @param exchangeName This message AMQP exchange name. - */ - public void setExchangeName(String exchangeName) - { - _qpidityMessage.getDeliveryProperties().setExchange(exchangeName); - } - - /** - * Get this message excahgne name - * - * @return this message excahgne name - */ - public String getExchangeName() - { - return _qpidityMessage.getDeliveryProperties().getExchange(); - } - - /** - * This method is invoked before a message dispatch operation. - * - * @throws QpidException If the destination is not set - */ - public void beforeMessageDispatch() throws QpidException - { - try - { - // set the message data - _qpidityMessage.clearData(); - if (_logger.isDebugEnabled()) - { - _logger.debug("_messageData POS " + _messageData.position()); - _logger.debug("_messageData limit " + _messageData.limit()); - } - _qpidityMessage.appendData(_messageData); - _qpidityMessage.getMessageProperties().setApplicationHeaders(_messageProperties); - } - catch (IOException e) - { - throw new QpidException("IO exception when sending message", ErrorCode.UNDEFINED, e); - } - } - - /** - * Get the underlying qpidity message - * - * @return The underlying qpidity message. - */ - public org.apache.qpidity.api.Message getQpidityMessage() - { - return _qpidityMessage; - } - - /** - * Get this message transfer ID. - * - * @return This message transfer ID. - */ - public long getMessageTransferId() - { - return _qpidityMessage.getMessageTransferId(); - } - - /** - * This method is invoked after this message is received. - * - * @throws QpidException If there is an internal error when procesing this message. - */ - public void afterMessageReceive() throws QpidException - { - // do nothing for now - } - -} - - diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/StreamMessageImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/message/StreamMessageImpl.java deleted file mode 100644 index 670dddd969..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/StreamMessageImpl.java +++ /dev/null @@ -1,1115 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms.message; - -import org.apache.qpidity.QpidException; - -import javax.jms.*; -import java.io.IOException; -import java.io.EOFException; - -/** - * The JMS spec says: - * StreamMessage objects support the following conversion table. - * The marked cases must be supported. The unmarked cases must throw a JMSException. - * The String-to-primitive conversions may throw a runtime exception if the - * primitive's valueOf() method does not accept it as a valid String representation of the primitive. - * <p> A value written as the row type can be read as the column type. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |boolean | X X - * |byte | X X X X X - * |short | X X X X - * |char | X X - * |int | X X X - * |long | X X - * |float | X X X - * |double | X X - * |String | X X X X X X X X - * |byte[] | X - * |---------------------------------------------------------------------- - */ -public class StreamMessageImpl extends BytesMessageImpl implements StreamMessage -{ - /** - * Those statics represent incoming field types. The type of a field is - * written first in the stream - */ - private static final byte BOOLEAN = 1; - private static final byte BYTE = 2; - private static final byte CHAR = 3; - private static final byte DOUBLE = 4; - private static final byte FLOAT = 5; - private static final byte INT = 6; - private static final byte LONG = 7; - private static final byte SHORT = 8; - private static final byte STRING = 9; - private static final byte BYTEARRAY = 10; - private static final byte NULL = 11; - - /** - * The size of the byteArray written in this stream - */ - private int _sizeOfByteArray = 0; - - //--- Constructor - /** - * Constructor used by SessionImpl. - */ - public StreamMessageImpl() - { - super(); - setMessageType(String.valueOf(MessageFactory.JAVAX_JMS_STREAMMESSAGE)); - } - - /** - * Constructor used by MessageFactory - * - * @param message The new qpid message. - * @throws QpidException In case of problem when receiving the message body. - */ - protected StreamMessageImpl(org.apache.qpidity.api.Message message) throws QpidException - { - super(message); - } - - //--- Interface StreamMessage - /** - * Reads a boolean. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |boolean | X X - * - * @return The boolean value read - * @throws JMSException If reading a boolean fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public boolean readBoolean() throws JMSException - { - isReadableAndNotReadingByteArray(); - boolean result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case BOOLEAN: - result = super.readBoolean(); - break; - case STRING: - int len = _dataIn.readInt(); - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = Boolean.valueOf(new String(bArray)); - break; - case NULL: - result = false; - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads a byte. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |byte | X X - * - * @return The byte value read - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public byte readByte() throws JMSException - { - isReadableAndNotReadingByteArray(); - byte result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case BYTE: - result = super.readByte(); - break; - case STRING: - int len = _dataIn.readInt(); - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = new Byte(new String(bArray)); - break; - case NULL: - result = Byte.valueOf(null); - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads a short. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |short | X X X - * - * @return The short value read - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public short readShort() throws JMSException - { - isReadableAndNotReadingByteArray(); - short result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case SHORT: - result = super.readShort(); - break; - case BYTE: - result = super.readByte(); - break; - case STRING: - int len = _dataIn.readInt(); - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = new Short(new String(bArray)); - break; - case NULL: - result = Short.valueOf(null); - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads a char. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |char | X - * - * @return The char value read - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public char readChar() throws JMSException - { - isReadableAndNotReadingByteArray(); - char result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case CHAR: - result = super.readChar(); - break; - case NULL: - _dataIn.reset(); - throw new NullPointerException(); - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads an Int. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |int | X X X X - * - * @return The int value read - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public int readInt() throws JMSException - { - isReadableAndNotReadingByteArray(); - int result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case INT: - result = super.readInt(); - break; - case SHORT: - result = super.readShort(); - break; - case BYTE: - result = super.readByte(); - break; - case STRING: - int len = _dataIn.readInt(); - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = new Integer(new String(bArray)); - break; - case NULL: - result = Integer.valueOf(null); - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads an Long. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |long | X X X X X - * - * @return The long value read - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public long readLong() throws JMSException - { - isReadableAndNotReadingByteArray(); - long result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case LONG: - result = super.readLong(); - break; - case INT: - result = super.readInt(); - break; - case SHORT: - result = super.readShort(); - break; - case BYTE: - result = super.readByte(); - break; - case STRING: - int len = _dataIn.readInt(); - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = (new Long(new String(bArray))); - break; - case NULL: - result = Long.valueOf(null); - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads an Float. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |float | X X - * - * @return The float value read - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public float readFloat() throws JMSException - { - isReadableAndNotReadingByteArray(); - float result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case FLOAT: - result = super.readFloat(); - break; - case STRING: - int len = _dataIn.readInt(); - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = new Float(new String(bArray)); - break; - case NULL: - result = Float.valueOf(null); - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads an double. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |double | X X X - * - * @return The double value read - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public double readDouble() throws JMSException - { - isReadableAndNotReadingByteArray(); - double result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case DOUBLE: - result = super.readDouble(); - break; - case FLOAT: - result = super.readFloat(); - break; - case STRING: - int len = _dataIn.readInt(); - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = new Double(new String(bArray)); - break; - case NULL: - result = Double.valueOf(null); - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads an string. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |double | X X X X X X X X X - * - * @return The string value read - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public String readString() throws JMSException - { - isReadableAndNotReadingByteArray(); - String result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case BOOLEAN: - result = Boolean.valueOf(super.readBoolean()).toString(); - break; - case BYTE: - result = Byte.valueOf(super.readByte()).toString(); - break; - case SHORT: - result = Short.valueOf(super.readShort()).toString(); - break; - case CHAR: - result = Character.valueOf(super.readChar()).toString(); - break; - case INT: - result = Integer.valueOf(super.readInt()).toString(); - break; - case LONG: - result = Long.valueOf(super.readLong()).toString(); - break; - case FLOAT: - result = Float.valueOf(super.readFloat()).toString(); - break; - case DOUBLE: - result = Double.valueOf(super.readDouble()).toString(); - break; - case STRING: - int len = _dataIn.readInt(); - if (len == 0) - { - throw new NullPointerException("trying to read a null String"); - } - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = new String(bArray); - break; - case NULL: - result = null; - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads an byte[]. - * <p/> - * | | boolean byte short char int long float double String byte[] - * |---------------------------------------------------------------------- - * |byte[] | X - * <p> The JMS spec says: - * To read the field value, readBytes should be successively called until - * it returns a value less than the length - * of the read buffer. The value of the bytes in the buffer following the last byte read is undefined. - * - * @param value The byte array into which the data is read. - * @return the total number of bytes read into the array, or -1 if - * there is no more data because the end of the byte field has been - * reached. - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public int readBytes(byte[] value) throws JMSException - { - isReadable(); - int result = -1; - try - { - byte type = BYTEARRAY; - if (_sizeOfByteArray == 0) - { - // we are not in the middle of reading this byte array - _dataIn.mark(10); - type = _dataIn.readByte(); - } - switch (type) - { - case BYTEARRAY: - if (_sizeOfByteArray == 0) - { - // we need to read the size of this byte array - _sizeOfByteArray = _dataIn.readInt(); - } - result = _dataIn.read(value, 0, value.length); - if (result != -1) - { - _sizeOfByteArray = _sizeOfByteArray - result; - } - else - { - _sizeOfByteArray = 0; - } - case NULL: - // result = -1; - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Reads an object from the stream message. - * <p> The JMS spec says: - * <P>This method can be used to return, in objectified format, - * an object in the Java programming language ("Java object") that has - * been written to the stream with the equivalent - * <CODE>writeObject</CODE> method call, or its equivalent primitive - * <CODE>write<I>type</I></CODE> method. - * <P>An attempt to call <CODE>readObject</CODE> to read a byte field - * value into a new <CODE>byte[]</CODE> object before the full value of the - * byte field has been read will throw a - * <CODE>MessageFormatException</CODE>. - * - * @return A Java object from the stream message, in objectified - * format - * @throws JMSException If reading fails due to some error. - * @throws javax.jms.MessageEOFException If unexpected end of message data has been reached. - * @throws javax.jms.MessageNotReadableException - * If the message is in write-only mode. - * @throws MessageFormatException If this type conversion is invalid. - */ - public Object readObject() throws JMSException - { - isReadableAndNotReadingByteArray(); - Object result; - try - { - _dataIn.mark(10); - byte type = _dataIn.readByte(); - switch (type) - { - case BOOLEAN: - result = super.readBoolean(); - break; - case BYTE: - result = super.readByte(); - break; - case SHORT: - result = super.readShort(); - break; - case CHAR: - result = super.readChar(); - break; - case INT: - result = super.readInt(); - break; - case LONG: - result = super.readLong(); - break; - case FLOAT: - result = super.readFloat(); - break; - case DOUBLE: - result = super.readDouble(); - break; - case STRING: - int len = _dataIn.readInt(); - if (len == 0) - { - result = null; - } - else - { - byte[] bArray = new byte[len]; - _dataIn.readFully(bArray); - result = new String(bArray); - } - break; - case BYTEARRAY: - int totalBytes = _dataIn.readInt(); - byte[] bArray = new byte[totalBytes]; - _dataIn.read(bArray, 0, totalBytes); - result = bArray; - break; - case NULL: - result = null; - break; - default: - _dataIn.reset(); - throw new MessageFormatException("Invalid Object Type"); - } - } - catch (EOFException eof) - { - throw new MessageEOFException("End of file Reached when reading message"); - } - catch (IOException io) - { - throw new JMSException("IO exception when reading message"); - } - return result; - } - - /** - * Writes a boolean to the stream message. - * - * @param val The boolean value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeBoolean(boolean val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(BOOLEAN); - super.writeBoolean(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a byte to the stream message. - * - * @param val The byte value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeByte(byte val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(BYTE); - super.writeByte(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a short to the stream message. - * - * @param val The short value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeShort(short val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(SHORT); - super.writeShort(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a char to the stream message. - * - * @param val The char value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeChar(char val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(CHAR); - super.writeChar(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a int to the stream message. - * - * @param val The int value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeInt(int val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(INT); - super.writeInt(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a long to the stream message. - * - * @param val The long value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeLong(long val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(LONG); - super.writeLong(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a float to the stream message. - * - * @param val The float value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeFloat(float val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(FLOAT); - super.writeFloat(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a double to the stream message. - * - * @param val The double value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeDouble(double val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(DOUBLE); - super.writeDouble(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a string to the stream message. - * - * @param val The string value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeString(String val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(STRING); - if (val == null) - { - _dataOut.writeInt(0); - } - else - { - byte[] bArray = val.getBytes(); - int len = bArray.length; - _dataOut.writeInt(len); - _dataOut.write(bArray); - } - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a byte array to the stream message. - * - * @param val The byte array value to be written - * @throws JMSException If writting a boolean fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeBytes(byte[] val) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(BYTEARRAY); - _dataOut.writeInt(val.length); - super.writeBytes(val); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes a portion of byte array to the bytes message. - * - * @param val The byte array value to be written - * @throws JMSException If writting a byte array fails due to some error. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeBytes(byte[] val, int offset, int length) throws JMSException - { - isWriteable(); - try - { - _dataOut.writeShort(BYTEARRAY); - _dataOut.writeInt(length); - super.writeBytes(val, offset, length); - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - /** - * Writes an Object to the bytes message. - * JMS spec says: - * <p>This method works only for the objectified primitive - * object types Integer, Double, Long, String and byte - * arrays. - * - * @param val The short value to be written - * @throws JMSException If writting a short fails due to some error. - * @throws NullPointerException if the parameter val is null. - * @throws MessageFormatException If the object is of an invalid type. - * @throws javax.jms.MessageNotWriteableException - * If the message is in read-only mode. - */ - public void writeObject(Object val) throws JMSException - { - isWriteable(); - try - { - if (val == null) - { - _dataOut.writeShort(NULL); - } - else if (val instanceof Byte) - { - writeByte((Byte) val); - } - else if (val instanceof Boolean) - { - writeBoolean((Boolean) val); - } - else if (val instanceof Short) - { - writeShort((Short) val); - } - else if (val instanceof Integer) - { - writeInt((Integer) val); - } - else if (val instanceof Long) - { - writeLong((Long) val); - } - else if (val instanceof Double) - { - writeDouble((Double) val); - } - else if (val instanceof Float) - { - writeFloat((Float) val); - } - else if (val instanceof Character) - { - writeChar((Character) val); - } - else if (val instanceof String) - { - writeString((String) val); - } - else if (val instanceof byte[]) - { - writeBytes((byte[]) val); - } - else - { - throw new MessageFormatException( - "The data type of the object specified as the value to writeObject " + "was of an invalid type."); - } - } - catch (IOException e) - { - throw new JMSException("IO problem when writting " + e.getLocalizedMessage()); - } - } - - //-- overwritten methods - /** - * Test whether this message is readable by throwing a MessageNotReadableException if this - * message cannot be read. - * - * @throws javax.jms.MessageNotReadableException - * If this message cannot be read. - * @throws javax.jms.MessageFormatException - * If reading a byte array. - */ - protected void isReadableAndNotReadingByteArray() throws MessageNotReadableException, MessageFormatException - { - if (_dataIn == null) - { - throw new MessageNotReadableException("Cannot read this message"); - } - if (_sizeOfByteArray > 0) - { - throw new MessageFormatException( - "Read of object attempted while incomplete byteArray stored in message " + "- finish reading byte array first."); - } - } -} diff --git a/java/client/src/main/java/org/apache/qpidity/njms/message/TextMessageImpl.java b/java/client/src/main/java/org/apache/qpidity/njms/message/TextMessageImpl.java deleted file mode 100644 index 577b586fe2..0000000000 --- a/java/client/src/main/java/org/apache/qpidity/njms/message/TextMessageImpl.java +++ /dev/null @@ -1,328 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms.message; - -import org.apache.qpidity.QpidException; - -import javax.jms.TextMessage; -import javax.jms.JMSException; -import java.nio.ByteBuffer; -import java.nio.CharBuffer; -import java.nio.charset.*; -import java.io.UnsupportedEncodingException; - -/** - * Implements the interface javax.njms.TextMessage - */ -public class TextMessageImpl extends MessageImpl implements TextMessage -{ - /** - * The character encoding for converting non ASCII characters - * Default UTF-16 - */ - private static final String CHARACTER_ENCODING = "UTF-16"; - - /** - * This message text. The byte form is set when this message is sent - * the text is set when the message is received. - */ - private String _messageText; - - //--- Constructor - /** - * Constructor used by SessionImpl. - */ - public TextMessageImpl() - { - super(); - setMessageType(String.valueOf(MessageFactory.JAVAX_JMS_STREAMMESSAGE)); - } - - /** - * Constructor used by MessageFactory - * - * @param message The new qpid message. - * @throws QpidException In case of IO problem when reading the received message. - */ - protected TextMessageImpl(org.apache.qpidity.api.Message message) throws QpidException - { - super(message); - } - - //--- interface TextMessage - - public String getText() throws JMSException - { - return _messageText; - } - - /** - * Set the text (String) of this TextMessage. - * - * @param text The String containing the text. - * @throws JMSException If setting the text fails due some error. - * @throws javax.jms.MessageNotWriteableException - * If message in read-only mode. - */ - public void setText(String text) throws JMSException - { - isWriteable(); - _messageText = text; - } - - //-- Overwritten methods - - /** - * This method is invoked before this message is dispatched. - * <p>This class uses it to convert its text payload into a ByteBuffer - */ - public void beforeMessageDispatch() throws QpidException - { - if (_messageText != null) - { - // set this message data - try - { - setMessageData(ByteBuffer.wrap(_messageText.getBytes(CHARACTER_ENCODING))); - } - catch (UnsupportedEncodingException e) - { - throw new QpidException("Problem when encoding text " + _messageText, null, e); - } - } - super.beforeMessageDispatch(); - } - - - /** - * This method is invoked after this message has been received. - */ - @Override - public void afterMessageReceive() throws QpidException - { - super.afterMessageReceive(); - ByteBuffer messageData = getMessageData(); - if (messageData != null) - { - try - { - _messageText = getString(); - } - catch (Exception e) - { - throw new QpidException("Problem when decoding text", null, e); - } - } - } - - /** - * Clear out the message body. Clearing a message's body does not clear - * its header values or property entries. - * <P>If this message body was read-only, calling this method leaves - * the message body is in the same state as an empty body in a newly - * created message. - * - * @throws JMSException If clearing this message body fails to due to some error. - */ - public void clearBody() throws JMSException - { - super.clearBody(); - _messageText = null; - } - - /** - * This method is taken from Mina code - * - * Reads a <code>NUL</code>-terminated string from this buffer using the - * specified <code>decoder</code> and returns it. This method reads - * until the limit of this buffer if no <tt>NUL</tt> is found. - * - * @return - * @throws java.nio.charset.CharacterCodingException - * - */ - public String getString() throws CharacterCodingException - { - if (!getMessageData().hasRemaining()) - { - return ""; - } - Charset charset = Charset.forName(CHARACTER_ENCODING); - CharsetDecoder decoder = charset.newDecoder(); - - boolean utf16 = decoder.charset().name().startsWith("UTF-16"); - - int oldPos = getMessageData().position(); - int oldLimit = getMessageData().limit(); - int end = -1; - int newPos; - - if (!utf16) - { - end = indexOf((byte) 0x00); - if (end < 0) - { - newPos = end = oldLimit; - } - else - { - newPos = end + 1; - } - } - else - { - int i = oldPos; - for (; ;) - { - boolean wasZero = getMessageData().get(i) == 0; - i++; - - if (i >= oldLimit) - { - break; - } - - if (getMessageData().get(i) != 0) - { - i++; - if (i >= oldLimit) - { - break; - } - else - { - continue; - } - } - - if (wasZero) - { - end = i - 1; - break; - } - } - - if (end < 0) - { - newPos = end = oldPos + ((oldLimit - oldPos) & 0xFFFFFFFE); - } - else - { - if (end + 2 <= oldLimit) - { - newPos = end + 2; - } - else - { - newPos = end; - } - } - } - - if (oldPos == end) - { - getMessageData().position(newPos); - return ""; - } - - getMessageData().limit(end); - decoder.reset(); - - int expectedLength = (int) (getMessageData().remaining() * decoder.averageCharsPerByte()) + 1; - CharBuffer out = CharBuffer.allocate(expectedLength); - for (; ;) - { - CoderResult cr; - if (getMessageData().hasRemaining()) - { - cr = decoder.decode(getMessageData(), out, true); - } - else - { - cr = decoder.flush(out); - } - - if (cr.isUnderflow()) - { - break; - } - - if (cr.isOverflow()) - { - CharBuffer o = CharBuffer.allocate(out.capacity() + expectedLength); - out.flip(); - o.put(out); - out = o; - continue; - } - - if (cr.isError()) - { - // Revert the buffer back to the previous state. - getMessageData().limit(oldLimit); - getMessageData().position(oldPos); - cr.throwException(); - } - } - - getMessageData().limit(oldLimit); - getMessageData().position(newPos); - return out.flip().toString(); - } - - /** - * Returns the first occurence position of the specified byte from the current position to - * the current limit. - * - * @return <tt>-1</tt> if the specified byte is not found - * @param b - */ - public int indexOf(byte b) - { - if (getMessageData().hasArray()) - { - int arrayOffset = getMessageData().arrayOffset(); - int beginPos = arrayOffset + getMessageData().position(); - int limit = arrayOffset + getMessageData().limit(); - byte[] array = getMessageData().array(); - - for (int i = beginPos; i < limit; i++) - { - if (array[i] == b) - { - return i - arrayOffset; - } - } - } - else - { - int beginPos = getMessageData().position(); - int limit = getMessageData().limit(); - - for (int i = beginPos; i < limit; i++) - { - if (getMessageData().get(i) == b) - { - return i; - } - } - } - return -1; - } -} - diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java index 283db2a95b..216bbedef3 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java @@ -287,7 +287,7 @@ public class RecoverTest extends QpidTestCase con.start(); - long waitTime = 300000L; + long waitTime = 30000L; long waitUntilTime = System.currentTimeMillis() + waitTime; synchronized (lock) diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java index 2535692b5e..4957d700e6 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/close/TopicPublisherCloseTest.java @@ -50,6 +50,9 @@ public class TopicPublisherCloseTest extends QpidTestCase public void testAllMethodsThrowAfterConnectionClose() throws Exception { + // give external brokers a chance to start up + Thread.sleep(3000); + AMQConnection connection = (AMQConnection) getConnection("guest", "guest"); Topic destination1 = new AMQTopic(connection, "t1"); diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java index cae8634f37..495cc98f31 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/transacted/CommitRollbackTest.java @@ -276,7 +276,7 @@ public class CommitRollbackTest extends QpidTestCase _session.commit(); assertNotNull("test message was consumed and rolled back, but is gone", result); assertEquals("test message was correct message", MESSAGE_TEXT, ((TextMessage) result).getText()); - assertTrue("Messasge is not marked as redelivered", result.getJMSRedelivered()); + assertTrue("Message is not marked as redelivered", result.getJMSRedelivered()); } /** @@ -318,7 +318,7 @@ public class CommitRollbackTest extends QpidTestCase _session.commit(); assertNotNull("test message was consumed and rolled back, but is gone", result); assertEquals("test message was correct message", MESSAGE_TEXT, ((TextMessage) result).getText()); - assertTrue("Messasge is not marked as redelivered", result.getJMSRedelivered()); + assertTrue("Message is not marked as redelivered", result.getJMSRedelivered()); } /** @@ -430,7 +430,7 @@ public class CommitRollbackTest extends QpidTestCase _pubSession.commit(); _logger.info("getting test message"); - Message result = _consumer.receive(1000); + Message result = _consumer.receive(5000); assertNotNull("Message received should not be null", result); assertEquals("1", ((TextMessage) result).getText()); @@ -444,39 +444,24 @@ public class CommitRollbackTest extends QpidTestCase _logger.info("receiving result"); -// NOTE: Both msg 1 & 2 will be marked as redelivered as they have both will have been rejected. -// Only the occasion where it is not rejected will it mean it hasn't arrived at the client yet. - result = _consumer.receive(1000); - assertNotNull("test message was consumed and rolled back, but is gone", result); -// The first message back will be either 1 or 2 being redelivered - if (result.getJMSRedelivered()) - { - assertTrue("Messasge is not marked as redelivered" + result, result.getJMSRedelivered()); - } - else // or it will be msg 2 arriving the first time due to latency. - { - _logger.info("Message 2 wasn't prefetched so wasn't rejected"); - assertEquals("2", ((TextMessage) result).getText()); - } + // Message 2 may be marked as redelivered if it was prefetched. + result = _consumer.receive(5000); + assertNotNull("Second message was not consumed, but is gone", result); - result = _consumer.receive(1000); + // The first message back will be 2, message 1 has been received but not committed + // Closing the consumer does not commit the session. - if (isBroker08()) + // if this is message 1 then it should be marked as redelivered + if("1".equals(((TextMessage) result).getText())) { - assertNotNull("test message was consumed and rolled back, but is gone", result); - // assertTrue("Messasge is not marked as redelivered" + result, result.getJMSRedelivered()); - } - else - { - assertNull("test message was consumed and not rolled back, but is redelivered", result); + fail("First message was recieved again"); } result = _consumer.receive(1000); assertNull("test message should be null:" + result, result); _session.commit(); - } public void testPutThenRollbackThenGet() throws Exception diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java index 1339cf9060..d96e8546e2 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java @@ -219,14 +219,7 @@ public class TransactedTest extends QpidTestCase // ensure sent messages are not visible and received messages are requeued expect("RB_A", consumer1.receive(1000), true); expect("RB_B", consumer1.receive(1000), true); - if( isBroker08() ) - { - expect("RB_C", consumer1.receive(1000), true); - } - else - { - expect("RB_C", consumer1.receive(1000), false); - } + expect("RB_C", consumer1.receive(1000), true); _logger.info("Starting new connection"); testCon.start(); testConsumer1 = testSession.createConsumer(queue1); diff --git a/java/common/Composite.tpl b/java/common/Composite.tpl new file mode 100644 index 0000000000..4172ffdefc --- /dev/null +++ b/java/common/Composite.tpl @@ -0,0 +1,173 @@ +package org.apache.qpidity.transport; + +import java.util.ArrayList; +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.network.Frame; + +${ +from genutil import * + +cls = klass(type)["@name"] + +if type.name in ("control", "command"): + base = "Method" + size = 0 + pack = 2 + if type["segments"]: + payload = "true" + else: + payload = "false" + if type.name == "control" and cls == "connection": + track = "Frame.L1" + elif cls == "session" and type["@name"] in ("attach", "attached", "detach", "detached"): + track = "Frame.L2" + elif type.name == "command": + track = "Frame.L4" + else: + track = "Frame.L3" +else: + base = "Struct" + size = type["@size"] + pack = type["@pack"] + payload = "false" + track = "-1" + +typecode = code(type) +} + +public class $name extends $base { + + public static final int TYPE = $typecode; + + public final int getStructType() { + return TYPE; + } + + public final int getSizeWidth() { + return $size; + } + + public final int getPackWidth() { + return $pack; + } + + public final boolean hasPayload() { + return $payload; + } + + public final byte getEncodedTrack() { + return $track; + } + + private static final List<Field<?,?>> FIELDS = new ArrayList<Field<?,?>>(); + public List<Field<?,?>> getFields() { return FIELDS; } + +${ +fields = get_fields(type) +params = get_parameters(fields) +options = get_options(fields) + +for f in fields: + out(" private boolean has_$(f.name);\n") + out(" private $(f.type) $(f.name);\n") +} + +${ +if fields: + out(" public $name() {}\n") +} + + public $name($(", ".join(params))) { +${ +for f in fields: + if f.option: continue + out(" $(f.set)($(f.name));\n") + +for f in options: + out(" boolean _$(f.name) = false;\n") + +if options: + out(""" + for (int i=0; i < _options.length; i++) { + switch (_options[i]) { +""") + + for f in options: + out(" case $(f.option): _$(f.name) = true; break;\n") + + out(""" case NO_OPTION: break; + default: throw new IllegalArgumentException("invalid option: " + _options[i]); + } + } +""") + +for f in options: + out(" $(f.set)(_$(f.name));\n") +} + } + + public <C> void dispatch(C context, MethodDelegate<C> delegate) { + delegate.$(dromedary(name))(context, this); + } + +${ +for f in fields: + out(""" + public final boolean $(f.has)() { + return has_$(f.name); + } + + public final $name $(f.clear)() { + this.has_$(f.name) = false; + this.$(f.name) = $(f.default); + this.dirty = true; + return this; + } + + public final $(f.type) $(f.get)() { + return $(f.name); + } + + public final $name $(f.set)($(f.type) value) { + this.$(f.name) = value; + this.has_$(f.name) = true; + this.dirty = true; + return this; + } + + public final $name $(f.name)($(f.type) value) { + this.$(f.name) = value; + this.has_$(f.name) = true; + this.dirty = true; + return this; + } + + static { + FIELDS.add(new Field<$name,$(jref(jclass(f.type)))>($name.class, $(jref(jclass(f.type))).class, "$(f.name)", $(f.index)) { + public boolean has(Object struct) { + return check(struct).has_$(f.name); + } + public void has(Object struct, boolean value) { + check(struct).has_$(f.name) = value; + } + public $(jref(f.type)) get(Object struct) { + return check(struct).$(f.get)(); + } + public void read(Decoder dec, Object struct) { + check(struct).$(f.name) = $(f.read); + check(struct).dirty = true; + } + public void write(Encoder enc, Object struct) { + $(f.write); + } + }); + } +""") +}} diff --git a/java/common/Constant.tpl b/java/common/Constant.tpl new file mode 100644 index 0000000000..695812ea75 --- /dev/null +++ b/java/common/Constant.tpl @@ -0,0 +1,14 @@ +package org.apache.qpidity.transport; + +${from genutil import *} + +public interface Constant +{ +${ +constants = spec.query["amqp/constant"] + +for c in constants: + name = scream(c["@name"]) + value = c["@value"] + out(" public static final int $name = $value;\n") +}} diff --git a/java/common/Enum.tpl b/java/common/Enum.tpl new file mode 100644 index 0000000000..337feb7065 --- /dev/null +++ b/java/common/Enum.tpl @@ -0,0 +1,36 @@ +package org.apache.qpidity.transport; + +public enum $name { +${ +from genutil import * + +vtype = jtype(resolve_type(type)) + +choices = [(scream(ch["@name"]), "(%s) %s" % (vtype, ch["@value"])) + for ch in type.query["enum/choice"]] +} + $(",\n ".join(["%s(%s)" % ch for ch in choices])); + + private final $vtype value; + + $name($vtype value) + { + this.value = value; + } + + public $vtype getValue() + { + return value; + } + + public static $name get($vtype value) + { + switch (value) + { +${ +for ch, value in choices: + out(' case $value: return $ch;\n') +} default: throw new IllegalArgumentException("no such value: " + value); + } + } +} diff --git a/java/common/Invoker.tpl b/java/common/Invoker.tpl new file mode 100644 index 0000000000..d9905c71a0 --- /dev/null +++ b/java/common/Invoker.tpl @@ -0,0 +1,41 @@ +package org.apache.qpidity.transport; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public abstract class Invoker { + + protected abstract void invoke(Method method); + protected abstract <T> Future<T> invoke(Method method, Class<T> resultClass); + +${ +from genutil import * + +for c in composites: + name = cname(c) + fields = get_fields(c) + params = get_parameters(fields) + args = get_arguments(fields) + result = c["result"] + if result: + if not result["@type"]: + rname = cname(result["struct"]) + else: + rname = cname(result, "@type") + jresult = "Future<%s>" % rname + jreturn = "return " + jclass = ", %s.class" % rname + else: + jresult = "void" + jreturn = "" + jclass = "" + + out(""" + public $jresult $(dromedary(name))($(", ".join(params))) { + $(jreturn)invoke(new $name($(", ".join(args)))$jclass); + } +""") +} + +} diff --git a/java/common/MethodDelegate.tpl b/java/common/MethodDelegate.tpl new file mode 100644 index 0000000000..e5ab1ae1e7 --- /dev/null +++ b/java/common/MethodDelegate.tpl @@ -0,0 +1,12 @@ +package org.apache.qpidity.transport; + +public abstract class MethodDelegate<C> { + +${ +from genutil import * + +for c in composites: + name = cname(c) + out(" public void $(dromedary(name))(C context, $name struct) {}\n") +} +} diff --git a/java/common/Option.tpl b/java/common/Option.tpl new file mode 100644 index 0000000000..5fa2b95b9f --- /dev/null +++ b/java/common/Option.tpl @@ -0,0 +1,19 @@ +package org.apache.qpidity.transport; + +public enum Option { + +${ +from genutil import * + +options = {} + +for c in composites: + for f in c.query["field"]: + t = resolve_type(f) + if t["@name"] == "bit": + option = scream(f["@name"]) + if not options.has_key(option): + options[option] = None + out(" $option,\n")} + NO_OPTION +} diff --git a/java/common/StructFactory.tpl b/java/common/StructFactory.tpl new file mode 100644 index 0000000000..b27621b1d2 --- /dev/null +++ b/java/common/StructFactory.tpl @@ -0,0 +1,39 @@ +package org.apache.qpidity.transport; + +class StructFactory { + + public static Struct create(int type) + { + switch (type) + { +${ +from genutil import * + +fragment = """ case $name.TYPE: + return new $name(); +""" + +for c in composites: + name = cname(c) + if c.name == "struct": + out(fragment) +} default: + throw new IllegalArgumentException("type: " + type); + } + } + + public static Struct createInstruction(int type) + { + switch (type) + { +${ +for c in composites: + name = cname(c) + if c.name in ("command", "control"): + out(fragment) +} default: + throw new IllegalArgumentException("type: " + type); + } + } + +} diff --git a/java/common/Type.tpl b/java/common/Type.tpl new file mode 100644 index 0000000000..c869934538 --- /dev/null +++ b/java/common/Type.tpl @@ -0,0 +1,63 @@ +package org.apache.qpidity.transport; + +${from genutil import *} + +public enum Type +{ + +${ +types = spec.query["amqp/type"] + spec.query["amqp/class/type"] +codes = {} +first = True +for t in types: + code = t["@code"] + fix_width = t["@fixed-width"] + var_width = t["@variable-width"] + + if code is None: + continue + + if fix_width is None: + width = var_width + fixed = "false" + else: + width = fix_width + fixed = "true" + + name = scream(t["@name"]) + codes[code] = name + + if first: + first = False + else: + out(",\n") + + out(" $name((byte) $code, $width, $fixed)") +}; + + public byte code; + public int width; + public boolean fixed; + + Type(byte code, int width, boolean fixed) + { + this.code = code; + this.width = width; + this.fixed = fixed; + } + + public static Type get(byte code) + { + switch (code) + { +${ +keys = list(codes.keys()) +keys.sort() + +for code in keys: + out(" case (byte) $code: return $(codes[code]);\n") +} + default: return null; + } + } +} diff --git a/java/common/build.xml b/java/common/build.xml index 6c8bfbaf0f..796385eff3 100644 --- a/java/common/build.xml +++ b/java/common/build.xml @@ -34,7 +34,7 @@ <target name="check_jython_deps"> <uptodate property="jython.notRequired" targetfile="${jython.timestamp}"> - <srcfiles dir="${xml.spec.dir}" includes="amqp.0-10-preview.xml" /> + <srcfiles dir="${xml.spec.dir}" includes="amqp.0-10-qpid-errata.xml" /> </uptodate> </target> @@ -42,10 +42,9 @@ <java classname="org.python.util.jython" fork="true" failonerror="true"> <arg value="-Dpython.cachedir.skip=true"/> <arg value="-Dpython.path=${basedir}/jython-lib.jar/Lib${path.separator}${mllib.dir}"/> - <arg value="${basedir}/generate"/> + <arg value="${basedir}/codegen"/> <arg value="${module.precompiled}"/> - <arg value="org.apache.qpidity.transport"/> - <arg value="${xml.spec.dir}/amqp.0-10-preview.xml"/> + <arg value="${xml.spec.dir}/amqp.0-10-qpid-errata.xml"/> <classpath> <pathelement location="jython-2.2-rc2.jar"/> </classpath> diff --git a/java/common/codegen b/java/common/codegen new file mode 100755 index 0000000000..f5d1577774 --- /dev/null +++ b/java/common/codegen @@ -0,0 +1,63 @@ +#!/usr/bin/env python + +import os, sys, mllib +from templating import Parser +from genutil import * + +out_dir = sys.argv[1] +spec_file = sys.argv[2] +pkg_dir = os.path.join(out_dir, "org/apache/qpidity/transport") + +if not os.path.exists(pkg_dir): + os.makedirs(pkg_dir) + +spec = mllib.xml_parse(spec_file) + +def excludes(nd): + if (nd.parent is not None and + nd.parent.name == "class" and + nd.parent["@name"] in ("file", "stream")): + return False + else: + return True + +def execute(output, template, **kwargs): + f = open(template) + input = f.read() + f.close() + p = Parser(**kwargs) + p.parse(input) + fname = os.path.join(pkg_dir, output) + f = open(fname, "w") + f.write(p.output) + f.close() + +execute("Type.java", "Type.tpl", spec = spec) +execute("Constant.java", "Constant.tpl", spec = spec) + +structs = spec.query["amqp/struct"] + \ + spec.query["amqp/class/struct", excludes] + \ + spec.query["amqp/class/command/result/struct", excludes] +controls = spec.query["amqp/class/control", excludes] +commands = spec.query["amqp/class/command", excludes] + +composites = structs + controls + commands + +for c in composites: + name = cname(c) + execute("%s.java" % name, "Composite.tpl", type = c, name = name) + +execute("MethodDelegate.java", "MethodDelegate.tpl", composites = composites) +execute("Option.java", "Option.tpl", composites = composites) +execute("Invoker.java", "Invoker.tpl", composites = controls + commands) +execute("StructFactory.java", "StructFactory.tpl", composites = composites) + +def is_enum(nd): + return nd["enum"] is not None + +enums = spec.query["amqp/domain", is_enum] + \ + spec.query["amqp/class/domain", is_enum] + +for e in enums: + name = cname(e) + execute("%s.java" % name, "Enum.tpl", name = name, type = e) diff --git a/java/common/generate b/java/common/generate deleted file mode 100755 index daf8475c54..0000000000 --- a/java/common/generate +++ /dev/null @@ -1,567 +0,0 @@ -#!/usr/bin/python - -# Interim code generation script. - -import sys, os, mllib -from cStringIO import StringIO - -out_dir=sys.argv[1] -out_pkg = sys.argv[2] -spec_file = sys.argv[3] - -spec = mllib.xml_parse(spec_file) - -def jbool(b): - if b: - return "true" - else: - return "false" - -class Output: - - def __init__(self, dir, package, name): - self.dir = dir - self.package = package - self.name = name - self.lines = [] - - self.line("package %s;" % self.package) - self.line() - self.line("import java.util.ArrayList;") - self.line("import java.util.List;") - self.line("import java.util.Map;") - self.line("import java.util.UUID;") - self.line() - self.line("import org.apache.qpidity.transport.codec.Decoder;") - self.line("import org.apache.qpidity.transport.codec.Encodable;") - self.line("import org.apache.qpidity.transport.codec.Encoder;") - self.line() - self.line("import org.apache.qpidity.transport.network.Frame;") - self.line() - self.line() - - def line(self, l = ""): - self.lines.append(l) - - def getter(self, type, method, value, pre = None): - self.line() - self.line(" public final %s %s() {" % (type, method)) - if pre: - self.line(" %s;" % pre) - self.line(" return %s;" % value) - self.line(" }") - - def setter(self, type, method, variable, value = None, pre = None, - post = None): - if value: - params = "" - else: - params = "%s value" % type - value = "value" - - self.line() - self.line(" public final %s %s(%s) {" % (self.name, method, params)) - if pre: - self.line(" %s;" % pre) - self.line(" this.%s = %s;" % (variable, value)) - if post: - self.line(" %s;" % post) - self.line(" return this;") - self.line(" }") - - def write(self): - dir = os.path.join(self.dir, *self.package.split(".")) - if not os.path.exists(dir): - os.makedirs(dir) - file = os.path.join(dir, "%s.java" % self.name) - out = open(file, "w") - for l in self.lines: - out.write(l) - out.write(os.linesep) - out.close() - -TYPES = { - "longstr": "String", - "shortstr": "String", - "longlong": "long", - "long": "long", - "short": "int", - "octet": "short", - "bit": "boolean", - "table": "Map<String,Object>", - "timestamp": "long", - "content": "String", - "uuid": "UUID", - "rfc1982-long-set": "RangeSet", - "long-struct": "Struct", - "signed-byte": "byte", - "unsigned-byte": "short", - "char": "char", - "boolean": "boolean", - "two-octets": "short", - "signed-short": "short", - "unsigned-short": "int", - "four-octets": "int", - "signed-int": "int", - "unsigned-int": "long", - "float": "float", - "utf32-char": "char", - "eight-octets": "long", - "signed-long": "long", - "unsigned-long": "long", - "double": "double", - "datetime": "long", - "sixteen-octets": "byte[]", - "thirty-two-octets": "byte[]", - "sixty-four-octets": "byte[]", - "_128-octets": "byte[]", - "short-binary": "byte[]", - "short-string": "String", - "short-utf8-string": "String", - "short-utf16-string": "String", - "short-utf32-string": "String", - "binary": "byte[]", - "string": "String", - "utf8-string": "String", - "utf16-string": "String", - "utf32-string": "String", - "long-binary": "byte[]", - "long-string": "String", - "long-utf8-string": "String", - "long-utf16-string": "String", - "long-utf32-string": "String", - "sequence": "List<Object>", - "array": "List<Object>", - "five-octets": "byte[]", - "decimal": "byte[]", - "nine-octets": "byte[]", - "long-decimal": "byte[]", - "void": "Void" - } - -DEFAULTS = { - "longlong": "0", - "long": "0", - "short": "0", - "octet": "0", - "timestamp": "0", - "bit": "false" - } - -TRACKS = { - "connection": "Frame.L1", - "session": "Frame.L2", - "execution": "Frame.L3", - None: None - } - -def camel(offset, *args): - parts = [] - for a in args: - parts.extend(a.split("-")) - return "".join(parts[:offset] + [p[0].upper() + p[1:] for p in parts[offset:]]) - -def dromedary(s): - return s[0].lower() + s[1:] - -def scream(*args): - return "_".join([a.replace("-", "_").upper() for a in args]) - - -types = Output(out_dir, out_pkg, "Type") -types.line("public enum Type") -types.line("{") -codes = {} -for c in spec.query["amqp/constant"]: - if c["@class"] == "field-table-type": - name = c["@name"] - if name.startswith("field-table-"): - name = name[12:] - if name[0].isdigit(): - name = "_" + name - val = c["@value"] - codes[val] = name - if c["@width"] != None: - width = c["@width"] - fixed = "true" - if c["@lfwidth"] != None: - width = c["@lfwidth"] - fixed = "false" - types.line(" %s((byte) %s, %s, %s)," % - (scream(name), val, width, fixed)) -types.line(" ;") - -types.line(" public byte code;") -types.line(" public int width;") -types.line(" public boolean fixed;") - -types.line(" Type(byte code, int width, boolean fixed)") -types.line(" {") -for arg in ("code", "width", "fixed"): - types.line(" this.%s = %s;" % (arg, arg)) -types.line(" }") - -types.line(" public static Type get(byte code)") -types.line(" {") -types.line(" switch (code)") -types.line(" {") -for code, name in codes.items(): - types.line(" case (byte) %s: return %s;" % (code, scream(name))) -types.line(" default: return null;") -types.line(" }") -types.line(" }") - -types.line("}") -types.write() - - -const = Output(out_dir, out_pkg, "Constant") -const.line("public interface Constant") -const.line("{") -for d in spec.query["amqp/constant"]: - name = d["@name"] - val = d["@value"] - datatype = d["@datatype"] - if datatype == None: - const.line("public static final int %s = %s;" % (scream(name), val)) -const.line("}") -const.write() - - -DOMAINS = {} -STRUCTS = {} - -for d in spec.query["amqp/domain"]: - name = d["@name"] - type = d["@type"] - if type != None: - DOMAINS[name] = d["@type"] - elif d["struct"] != None: - DOMAINS[name] = name - STRUCTS[name] = camel(0, name) - -def resolve(type): - if DOMAINS.has_key(type) and DOMAINS[type] != type: - return resolve(DOMAINS[type]) - else: - return type - -def jtype(type): - if STRUCTS.has_key(type): - return STRUCTS[type] - else: - return TYPES[type] - -def jclass(jt): - idx = jt.find('<') - if idx > 0: - return jt[:idx] - else: - return jt - -REFS = { - "boolean": "Boolean", - "byte": "Byte", - "short": "Short", - "int": "Integer", - "long": "Long", - "float": "Float", - "double": "Double", - "char": "Character" -} - -def jref(jt): - return REFS.get(jt, jt) - - -OPTIONS = {} - -class Struct: - - def __init__(self, node, name, base, type, size, pack, track, content): - self.node = node - self.name = name - self.base = base - self.type = type - self.size = size - self.pack = pack - self.track = track - self.content = content - self.fields = [] - self.ticket = False - - def result(self): - r = self.node["result"] - if not r: return - name = r["@domain"] - if not name: - name = self.name + "Result" - else: - name = camel(0, name) - return name - - def field(self, type, name): - if name == "ticket": - self.ticket = True - else: - self.fields.append((type, name)) - - def impl(self, out): - out.line("public class %s extends %s {" % (self.name, self.base)) - - out.line() - out.line(" public static final int TYPE = %d;" % self.type) - out.getter("int", "getStructType", "TYPE") - out.getter("int", "getSizeWidth", self.size) - out.getter("int", "getPackWidth", self.pack) - out.getter("boolean", "hasTicket", jbool(self.ticket)) - - if self.base == "Method": - out.getter("boolean", "hasPayload", jbool(self.content)) - out.getter("byte", "getEncodedTrack", self.track) - - out.line() - out.line(" private static final List<Field<?,?>> FIELDS = new ArrayList<Field<?,?>>();") - out.line(" public List<Field<?,?>> getFields() { return FIELDS; }") - out.line() - - out.line() - for type, name in self.fields: - out.line(" private boolean has_%s;" % name) - out.line(" private %s %s;" % (jtype(type), name)) - - if self.fields: - out.line() - out.line(" public %s() {}" % self.name) - - out.line() - out.line(" public %s(%s) {" % (self.name, self.parameters())) - opts = False - for type, name in self.fields: - if not OPTIONS.has_key(name): - out.line(" %s(%s);" % (camel(1, "set", name), name)) - else: - opts = True - if opts: - for type, name in self.fields: - if OPTIONS.has_key(name): - out.line(" boolean _%s = false;" % name) - out.line(" for (int i=0; i < _options.length; i++) {") - out.line(" switch (_options[i]) {") - for type, name in self.fields: - if OPTIONS.has_key(name): - out.line(" case %s: _%s=true; break;" % (OPTIONS[name], name)) - out.line(" case NO_OPTION: break;") - out.line(' default: throw new IllegalArgumentException' - '("invalid option: " + _options[i]);') - out.line(" }") - out.line(" }") - for type, name in self.fields: - if OPTIONS.has_key(name): - out.line(" %s(_%s);" % (camel(1, "set", name), name)) - out.line(" }") - - out.line() - out.line(" public <C> void dispatch(C context, MethodDelegate<C> delegate) {") - out.line(" delegate.%s(context, this);" % dromedary(self.name)) - out.line(" }") - - index = 0 - for type, name in self.fields: - out.getter("boolean", camel(1, "has", name), "has_" + name) - out.setter("boolean", camel(1, "clear", name), "has_" + name, "false", - post = "this.%s = %s; this.dirty = true" % (name, DEFAULTS.get(type, "null"))) - out.getter(jtype(type), camel(1, "get", name), name) - for mname in (camel(1, "set", name), name): - out.setter(jtype(type), mname, name, - post = "this.has_%s = true; this.dirty = true" % name) - - out.line() - out.line(' static {') - ftype = jref(jclass(jtype(type))) - out.line(' FIELDS.add(new Field<%s,%s>(%s.class, %s.class, "%s", %d) {' % - (self.name, ftype, self.name, ftype, name, index)) - out.line(' public boolean has(Object struct) {') - out.line(' return check(struct).has_%s;' % name) - out.line(' }') - out.line(' public void has(Object struct, boolean value) {') - out.line(' check(struct).has_%s = value;' % name) - out.line(' }') - out.line(' public %s get(Object struct) {' % ftype) - out.line(' return check(struct).%s();' % camel(1, "get", name)) - out.line(' }') - out.line(' public void read(Decoder dec, Object struct) {') - if TYPES.has_key(type): - out.line(' check(struct).%s = dec.read%s();' % (name, camel(0, type))) - elif STRUCTS.has_key(type): - out.line(' check(struct).%s = (%s) dec.readStruct(%s.TYPE);' % - (name, STRUCTS[type], STRUCTS[type])) - else: - raise Exception("unknown type: %s" % type) - out.line(' check(struct).dirty = true;') - out.line(' }') - out.line(' public void write(Encoder enc, Object struct) {') - if TYPES.has_key(type): - out.line(' enc.write%s(check(struct).%s);' % (camel(0, type), name)) - elif STRUCTS.has_key(type): - out.line(' enc.writeStruct(%s.TYPE, check(struct).%s);' % - (STRUCTS[type], name)) - else: - raise Exception("unknown type: %s" % type) - out.line(' }') - out.line(' });') - out.line(' }') - index += 1; - - out.line("}") - - - def parameters(self): - params = [] - var = False - for type, name in self.fields: - if OPTIONS.has_key(name): - var = True - else: - params.append("%s %s" % (jtype(type), name)) - if var: - params.append("Option ... _options") - return ", ".join(params) - - def arguments(self): - args = [] - var = False - for type, name in self.fields: - if OPTIONS.has_key(name): - var = True - else: - args.append(name) - if var: - args.append("_options") - return ", ".join(args) - -CLASSES = {"file": False, "basic": False, "stream": False, "tunnel": False} - -PACK_WIDTHS = { - None: 2, - "octet": 1, - "short": 2, - "long": 4 - } - -SIZE_WIDTHS = PACK_WIDTHS.copy() -SIZE_WIDTHS[None] = 0 - -class Visitor(mllib.transforms.Visitor): - - def __init__(self): - self.structs = [] - self.untyped = -1 - - def do_method(self, m): - if CLASSES.get(m.parent["@name"], True): - name = camel(0, m.parent["@name"], m["@name"]) - type = int(m.parent["@index"])*256 + int(m["@index"]) - self.structs.append((name, "Method", type, 0, 2, m)) - self.descend(m) - - def do_domain(self, d): - s = d["struct"] - if s: - name = camel(0, d["@name"]) - st = s["@type"] - if st in (None, "none", ""): - type = self.untyped - self.untyped -= 1 - else: - type = int(st) - self.structs.append((name, "Struct", type, SIZE_WIDTHS[s["@size"]], - PACK_WIDTHS[s["@pack"]], s)) - self.descend(d) - - def do_result(self, r): - s = r["struct"] - if s: - name = camel(0, r.parent.parent["@name"], r.parent["@name"], "Result") - type = int(r.parent.parent["@index"]) * 256 + int(s["@type"]) - self.structs.append((name, "Result", type, SIZE_WIDTHS[s["@size"]], - PACK_WIDTHS[s["@pack"]], s)) - self.descend(r) - -v = Visitor() -spec.dispatch(v) - -opts = Output(out_dir, out_pkg, "Option") -opts.line("public enum Option {") -structs = [] -for name, base, typecode, size, pack, m in v.structs: - struct = Struct(m, name, base, typecode, size, pack, - TRACKS.get(m.parent["@name"], "Frame.L4"), - m["@content"] == "1") - for f in m.query["field"]: - type = resolve(f["@domain"]) - name = camel(1, f["@name"]) - struct.field(type, name) - if type == "bit": - opt_name = scream(f["@name"]) - if not OPTIONS.has_key(name): - OPTIONS[name] = opt_name - opts.line(" %s," % opt_name) - structs.append(struct) -opts.line(" %s," % "NO_OPTION") -opts.line("}") -opts.write() - - - - -for s in structs: - impl = Output(out_dir, out_pkg, s.name) - s.impl(impl) - impl.write() - -fct = Output(out_dir, out_pkg, "StructFactory") -fct.line("class StructFactory {") -fct.line(" public static Struct create(int type) {") -fct.line(" switch (type) {") -for s in structs: - fct.line(" case %s.TYPE:" % s.name) - fct.line(" return new %s();" % s.name) -fct.line(" default:") -fct.line(' throw new IllegalArgumentException("type: " + type);') -fct.line(" }") -fct.line(" }") -fct.line("}"); -fct.write() - -dlg = Output(out_dir, out_pkg, "MethodDelegate") -dlg.line("public abstract class MethodDelegate<C> {") -for s in structs: - dlg.line(" public void %s(C context, %s struct) {}" % - (dromedary(s.name), s.name)) -dlg.line("}") -dlg.write() - -inv = Output(out_dir, out_pkg, "Invoker") -inv.line("public abstract class Invoker {") -inv.line() -inv.line(" protected abstract void invoke(Method method);") -inv.line(" protected abstract <T> Future<T> invoke(Method method, Class<T> resultClass);") -inv.line() -for s in structs: - if s.base != "Method": continue - dname = dromedary(s.name) - result = s.result() - if result: - result_type = "Future<%s>" % result - else: - result_type = "void" - inv.line(" public %s %s(%s) {" % (result_type, dname, s.parameters())) - if result: - inv.line(" return invoke(new %s(%s), %s.class);" % - (s.name, s.arguments(), result)) - else: - inv.line(" invoke(new %s(%s));" % (s.name, s.arguments())) - inv.line(" }") -inv.line("}") -inv.write() diff --git a/java/common/genutil.py b/java/common/genutil.py new file mode 100644 index 0000000000..5206b50bbd --- /dev/null +++ b/java/common/genutil.py @@ -0,0 +1,207 @@ + +def camel(offset, *args): + parts = [] + for a in args: + parts.extend(a.split("-")) + return "".join(parts[:offset] + [p[0].upper() + p[1:] for p in parts[offset:]]) + +def dromedary(s): + return s[0].lower() + s[1:] + +def scream(*args): + return "_".join([a.replace("-", "_").upper() for a in args]) + +def num(x): + if x is not None and x != "": + return int(x, 0) + else: + return None + +def klass(nd): + parent = nd.parent + while parent is not None: + if hasattr(parent, "name") and parent.name == "class": + return parent + parent = parent.parent + +untyped = -1 + +def code(nd): + global untyped + cd = num(nd["@code"]) + if cd is None: + cd = untyped + untyped -= 1 + return cd + + cls = klass(nd) + if cls: + cd |= (num(cls["@code"]) << 8) + return cd + +def root(nd): + if nd.parent is None: + return nd + else: + return root(nd.parent) + +def qname(nd): + name = nd["@name"] + cls = klass(nd) + if cls != None: + return "%s.%s" % (cls["@name"], name) + else: + return name + +def resolve(node, name): + spec = root(node) + cls = klass(node) + if cls: + for nd in cls.query["#tag"]: + if nd["@name"] == name: + return nd + for nd in spec.query["amqp/#tag"] + spec.query["amqp/class/#tag"]: + if name == qname(nd): + return nd + raise Exception("unresolved name: %s" % name) + +def resolve_type(nd): + name = nd["@type"] + type = resolve(nd, name) + if type.name == "domain" and not type["enum"]: + return resolve_type(type) + else: + return type + +TYPES = { + "bit": "boolean", + "uint8": "short", + "uint16": "int", + "uint32": "long", + "uint64": "long", + "datetime": "long", + "uuid": "UUID", + "sequence-no": "int", + "sequence-set": "RangeSet", # XXX + "byte-ranges": "RangeSet", # XXX + "str8": "String", + "str16": "String", + "vbin8": "byte[]", + "vbin16": "byte[]", + "vbin32": "byte[]", + "struct32": "Struct", + "map": "Map<String,Object>", + "array": "List<Object>" + } + +def cname(nd, field="@name"): + cls = klass(nd) + if cls: + if (nd.name in ("struct", "result") and + cls["@name"] != "session" and + nd[field] != "header"): + return camel(0, nd[field]) + else: + return camel(0, cls["@name"], nd[field]) + else: + return camel(0, nd[field]) + +def jtype(nd): + if nd.name == "struct" or nd["enum"]: + return cname(nd) + else: + return TYPES[nd["@name"]] + +REFS = { + "boolean": "Boolean", + "byte": "Byte", + "short": "Short", + "int": "Integer", + "long": "Long", + "float": "Float", + "double": "Double", + "char": "Character" +} + +def jref(jt): + return REFS.get(jt, jt) + +def jclass(jt): + idx = jt.find('<') + if idx > 0: + return jt[:idx] + else: + return jt + +DEFAULTS = { + "long": 0, + "int": 0, + "short": 0, + "byte": 0, + "char": 0, + "boolean": "false" + } + +class Field: + + def __init__(self, index, nd): + self.index = index + self.name = camel(1, nd["@name"]) + type_node = resolve_type(nd) + tname = cname(type_node) + if 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) + elif type_node.name == "domain": + coder = camel(0, resolve_type(type_node)["@name"]) + self.read = "%s.get(dec.read%s())" % (tname, coder) + self.write = "enc.write%s(check(struct).%s.getValue())" % (coder, self.name) + else: + coder = camel(0, type_node["@name"]) + self.read = "dec.read%s()" % coder + self.write = "enc.write%s(check(struct).%s)" % (coder, self.name) + self.type = jtype(type_node) + self.default = DEFAULTS.get(self.type, "null") + self.has = camel(1, "has", self.name) + self.get = camel(1, "get", self.name) + self.set = camel(1, "set", self.name) + self.clear = camel(1, "clear", self.name) + if self.type == "boolean": + self.option = scream(nd["@name"]) + else: + self.option = None + +def get_fields(nd): + fields = [] + index = 0 + for f in nd.query["field"]: + fields.append(Field(index, f)) + index += 1 + return fields + +def get_parameters(fields): + params = [] + options = False + for f in fields: + if f.option: + options = True + else: + params.append("%s %s" % (f.type, f.name)) + if options: + params.append("Option ... _options") + return params + +def get_arguments(fields): + args = [] + options = False + for f in fields: + if f.option: + options = True + else: + args.append(f.name) + if options: + args.append("_options") + return args + +def get_options(fields): + return [f for f in fields if f.option] diff --git a/java/common/src/main/java/org/apache/qpidity/SecurityHelper.java b/java/common/src/main/java/org/apache/qpidity/SecurityHelper.java index d0b3272dec..a72997813a 100644 --- a/java/common/src/main/java/org/apache/qpidity/SecurityHelper.java +++ b/java/common/src/main/java/org/apache/qpidity/SecurityHelper.java @@ -22,6 +22,7 @@ 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; @@ -29,13 +30,12 @@ import org.apache.qpidity.security.CallbackHandlerRegistry; public class SecurityHelper { - public static String chooseMechanism(String mechanisms) throws UnsupportedEncodingException + public static String chooseMechanism(List<Object> mechanisms) throws UnsupportedEncodingException { - StringTokenizer tokenizer = new StringTokenizer(mechanisms, " "); HashSet mechanismSet = new HashSet(); - while (tokenizer.hasMoreTokens()) + for (Object m : mechanisms) { - mechanismSet.add(tokenizer.nextToken()); + mechanismSet.add(m); } String preferredMechanisms = CallbackHandlerRegistry.getInstance().getMechanisms(); diff --git a/java/common/src/main/java/org/apache/qpidity/ToyBroker.java b/java/common/src/main/java/org/apache/qpidity/ToyBroker.java index 2bd97f3aff..5f9917e30a 100644 --- a/java/common/src/main/java/org/apache/qpidity/ToyBroker.java +++ b/java/common/src/main/java/org/apache/qpidity/ToyBroker.java @@ -59,7 +59,7 @@ class ToyBroker extends SessionDelegate public void messageAcquire(Session context, MessageAcquire struct) { System.out.println("\n==================> messageAcquire " ); - context.messageAcquired(struct.getTransfers()); + context.executionResult((int) struct.getId(), new Acquired(struct.getTransfers())); } @Override public void queueDeclare(Session ssn, QueueDeclare qd) @@ -68,16 +68,16 @@ class ToyBroker extends SessionDelegate System.out.println("\n==================> declared queue: " + qd.getQueue() + "\n"); } - @Override public void queueBind(Session ssn, QueueBind qb) + @Override public void exchangeBind(Session ssn, ExchangeBind qb) { - exchange.bindQueue(qb.getExchange(), qb.getRoutingKey(),qb.getQueue()); - System.out.println("\n==================> bound queue: " + qb.getQueue() + " with routing key " + qb.getRoutingKey() + "\n"); + 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(qq.getId(), result); + ssn.executionResult((int) qq.getId(), result); } @Override public void messageSubscribe(Session ssn, MessageSubscribe ms) @@ -112,7 +112,8 @@ class ToyBroker extends SessionDelegate { if (xfr == null || body == null) { - ssn.connectionClose(503, "no method segment", 0, 0); + ssn.connectionClose(ConnectionCloseCode.FRAMING_ERROR, + "no method segment"); ssn.close(); return; } @@ -136,7 +137,7 @@ class ToyBroker extends SessionDelegate { if (xfr == null || body == null) { - ssn.connectionClose(503, "no method segment", 0, 0); + ssn.connectionClose(ConnectionCloseCode.FRAMING_ERROR, "no method segment"); ssn.close(); return; } @@ -174,14 +175,16 @@ class ToyBroker extends SessionDelegate { RangeSet ranges = new RangeSet(); ranges.add(xfr.getId()); - ssn.messageReject(ranges, 0, "no such destination"); + 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, (short)0, (short)0); + ssn.messageTransfer(dest, MessageAcceptMode.EXPLICIT, + MessageAcquireMode.PRE_ACQUIRED); ssn.header(m.header); for (Data d : m.body) { diff --git a/java/common/src/main/java/org/apache/qpidity/ToyClient.java b/java/common/src/main/java/org/apache/qpidity/ToyClient.java index 10b68bbb20..a3233afcbe 100644 --- a/java/common/src/main/java/org/apache/qpidity/ToyClient.java +++ b/java/common/src/main/java/org/apache/qpidity/ToyClient.java @@ -63,7 +63,7 @@ class ToyClient extends SessionDelegate public static final void main(String[] args) { Connection conn = MinaHandler.connect("0.0.0.0", 5672, - new ConnectionDelegate() + new ClientDelegate() { public SessionDelegate getSessionDelegate() { @@ -80,9 +80,9 @@ class ToyClient extends SessionDelegate TransportConstants.getVersionMinor()))); Channel ch = conn.getChannel(0); - Session ssn = new Session(); + Session ssn = new Session("my-session".getBytes()); ssn.attach(ch); - ssn.sessionOpen(1234); + ssn.sessionAttach(ssn.getName()); ssn.queueDeclare("asdf", null, null); ssn.sync(); @@ -111,13 +111,15 @@ class ToyClient extends SessionDelegate 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", (short) 0, (short) 1); + 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", (short) 0, (short) 1); + ssn.messageTransfer("fdsa", MessageAcceptMode.EXPLICIT, + MessageAcquireMode.PRE_ACQUIRED); ssn.data("this should be rejected"); ssn.endData(); ssn.sync(); 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 index 224917ade1..89d7e7917f 100644 --- a/java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java +++ b/java/common/src/main/java/org/apache/qpidity/dtx/XidImpl.java @@ -241,28 +241,10 @@ public class XidImpl implements Xid * @return The String representation of this Xid * @throws QpidException In case of problem when converting this Xid into a string. */ - public static String convertToString(Xid xid) throws QpidException + public static org.apache.qpidity.transport.Xid convert(Xid xid) throws QpidException { - if (_logger.isDebugEnabled()) - { - _logger.debug("converting " + xid + " into a String"); - } - try - { - ByteArrayOutputStream res = new ByteArrayOutputStream(); - DataOutputStream out = new DataOutputStream(res); - out.writeLong(xid.getFormatId()); - byte[] txId = xid.getGlobalTransactionId(); - byte[] brId = xid.getBranchQualifier(); - out.writeByte(txId.length); - out.writeByte(brId.length); - out.write(txId); - out.write(brId); - return res.toString(); - } - catch (IOException e) - { - throw new QpidException("cannot convert the xid " + xid + " into a String", null, e); - } + return new org.apache.qpidity.transport.Xid(xid.getFormatId(), + xid.getGlobalTransactionId(), + xid.getBranchQualifier()); } } 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 index 7327697088..651402bcb7 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/Channel.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/Channel.java @@ -77,7 +77,7 @@ public class Channel extends Invoker connection.getConnectionDelegate().init(this, hdr); } - public void method(Void v, Method method) + public void control(Void v, Method method) { switch (method.getEncodedTrack()) { @@ -90,15 +90,17 @@ public class Channel extends Invoker case L3: method.delegate(session, sessionDelegate); break; - case L4: - 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); 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 index 84621fbe25..7f4365f515 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/ChannelDelegate.java @@ -32,15 +32,14 @@ import java.util.UUID; class ChannelDelegate extends MethodDelegate<Channel> { - public @Override void sessionOpen(Channel channel, SessionOpen open) + public @Override void sessionAttach(Channel channel, SessionAttach atch) { - Session ssn = new Session(); + Session ssn = new Session(atch.getName()); ssn.attach(channel); - long lifetime = open.getDetachedLifetime(); - ssn.sessionAttached(UUID.randomUUID(), lifetime); + ssn.sessionAttached(ssn.getName()); } - public @Override void sessionClosed(Channel channel, SessionClosed closed) + public @Override void sessionDetached(Channel channel, SessionDetached closed) { channel.getSession().closed(); // XXX: should we remove the channel from the connection? It diff --git a/java/client/src/main/java/org/apache/qpidity/njms/TopicConnectionImpl.java b/java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java index 4174c6a5d5..699854fb3b 100644 --- a/java/client/src/main/java/org/apache/qpidity/njms/TopicConnectionImpl.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/ClientDelegate.java @@ -1,35 +1,41 @@ -/* Licensed to the Apache Software Foundation (ASF) under one +/* + * + * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.njms; +package org.apache.qpidity.transport; -import org.apache.qpidity.QpidException; - -import javax.jms.TopicConnection; /** - * Implements javax.njms.TopicConnection + * ClientDelegate + * */ -public class TopicConnectionImpl extends ConnectionImpl implements TopicConnection + +public abstract class ClientDelegate extends ConnectionDelegate { - //-- constructor - public TopicConnectionImpl(String host, int port, String virtualHost, String username, String password) - throws QpidException + + public void init(Channel ch, ProtocolHeader hdr) { - super(host, port, virtualHost, username, password); + 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/ConnectionDelegate.java b/java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java index 4815f1025f..cb5f05a185 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/ConnectionDelegate.java @@ -26,7 +26,10 @@ 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; @@ -79,17 +82,27 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel> public void init(Channel ch, ProtocolHeader hdr) { - // XXX: hardcoded version - if (hdr.getMajor() != 0 && hdr.getMinor() != 10) + 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().send(new ConnectionEvent(0, new ProtocolHeader + (1, + TransportConstants.getVersionMajor(), + TransportConstants.getVersionMinor()))); ch.getConnection().close(); } else { - ch.connectionStart(hdr.getMajor(), hdr.getMinor(), null, "PLAIN", "utf8"); + List<Object> plain = new ArrayList<Object>(); + plain.add("PLAIN"); + List<Object> utf8 = new ArrayList<Object>(); + utf8.add("utf8"); + ch.connectionStart(null, plain, utf8); } } @@ -99,13 +112,13 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel> @Override public void connectionStart(Channel context, ConnectionStart struct) { String mechanism = null; - String response = 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 = new String(saslClient.evaluateChallenge(new byte[0]),_locale); + response = saslClient.evaluateChallenge(new byte[0]); } catch (UnsupportedEncodingException e) { @@ -128,13 +141,9 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel> { try { - String response = new String(saslClient.evaluateChallenge(struct.getChallenge().getBytes()),_locale); + byte[] response = saslClient.evaluateChallenge(struct.getChallenge()); context.connectionSecureOk(response); } - catch (UnsupportedEncodingException e) - { - // need error handling - } catch (SaslException e) { // need error handling @@ -144,14 +153,14 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel> @Override public void connectionTune(Channel context, ConnectionTune struct) { // should update the channel max given by the broker. - context.connectionTuneOk(struct.getChannelMax(), struct.getFrameMax(), struct.getHeartbeat()); + context.connectionTuneOk(struct.getChannelMax(), struct.getMaxFrameSize(), struct.getHeartbeatMax()); context.connectionOpen(_virtualHost, null, Option.INSIST); } @Override public void connectionOpenOk(Channel context, ConnectionOpenOk struct) { - String knownHosts = struct.getKnownHosts(); + List<Object> knownHosts = struct.getKnownHosts(); if(_negotiationCompleteLock != null) { _negotiationCompleteLock.lock(); @@ -187,13 +196,13 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel> byte[] challenge = null; if ( challenge == null) { - context.connectionTune(Integer.MAX_VALUE,maxFrame, 0); + context.connectionTune(Integer.MAX_VALUE, maxFrame, 0, Integer.MAX_VALUE); } else { try { - context.connectionSecure(new String(challenge,_locale)); + context.connectionSecure(challenge); } catch(Exception e) { @@ -218,16 +227,16 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel> try { saslServer = Sasl.createSaslServer(_mechanism, "AMQP", "ABC",new HashMap(),SecurityHelper.createCallbackHandler(_mechanism,_username,_password)); - byte[] challenge = saslServer.evaluateResponse(struct.getResponse().getBytes()); + byte[] challenge = saslServer.evaluateResponse(struct.getResponse()); if ( challenge == null) { - context.connectionTune(Integer.MAX_VALUE,maxFrame, 0); + context.connectionTune(Integer.MAX_VALUE, maxFrame, 0, Integer.MAX_VALUE); } else { try { - context.connectionSecure(new String(challenge,_locale)); + context.connectionSecure(challenge); } catch(Exception e) { @@ -250,8 +259,9 @@ public abstract class ConnectionDelegate extends MethodDelegate<Channel> @Override public void connectionOpen(Channel context, ConnectionOpen struct) { - String hosts = "amqp:1223243232325"; - context.connectionOpenOk(hosts); + List<Object> hosts = new ArrayList<Object>(); + hosts.add("amqp:1223243232325"); + context.connectionOpenOk(hosts); } public String getPassword() 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 index b9b8636d18..72c1c3331d 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/Data.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/Data.java @@ -93,7 +93,7 @@ public class Data implements ProtocolEvent { str.append(" | "); } - str.append(str(buf, 20)); + str.append(str(buf)); } 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 index 7304260333..bc4ec6289d 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/Method.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/Method.java @@ -20,6 +20,7 @@ */ package org.apache.qpidity.transport; +import org.apache.qpidity.transport.network.Frame; /** * Method @@ -34,11 +35,12 @@ public abstract class Method extends Struct implements ProtocolEvent { // XXX: should generate separate factories for separate // namespaces - return (Method) Struct.create(type); + return (Method) StructFactory.createInstruction(type); } // XXX: command subclass? private long id; + private boolean sync = false; public final long getId() { @@ -50,6 +52,16 @@ public abstract class Method extends Struct implements ProtocolEvent this.id = id; } + public final boolean isSync() + { + return sync; + } + + void setSync(boolean value) + { + this.sync = value; + } + public abstract boolean hasPayload(); public abstract byte getEncodedTrack(); @@ -58,7 +70,14 @@ public abstract class Method extends Struct implements ProtocolEvent public <C> void delegate(C context, ProtocolDelegate<C> delegate) { - delegate.method(context, this); + if (getEncodedTrack() == Frame.L4) + { + delegate.command(context, this); + } + else + { + delegate.control(context, this); + } } } 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 index 6149c3876a..028d570416 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/ProtocolDelegate.java @@ -31,7 +31,9 @@ public interface ProtocolDelegate<C> void init(C context, ProtocolHeader header); - void method(C context, Method method); + void control(C context, Method control); + + void command(C context, Method command); void header(C context, Header header); 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 index 97d4be0d2e..ccbcfa99d0 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/RangeSet.java @@ -98,6 +98,13 @@ public class RangeSet implements Iterable<Range> ranges.clear(); } + public RangeSet copy() + { + RangeSet copy = new RangeSet(); + copy.ranges.addAll(ranges); + return copy; + } + public String toString() { StringBuffer str = new StringBuffer(); 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 index e4f4af95a5..f6f4062c6d 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/Session.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/Session.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; +import static org.apache.qpidity.transport.Option.*; /** * Session @@ -56,23 +57,34 @@ public class Session extends Invoker private static boolean ENABLE_REPLAY = false; private static final Logger log = Logger.get(Session.class); + private byte[] name; + private long timeout = 60000; + // channel may be null Channel channel; // incoming command count - private long commandsIn = 0; + long commandsIn = 0; // completed incoming commands private final RangeSet processed = new RangeSet(); - private long processedMark = -1; private Range syncPoint = null; // outgoing command count private long commandsOut = 0; private Map<Long,Method> commands = new HashMap<Long,Method>(); - private long mark = 0; + private long maxComplete = -1; private AtomicBoolean closed = new AtomicBoolean(false); + public Session(byte[] name) + { + this.name = name; + } + + public byte[] getName() + { + return name; + } public Map<Long,Method> getOutstandingCommands() { @@ -133,25 +145,12 @@ public class Session extends Invoker public void flushProcessed() { - boolean first = true; - RangeSet rest = new RangeSet(); + RangeSet copy; synchronized (processed) { - for (Range r: processed) - { - if (first && r.includes(processedMark)) - { - processedMark = r.getUpper(); - } - else - { - rest.add(r); - } - - first = false; - } + copy = processed.copy(); } - executionComplete(processedMark, rest); + sessionCompleted(copy); } void syncPoint() @@ -193,34 +192,34 @@ public class Session extends Invoker log.debug("%s complete(%d, %d)", this, lower, upper); synchronized (commands) { - for (long id = lower; id <= upper; id++) + for (long id = maxComplete; id <= upper; id++) { commands.remove(id); } + if (lower <= maxComplete + 1) + { + maxComplete = Math.max(maxComplete, upper); + } commands.notifyAll(); log.debug("%s commands remaining: %s", this, commands); } } - void complete(long mark) - { - synchronized (commands) - { - complete(this.mark, mark); - this.mark = mark; - commands.notifyAll(); - } - } - protected void invoke(Method m) { if (m.getEncodedTrack() == Frame.L4) { synchronized (commands) { - // You only need to keep the command if you need command level replay. - // If not we only need to keep track of commands to make sync work - commands.put(commandsOut++,(ENABLE_REPLAY?m:null)); + long next = commandsOut++; + if (next == 0) + { + sessionCommandPoint(0, 0); + } + if (ENABLE_REPLAY) + { + commands.put(next, m); + } channel.method(m); } } @@ -230,7 +229,7 @@ public class Session extends Invoker } } - public void header(Header header) + public void header(Header header) { channel.header(header); } @@ -269,21 +268,32 @@ public class Session extends Invoker public void sync() { + sync(timeout); + } + + public void sync(long timeout) + { log.debug("%s sync()", this); synchronized (commands) { long point = commandsOut - 1; - if (mark < point) + if (maxComplete < point) { - executionSync(); + ExecutionSync sync = new ExecutionSync(); + sync.setSync(true); + invoke(sync); } - while (!closed.get() && mark < point) + long start = System.currentTimeMillis(); + long elapsed = 0; + while (!closed.get() && elapsed < timeout && maxComplete < point) { try { - log.debug("%s waiting for[%d]: %s", this, point, commands); - commands.wait(); + log.debug("%s waiting for[%d]: %d, %s", this, point, + maxComplete, commands); + commands.wait(timeout - elapsed); + elapsed = System.currentTimeMillis() - start; } catch (InterruptedException e) { @@ -291,9 +301,16 @@ public class Session extends Invoker } } - if (mark < point) + if (maxComplete < point) { - throw new RuntimeException("session closed"); + if (closed.get()) + { + throw new RuntimeException("session closed"); + } + else + { + throw new RuntimeException("timed out waiting for sync"); + } } } } @@ -346,16 +363,19 @@ public class Session extends Invoker } } - public T get(long timeout, int nanos) + public T get(long timeout) { synchronized (this) { - while (!closed.get() && !isDone()) + 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, nanos); + wait(timeout - elapsed); + elapsed = System.currentTimeMillis() - start; } catch (InterruptedException e) { @@ -364,22 +384,23 @@ public class Session extends Invoker } } - if (!isDone()) + if (isDone()) + { + return result; + } + else if (closed.get()) { throw new RuntimeException("session closed"); } - - return result; - } - - public T get(long timeout) - { - return get(timeout, 0); + else + { + return null; + } } public T get() { - return get(0); + return get(timeout); } public boolean isDone() @@ -396,7 +417,8 @@ public class Session extends Invoker public void close() { - sessionClose(); + sessionRequestTimeout(0); + sessionDetach(name); // XXX: channel.close(); } 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 index 5e36a77a98..442aba0e9b 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/SessionDelegate.java @@ -35,20 +35,16 @@ public abstract class SessionDelegate { public void init(Session ssn, ProtocolHeader hdr) { } - public void method(Session ssn, Method method) { - if (method.getEncodedTrack() == Frame.L4) - { - method.setId(ssn.nextCommandId()); - } - + public void control(Session ssn, Method method) { method.dispatch(ssn, this); + } - if (method.getEncodedTrack() == Frame.L4) + public void command(Session ssn, Method method) { + method.setId(ssn.nextCommandId()); + method.dispatch(ssn, this); + if (!method.hasPayload()) { - if (!method.hasPayload()) - { - ssn.processed(method); - } + ssn.processed(method); } } @@ -60,12 +56,12 @@ public abstract class SessionDelegate @Override public void executionResult(Session ssn, ExecutionResult result) { - ssn.result(result.getCommandId(), result.getData()); + ssn.result(result.getCommandId(), result.getValue()); } - @Override public void executionComplete(Session ssn, ExecutionComplete excmp) + @Override public void sessionCompleted(Session ssn, SessionCompleted cmp) { - RangeSet ranges = excmp.getRangedExecutionSet(); + RangeSet ranges = cmp.getCommands(); if (ranges != null) { for (Range range : ranges) @@ -73,12 +69,27 @@ public abstract class SessionDelegate ssn.complete(range.getLower(), range.getUpper()); } } - ssn.complete(excmp.getCumulativeExecutionMark()); } - @Override public void executionFlush(Session ssn, ExecutionFlush flush) + @Override public void sessionFlush(Session ssn, SessionFlush flush) + { + if (flush.getCompleted()) + { + ssn.flushProcessed(); + } + if (flush.getConfirmed()) + { + throw new Error("not implemented"); + } + if (flush.getExpected()) + { + throw new Error("not implemented"); + } + } + + @Override public void sessionCommandPoint(Session ssn, SessionCommandPoint scp) { - ssn.flushProcessed(); + ssn.commandsIn = scp.getCommandId(); } @Override public void executionSync(Session ssn, ExecutionSync sync) 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 index 200c3b68e3..f901f9e840 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/Struct.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/Struct.java @@ -71,8 +71,6 @@ public abstract class Struct implements Encodable return type; } - public abstract boolean hasTicket(); - private final boolean isBit(Field<?,?> f) { return f.getType().equals(Boolean.class); @@ -80,14 +78,7 @@ public abstract class Struct implements Encodable private final boolean packed() { - if (this instanceof Method) - { - return false; - } - else - { - return true; - } + return getPackWidth() > 0; } private final boolean encoded(Field<?,?> f) @@ -147,11 +138,6 @@ public abstract class Struct implements Encodable } } - if (hasTicket()) - { - dec.readShort(); - } - for (Field<?,?> f : fields) { if (encoded(f)) @@ -187,11 +173,6 @@ public abstract class Struct implements Encodable } } - if (hasTicket()) - { - enc.writeShort(0x0); - } - for (Field<?,?> f : fields) { if (encoded(f)) 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 index 54429a1a4f..e9a0705de0 100644 --- a/java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java +++ b/java/common/src/main/java/org/apache/qpidity/transport/TransportConstants.java @@ -2,8 +2,9 @@ package org.apache.qpidity.transport; public class TransportConstants { - private static byte _protocol_version_minor = 0; - private static byte _protocol_version_major = 99; + + private static byte _protocol_version_minor = 10; + private static byte _protocol_version_major = 0; public static void setVersionMajor(byte value) { @@ -24,4 +25,5 @@ public class TransportConstants { return _protocol_version_minor; } + } 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 index ae67483a23..0f6180f54a 100644 --- 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 @@ -20,7 +20,10 @@ */ 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; @@ -99,19 +102,19 @@ abstract class AbstractDecoder implements Decoder nbits = 0; } - public short readOctet() + public short readUint8() { return uget(); } - public int readShort() + public int readUint16() { int i = uget() << 8; i |= uget(); return i; } - public long readLong() + public long readUint32() { long l = uget() << 24; l |= uget() << 16; @@ -120,7 +123,12 @@ abstract class AbstractDecoder implements Decoder return l; } - public long readLonglong() + public int readSequenceNo() + { + return (int) readUint32(); + } + + public long readUint64() { long l = 0; for (int i = 0; i < 8; i++) @@ -130,31 +138,67 @@ abstract class AbstractDecoder implements Decoder return l; } - public long readTimestamp() + public long readDatetime() + { + return readUint64(); + } + + private static final String decode(byte[] bytes, String charset) { - return readLonglong(); + try + { + return new String(bytes, charset); + } + catch (UnsupportedEncodingException e) + { + throw new RuntimeException(e); + } } - public String readShortstr() + public String readStr8() + { + short size = readUint8(); + byte[] bytes = new byte[size]; + get(bytes); + return decode(bytes, "UTF-8"); + } + + public String readStr16() { - short size = readOctet(); + int size = readUint16(); byte[] bytes = new byte[size]; get(bytes); - return new String(bytes); + return decode(bytes, "UTF-8"); } - public String readLongstr() + public byte[] readVbin8() { - long size = readLong(); - byte[] bytes = new byte[(int) size]; + int size = readUint8(); + byte[] bytes = new byte[size]; get(bytes); - return new String(bytes); + return bytes; } - public RangeSet readRfc1982LongSet() + public byte[] readVbin16() { - int count = readShort()/8; + 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; @@ -164,16 +208,21 @@ abstract class AbstractDecoder implements Decoder RangeSet ranges = new RangeSet(); for (int i = 0; i < count; i++) { - ranges.add(readLong(), readLong()); + ranges.add(readUint32(), readUint32()); } return ranges; } } + public RangeSet readByteRanges() + { + throw new Error("not implemented"); + } + public UUID readUuid() { - long msb = readLonglong(); - long lsb = readLonglong(); + long msb = readUint64(); + long lsb = readUint64(); return new UUID(msb, lsb); } @@ -194,34 +243,39 @@ abstract class AbstractDecoder implements Decoder return null; } } + if (type > 0) + { + int code = readUint16(); + assert code == type; + } st.read(this); return st; } - public Struct readLongStruct() + public Struct readStruct32() { - long size = readLong(); + long size = readUint32(); if (size == 0) { return null; } else { - int type = readShort(); + int type = readUint16(); Struct result = Struct.create(type); result.read(this); return result; } } - public Map<String,Object> readTable() + public Map<String,Object> readMap() { - long size = readLong(); + long size = readUint32(); int start = count; Map<String,Object> result = new LinkedHashMap(); while (count < start + size) { - String key = readShortstr(); + String key = readStr8(); byte code = get(); Type t = getType(code); Object value = read(t); @@ -230,9 +284,9 @@ abstract class AbstractDecoder implements Decoder return result; } - public List<Object> readSequence() + public List<Object> readList() { - long size = readLong(); + long size = readUint32(); int start = count; List<Object> result = new ArrayList(); while (count < start + size) @@ -247,10 +301,15 @@ abstract class AbstractDecoder implements Decoder public List<Object> readArray() { - long size = readLong(); + long size = readUint32(); + if (size == 0) + { + return Collections.EMPTY_LIST; + } + byte code = get(); Type t = getType(code); - long count = readLong(); + long count = readUint32(); List<Object> result = new ArrayList<Object>(); for (int i = 0; i < count; i++) @@ -291,11 +350,11 @@ abstract class AbstractDecoder implements Decoder switch (width) { case 1: - return readOctet(); + return readUint8(); case 2: - return readShort(); + return readUint16(); case 4: - return readLong(); + return readUint32(); default: throw new IllegalStateException("illegal width: " + width); } @@ -313,81 +372,72 @@ abstract class AbstractDecoder implements Decoder { switch (t) { - case OCTET: - case UNSIGNED_BYTE: - return readOctet(); - case SIGNED_BYTE: + case BIN8: + case UINT8: + return readUint8(); + case INT8: return get(); case CHAR: return (char) get(); case BOOLEAN: return get() > 0; - case TWO_OCTETS: - case UNSIGNED_SHORT: - return readShort(); + case BIN16: + case UINT16: + return readUint16(); - case SIGNED_SHORT: - return (short) readShort(); + case INT16: + return (short) readUint16(); - case FOUR_OCTETS: - case UNSIGNED_INT: - return readLong(); + case BIN32: + case UINT32: + return readUint32(); - case UTF32_CHAR: - case SIGNED_INT: - return (int) readLong(); + case CHAR_UTF32: + case INT32: + return (int) readUint32(); case FLOAT: - return Float.intBitsToFloat((int) readLong()); + return Float.intBitsToFloat((int) readUint32()); - case EIGHT_OCTETS: - case SIGNED_LONG: - case UNSIGNED_LONG: + case BIN64: + case UINT64: + case INT64: case DATETIME: - return readLonglong(); + return readUint64(); case DOUBLE: - return Double.longBitsToDouble(readLonglong()); - - case SIXTEEN_OCTETS: - case THIRTY_TWO_OCTETS: - case SIXTY_FOUR_OCTETS: - case _128_OCTETS: - case SHORT_BINARY: - case BINARY: - case LONG_BINARY: - return readBytes(t); + return Double.longBitsToDouble(readUint64()); case UUID: return readUuid(); - case SHORT_STRING: - case SHORT_UTF8_STRING: - case SHORT_UTF16_STRING: - case SHORT_UTF32_STRING: - case STRING: - case UTF8_STRING: - case UTF16_STRING: - case UTF32_STRING: - case LONG_STRING: - case LONG_UTF8_STRING: - case LONG_UTF16_STRING: - case LONG_UTF32_STRING: + 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 TABLE: - return readTable(); - case SEQUENCE: - return readSequence(); + case MAP: + return readMap(); + case LIST: + return readList(); case ARRAY: return readArray(); + case STRUCT32: + return readStruct32(); - case FIVE_OCTETS: - case DECIMAL: - case NINE_OCTETS: - case LONG_DECIMAL: + case BIN40: + case DEC32: + case BIN72: + case DEC64: // XXX: what types are we supposed to use here? 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 index c2dd205d66..56b4537719 100644 --- 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 @@ -20,8 +20,11 @@ */ 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; @@ -48,17 +51,17 @@ abstract class AbstractEncoder implements Encoder static { ENCODINGS.put(Boolean.class, Type.BOOLEAN); - ENCODINGS.put(String.class, Type.LONG_STRING); - ENCODINGS.put(Long.class, Type.SIGNED_LONG); - ENCODINGS.put(Integer.class, Type.SIGNED_INT); - ENCODINGS.put(Short.class, Type.SIGNED_SHORT); - ENCODINGS.put(Byte.class, Type.SIGNED_BYTE); - ENCODINGS.put(Map.class, Type.TABLE); - ENCODINGS.put(List.class, Type.SEQUENCE); + 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.LONG_BINARY); + ENCODINGS.put(byte[].class, Type.VBIN32); } protected Sizer sizer() @@ -120,14 +123,14 @@ abstract class AbstractEncoder implements Encoder flushBits(); } - public void writeOctet(short b) + public void writeUint8(short b) { assert b < 0x100; put((byte) b); } - public void writeShort(int s) + public void writeUint16(int s) { assert s < 0x10000; @@ -135,7 +138,7 @@ abstract class AbstractEncoder implements Encoder put(lsb(s)); } - public void writeLong(long i) + public void writeUint32(long i) { assert i < 0x100000000L; @@ -145,7 +148,12 @@ abstract class AbstractEncoder implements Encoder put(lsb(i)); } - public void writeLonglong(long l) + public void writeSequenceNo(int i) + { + writeUint32(i); + } + + public void writeUint64(long l) { for (int i = 0; i < 8; i++) { @@ -154,47 +162,101 @@ abstract class AbstractEncoder implements Encoder } - public void writeTimestamp(long l) + 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) { - writeLonglong(l); + 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 writeShortstr(String s) + public void writeVbin8(byte[] bytes) { - if (s == null) { s = ""; } - if (s.length() > 255) { - throw new IllegalArgumentException(s); + if (bytes == null) { bytes = new byte[0]; } + if (bytes.length > 255) + { + throw new IllegalArgumentException("array too long: " + bytes.length); } - writeOctet((short) s.length()); - put(ByteBuffer.wrap(s.getBytes())); + writeUint8((short) bytes.length); + put(ByteBuffer.wrap(bytes)); } - public void writeLongstr(String s) + public void writeVbin16(byte[] bytes) { - if (s == null) { s = ""; } - writeLong(s.length()); - put(ByteBuffer.wrap(s.getBytes())); + 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 writeRfc1982LongSet(RangeSet ranges) + public void writeSequenceSet(RangeSet ranges) { if (ranges == null) { - writeShort((short) 0); + writeUint16((short) 0); } else { - writeShort(ranges.size() * 8); + writeUint16(ranges.size() * 8); for (Range range : ranges) { - writeLong(range.getLower()); - writeLong(range.getUpper()); + writeUint32(range.getLower()); + writeUint32(range.getUpper()); } } } + public void writeByteRanges(RangeSet ranges) + { + throw new Error("not implemented"); + } + public void writeUuid(UUID uuid) { long msb = 0; @@ -202,15 +264,10 @@ abstract class AbstractEncoder implements Encoder if (uuid != null) { msb = uuid.getMostSignificantBits(); - uuid.getLeastSignificantBits(); + lsb = uuid.getLeastSignificantBits(); } - writeLonglong(msb); - writeLonglong(lsb); - } - - public void writeContent(String c) - { - throw new Error("Deprecated"); + writeUint64(msb); + writeUint64(lsb); } public void writeStruct(int type, Struct s) @@ -237,22 +294,27 @@ abstract class AbstractEncoder implements Encoder } } + if (type > 0) + { + writeUint16(type); + } + s.write(this); } - public void writeLongStruct(Struct s) + public void writeStruct32(Struct s) { if (s == null) { - writeLong(0); + writeUint32(0); } else { Sizer sizer = sizer(); - sizer.writeShort(s.getEncodedType()); + sizer.writeUint16(s.getEncodedType()); s.write(sizer); - writeLong(sizer.size()); - writeShort(s.getEncodedType()); + writeUint32(sizer.size()); + writeUint16(s.getEncodedType()); s.write(this); } } @@ -309,46 +371,46 @@ abstract class AbstractEncoder implements Encoder return null; } - public void writeTable(Map<String,Object> table) + public void writeMap(Map<String,Object> map) { - if (table == null) + if (map == null) { - writeLong(0); + writeUint32(0); return; } Sizer sizer = sizer(); - sizer.writeTable(table); + sizer.writeMap(map); // XXX: - 4 - writeLong(sizer.size() - 4); - writeTableEntries(table); + writeUint32(sizer.size() - 4); + writeMapEntries(map); } - protected void writeTableEntries(Map<String,Object> table) + protected void writeMapEntries(Map<String,Object> map) { - for (Map.Entry<String,Object> entry : table.entrySet()) + for (Map.Entry<String,Object> entry : map.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); Type type = encoding(value); - writeShortstr(key); + writeStr8(key); put(type.code); write(type, value); } } - public void writeSequence(List<Object> sequence) + public void writeList(List<Object> list) { Sizer sizer = sizer(); - sizer.writeSequence(sequence); + sizer.writeList(list); // XXX: - 4 - writeLong(sizer.size() - 4); - writeSequenceEntries(sequence); + writeUint32(sizer.size() - 4); + writeListEntries(list); } - protected void writeSequenceEntries(List<Object> sequence) + protected void writeListEntries(List<Object> list) { - for (Object value : sequence) + for (Object value : list) { Type type = encoding(value); put(type.code); @@ -358,10 +420,15 @@ abstract class AbstractEncoder implements Encoder public void writeArray(List<Object> array) { + if (array == null) + { + array = Collections.EMPTY_LIST; + } + Sizer sizer = sizer(); sizer.writeArray(array); // XXX: -4 - writeLong(sizer.size() - 4); + writeUint32(sizer.size() - 4); writeArrayEntries(array); } @@ -371,7 +438,7 @@ abstract class AbstractEncoder implements Encoder if (array.isEmpty()) { - type = Type.VOID; + return; } else { @@ -380,6 +447,8 @@ abstract class AbstractEncoder implements Encoder put(type.code); + writeUint32(array.size()); + for (Object value : array) { write(type, value); @@ -409,13 +478,13 @@ abstract class AbstractEncoder implements Encoder switch (width) { case 1: - writeOctet((short) size); + writeUint8((short) size); break; case 2: - writeShort(size); + writeUint16(size); break; case 4: - writeLong(size); + writeUint32(size); break; default: throw new IllegalStateException("illegal width: " + width); @@ -444,11 +513,11 @@ abstract class AbstractEncoder implements Encoder { switch (t) { - case OCTET: - case UNSIGNED_BYTE: - writeOctet(coerce(Short.class, value)); + case BIN8: + case UINT8: + writeUint8(coerce(Short.class, value)); break; - case SIGNED_BYTE: + case INT8: put(coerce(Byte.class, value)); break; case CHAR: @@ -465,85 +534,78 @@ abstract class AbstractEncoder implements Encoder } break; - case TWO_OCTETS: - case UNSIGNED_SHORT: - writeShort(coerce(Integer.class, value)); + case BIN16: + case UINT16: + writeUint16(coerce(Integer.class, value)); break; - case SIGNED_SHORT: - writeShort(coerce(Short.class, value)); + case INT16: + writeUint16(coerce(Short.class, value)); break; - case FOUR_OCTETS: - case UNSIGNED_INT: - writeLong(coerce(Long.class, value)); + case BIN32: + case UINT32: + writeUint32(coerce(Long.class, value)); break; - case UTF32_CHAR: - case SIGNED_INT: - writeLong(coerce(Integer.class, value)); + case CHAR_UTF32: + case INT32: + writeUint32(coerce(Integer.class, value)); break; case FLOAT: - writeLong(Float.floatToIntBits(coerce(Float.class, value))); + writeUint32(Float.floatToIntBits(coerce(Float.class, value))); break; - case EIGHT_OCTETS: - case SIGNED_LONG: - case UNSIGNED_LONG: + case BIN64: + case UINT64: + case INT64: case DATETIME: - writeLonglong(coerce(Long.class, value)); + writeUint64(coerce(Long.class, value)); break; case DOUBLE: long bits = Double.doubleToLongBits(coerce(Double.class, value)); - writeLonglong(bits); - break; - - case SIXTEEN_OCTETS: - case THIRTY_TWO_OCTETS: - case SIXTY_FOUR_OCTETS: - case _128_OCTETS: - case SHORT_BINARY: - case BINARY: - case LONG_BINARY: - writeBytes(t, coerce(byte[].class, value)); + writeUint64(bits); break; case UUID: writeUuid(coerce(UUID.class, value)); break; - case SHORT_STRING: - case SHORT_UTF8_STRING: - case SHORT_UTF16_STRING: - case SHORT_UTF32_STRING: - case STRING: - case UTF8_STRING: - case UTF16_STRING: - case UTF32_STRING: - case LONG_STRING: - case LONG_UTF8_STRING: - case LONG_UTF16_STRING: - case LONG_UTF32_STRING: + 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 TABLE: - writeTable((Map<String,Object>) coerce(Map.class, value)); + case MAP: + writeMap((Map<String,Object>) coerce(Map.class, value)); break; - case SEQUENCE: - writeSequence(coerce(List.class, value)); + 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 FIVE_OCTETS: - case DECIMAL: - case NINE_OCTETS: - case LONG_DECIMAL: + case BIN40: + case DEC32: + case BIN72: + case DEC64: // XXX: what types are we supposed to use here? writeBytes(t, coerce(byte[].class, value)); break; 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 index f0738e0a91..df2d208118 100644 --- 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 @@ -38,26 +38,30 @@ public interface Decoder { boolean readBit(); - short readOctet(); - int readShort(); - long readLong(); - long readLonglong(); + short readUint8(); + int readUint16(); + long readUint32(); + long readUint64(); - long readTimestamp(); - - String readShortstr(); - String readLongstr(); - - RangeSet readRfc1982LongSet(); + long readDatetime(); UUID readUuid(); - String readContent(); + int readSequenceNo(); + RangeSet readSequenceSet(); // XXX + RangeSet readByteRanges(); // XXX - Struct readStruct(int type); - Struct readLongStruct(); + String readStr8(); + String readStr16(); - Map<String,Object> readTable(); - List<Object> readSequence(); + byte[] readVbin8(); + byte[] readVbin16(); + byte[] readVbin32(); + + Struct readStruct32(); + Map<String,Object> readMap(); + List<Object> readList(); List<Object> readArray(); + Struct readStruct(int type); + } 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 index 1b2fe0213e..0449ba6702 100644 --- 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 @@ -40,26 +40,30 @@ public interface Encoder void flush(); void writeBit(boolean b); - void writeOctet(short b); - void writeShort(int s); - void writeLong(long i); - void writeLonglong(long l); + void writeUint8(short b); + void writeUint16(int s); + void writeUint32(long i); + void writeUint64(long l); - void writeTimestamp(long l); - - void writeShortstr(String s); - void writeLongstr(String s); - - void writeRfc1982LongSet(RangeSet ranges); + void writeDatetime(long l); void writeUuid(UUID uuid); - void writeContent(String c); + void writeSequenceNo(int s); + void writeSequenceSet(RangeSet ranges); // XXX + void writeByteRanges(RangeSet ranges); // XXX - void writeStruct(int type, Struct s); - void writeLongStruct(Struct s); + void writeStr8(String s); + void writeStr16(String s); - void writeTable(Map<String,Object> table); - void writeSequence(List<Object> sequence); + void writeVbin8(byte[] bytes); + void writeVbin16(byte[] bytes); + void writeVbin32(byte[] bytes); + + void writeStruct32(Struct s); + void writeMap(Map<String,Object> map); + void writeList(List<Object> list); void writeArray(List<Object> 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 index b98bf98239..8ffdd5150b 100644 --- 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 @@ -38,30 +38,34 @@ public interface Sizer extends Encoder public static final Sizer NULL = new Sizer() { - public void flush() {}; + public void flush() {} - public void writeBit(boolean b) {}; - public void writeOctet(short b) {}; - public void writeShort(int s) {}; - public void writeLong(long i) {}; - public void writeLonglong(long l) {}; + public void writeBit(boolean b) {} + public void writeUint8(short b) {} + public void writeUint16(int s) {} + public void writeUint32(long i) {} + public void writeUint64(long l) {} - public void writeTimestamp(long l) {}; + public void writeDatetime(long l) {} + public void writeUuid(UUID uuid) {} - public void writeShortstr(String s) {}; - public void writeLongstr(String s) {}; + public void writeSequenceNo(int s) {} + public void writeSequenceSet(RangeSet ranges) {} // XXX + public void writeByteRanges(RangeSet ranges) {} // XXX - public void writeRfc1982LongSet(RangeSet ranges) {}; - public void writeUuid(UUID uuid) {}; + public void writeStr8(String s) {} + public void writeStr16(String s) {} - public void writeContent(String c) {}; + public void writeVbin8(byte[] bytes) {} + public void writeVbin16(byte[] bytes) {} + public void writeVbin32(byte[] bytes) {} - public void writeStruct(int type, Struct s) {}; - public void writeLongStruct(Struct s) {}; + public void writeStruct32(Struct s) {} + public void writeMap(Map<String,Object> map) {} + public void writeList(List<Object> list) {} + public void writeArray(List<Object> array) {} - public void writeTable(Map<String,Object> table) {}; - public void writeSequence(List<Object> sequence) {}; - public void writeArray(List<Object> array) {}; + public void writeStruct(int type, Struct s) {} public int getSize() { return 0; } 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 index 5c35596fd8..d493245f0c 100644 --- 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 @@ -37,6 +37,7 @@ 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; @@ -118,7 +119,7 @@ public class Assembler implements Receiver<NetworkEvent>, NetworkDelegate { switch (frame.getType()) { - case Frame.BODY: + case BODY: emit(frame, new Data(frame, frame.isFirstFrame(), frame.isLastFrame())); break; @@ -158,22 +159,29 @@ public class Assembler implements Receiver<NetworkEvent>, NetworkDelegate } } - private ProtocolEvent decode(Frame frame, byte type, List<ByteBuffer> segment) + private ProtocolEvent decode(Frame frame, SegmentType type, List<ByteBuffer> segment) { FragmentDecoder dec = new FragmentDecoder(segment.iterator()); switch (type) { - case Frame.METHOD: - int methodType = dec.readShort(); - Method method = Method.create(methodType); - method.read(dec); - return method; - case Frame.HEADER: + 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<Struct> structs = new ArrayList(); while (dec.hasRemaining()) { - structs.add(dec.readLongStruct()); + structs.add(dec.readStruct32()); } return new Header(structs,frame.isLastFrame() && frame.isLastSegment()); default: 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 index d38d8ded98..0357df6e86 100644 --- 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 @@ -31,6 +31,7 @@ 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; @@ -76,50 +77,50 @@ public class Disassembler implements Sender<ConnectionEvent>, sender.close(); } - private void fragment(byte flags, byte type, ConnectionEvent event, + private void fragment(byte flags, SegmentType type, ConnectionEvent event, ByteBuffer buf, boolean first, boolean last) { if(!buf.hasRemaining()) { //empty data - byte nflags = flags; + byte nflags = flags; if (first) { nflags |= FIRST_FRAME; first = false; } - nflags |= LAST_FRAME; - Frame frame = new Frame(nflags, type, + nflags |= LAST_FRAME; + Frame frame = new Frame(nflags, type, event.getProtocolEvent().getEncodedTrack(), event.getChannel()); - // frame.addFragment(buf); + // 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) + while (buf.hasRemaining()) { - newflags |= FIRST_FRAME; - first = false; + 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, + event.getProtocolEvent().getEncodedTrack(), + event.getChannel()); + frame.addFragment(slice); + sender.send(frame); } - if (last && !buf.hasRemaining()) - { - newflags |= LAST_FRAME; - } - - Frame frame = new Frame(newflags, type, - event.getProtocolEvent().getEncodedTrack(), - event.getChannel()); - frame.addFragment(slice); - sender.send(frame); - } } } @@ -128,15 +129,40 @@ public class Disassembler implements Sender<ConnectionEvent>, sender.send(header); } - public void method(ConnectionEvent event, Method method) + 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.writeShort(method.getEncodedType()); + 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.writeShort(method.getEncodedType()); + enc.writeUint16(method.getEncodedType()); + if (type == SegmentType.COMMAND) + { + if (method.isSync()) + { + enc.writeUint16(0x0101); + } + else + { + enc.writeUint16(0x0100); + } + } method.write(enc); enc.flush(); buf.flip(); @@ -148,7 +174,7 @@ public class Disassembler implements Sender<ConnectionEvent>, flags |= LAST_SEG; } - fragment(flags, METHOD, event, buf, true, true); + fragment(flags, type, event, buf, true, true); } public void header(ConnectionEvent event, Header header) @@ -159,24 +185,24 @@ public class Disassembler implements Sender<ConnectionEvent>, SizeEncoder sizer = new SizeEncoder(); for (Struct st : header.getStructs()) { - sizer.writeLongStruct(st); + sizer.writeStruct32(st); } buf = ByteBuffer.allocate(sizer.size()); BBEncoder enc = new BBEncoder(buf); for (Struct st : header.getStructs()) { - enc.writeLongStruct(st); + enc.writeStruct32(st); enc.flush(); } header.setBuf(buf); } else { - buf = header.getBuf(); + buf = header.getBuf(); } buf.flip(); - fragment((byte) 0x0, HEADER, event, buf, true, true); + fragment((byte) 0x0, SegmentType.HEADER, event, buf, true, true); } public void data(ConnectionEvent event, Data data) @@ -187,7 +213,7 @@ public class Disassembler implements Sender<ConnectionEvent>, { ByteBuffer buf = it.next(); boolean last = data.isLast() && !it.hasNext(); - fragment(LAST_SEG, BODY, event, buf, first, last); + fragment(LAST_SEG, SegmentType.BODY, event, buf, first, last); first = false; } } 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 index a5c5db4dba..c5fb7b9986 100644 --- 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 @@ -20,6 +20,7 @@ */ package org.apache.qpidity.transport.network; +import org.apache.qpidity.transport.SegmentType; import org.apache.qpidity.transport.util.SliceIterator; import java.nio.ByteBuffer; @@ -48,10 +49,6 @@ public class Frame implements NetworkEvent, Iterable<ByteBuffer> public static final byte L3 = 2; public static final byte L4 = 3; - public static final byte METHOD = 1; - public static final byte HEADER = 2; - public static final byte BODY = 3; - public static final byte RESERVED = 0x0; public static final byte VERSION = 0x0; @@ -62,13 +59,13 @@ public class Frame implements NetworkEvent, Iterable<ByteBuffer> public static final byte LAST_FRAME = 0x1; final private byte flags; - final private byte type; + final private SegmentType type; final private byte track; final private int channel; final private List<ByteBuffer> fragments; private int size; - public Frame(byte flags, byte type, byte track, int channel) + public Frame(byte flags, SegmentType type, byte track, int channel) { this.flags = flags; this.type = type; @@ -99,7 +96,7 @@ public class Frame implements NetworkEvent, Iterable<ByteBuffer> return size; } - public byte getType() + public SegmentType getType() { return type; } @@ -153,7 +150,7 @@ public class Frame implements NetworkEvent, Iterable<ByteBuffer> { StringBuilder str = new StringBuilder(); str.append(String.format - ("[%05d %05d %1d %1d %d%d%d%d]", getChannel(), getSize(), + ("[%05d %05d %1d %1d %d%d%d%d] ", getChannel(), getSize(), getTrack(), getType(), isFirstSegment() ? 1 : 0, isLastSegment() ? 1 : 0, isFirstFrame() ? 1 : 0, isLastFrame() ? 1 : 0)); @@ -170,7 +167,7 @@ public class Frame implements NetworkEvent, Iterable<ByteBuffer> str.append(" | "); } - str.append(str(buf, 20)); + 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 index 871c45743e..2d41a9f516 100644 --- 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 @@ -22,10 +22,10 @@ package org.apache.qpidity.transport.network; import java.nio.ByteBuffer; -import org.apache.qpidity.transport.Constant; 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.*; @@ -77,7 +77,7 @@ public class InputHandler implements Receiver<ByteBuffer> private byte minor; private byte flags; - private byte type; + private SegmentType type; private byte track; private int channel; private int size; @@ -146,7 +146,7 @@ public class InputHandler implements Receiver<ByteBuffer> flags = buf.get(); return FRAME_HDR_TYPE; case FRAME_HDR_TYPE: - type = buf.get(); + type = SegmentType.get(buf.get()); return FRAME_HDR_SIZE1; case FRAME_HDR_SIZE1: size = (0xFF & buf.get()) << 8; @@ -218,7 +218,7 @@ public class InputHandler implements Receiver<ByteBuffer> return FRAME_END; } case FRAME_END: - return expect(buf, Constant.FRAME_END, FRAME_HDR); + return expect(buf, OutputHandler.FRAME_END, FRAME_HDR); default: throw new IllegalStateException(); } 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 index 9f770bcb1c..8f615cf80d 100644 --- 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 @@ -67,11 +67,13 @@ public class OutputHandler implements Sender<NetworkEvent>, NetworkDelegate } } + public static final int FRAME_END = 0xCE; + public void frame(Frame frame) { ByteBuffer hdr = ByteBuffer.allocate(HEADER_SIZE + frame.getSize() + 1); hdr.put(frame.getFlags()); - hdr.put(frame.getType()); + hdr.put((byte) frame.getType().getValue()); hdr.putShort((short) (frame.getSize() + HEADER_SIZE)); hdr.put(RESERVED); hdr.put(frame.getTrack()); @@ -84,7 +86,7 @@ public class OutputHandler implements Sender<NetworkEvent>, NetworkDelegate { hdr.put(buf); } - hdr.put((byte) Constant.FRAME_END); + hdr.put((byte) FRAME_END); hdr.flip(); synchronized (lock) { 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 index 2e4875cf42..7da719087c 100644 --- 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 @@ -200,7 +200,7 @@ public class MinaHandler<E> implements IoHandler ConnectionDelegate delegate) { return connect(host, port, new ConnectionBinding - (delegate, InputHandler.State.FRAME_HDR)); + (delegate, InputHandler.State.PROTO_HDR)); } private static class ConnectionBinding 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 index 7dbb3d30e8..14e756c047 100644 --- 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 @@ -52,15 +52,24 @@ public class Functions 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++) { - if (i > 0 && i % 2 == 0) + byte c = buf.get(buf.position() + i); + + if (c > 31 && c < 127 && c != '\\') { - str.append(" "); + str.append((char)c); + } + else + { + str.append(String.format("\\x%02x", c)); } - str.append(String.format("%02x", buf.get(buf.position() + i))); } + str.append('"'); + return str.toString(); } 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 index d7ece9b745..1a83786e12 100644 --- a/java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java +++ b/java/common/src/test/java/org/apache/qpidity/transport/ConnectionTest.java @@ -100,12 +100,12 @@ public class ConnectionTest extends TestCase } Channel ch = conn.getChannel(0); - Session ssn = new Session(); + Session ssn = new Session("test".getBytes()); ssn.attach(ch); try { - ssn.sessionOpen(1234); + ssn.sessionAttach(ssn.getName()); fail("writing to a closed socket succeeded"); } catch (TransportException e) diff --git a/java/common/templating.py b/java/common/templating.py new file mode 100644 index 0000000000..832b7ecb9c --- /dev/null +++ b/java/common/templating.py @@ -0,0 +1,101 @@ + +class Parser: + + def __init__(self, **kwargs): + self.output = "" + self.environ = {"out": self.parse} + for k, v in kwargs.items(): + self.environ[k] = v + self.text = "" + self.level = 0 + self.line = None + + def action(self, actor): + text = self.text + self.text = "" + actor(text) + + def out(self, text): + self.output += text + + def prefix_lines(self, text): + return "%s%s" % ("\n"*(self.line - 1 - text.count("\n")), text) + + def evaluate(self, text): + self.out(str(eval(self.prefix_lines(text), self.environ, self.environ))) + + def execute(self, text): + exec self.prefix_lines(text) in self.environ, self.environ + + def parse(self, input): + old_line = self.line + try: + state = self.start + self.line = 1 + for ch in input: + state = state(ch) + if ch == "\n": + self.line += 1 + if state == self.start: + self.action(self.out) + elif state == self.alnum: + self.action(self.evaluate) + else: + raise ParseError() + finally: + self.line = old_line + + def start(self, ch): + if ch == "$": + return self.dollar + else: + self.text += ch + return self.start + + def dollar(self, ch): + if ch == "$": + self.text += "$" + return self.start + elif ch == "(": + self.action(self.out) + return self.expression + elif ch == "{": + self.action(self.out) + return self.block + else: + self.action(self.out) + self.text += ch + return self.alnum + + def alnum(self, ch): + if ch.isalnum(): + self.text += ch + return self.alnum + else: + self.action(self.evaluate) + self.text += ch + return self.start + + def match(self, ch, start, end): + if ch == start: + self.level += 1 + if ch == end: + self.level -= 1 + + def block(self, ch): + if not self.level and ch == "}": + self.action(self.execute) + return self.start + else: + self.match(ch, "{", "}") + self.text += ch + return self.block + + def expression(self, ch): + if not self.level and ch == ")": + self.action(self.evaluate) + return self.start + else: + self.match(ch, "(", ")") + self.text += ch + return self.expression diff --git a/java/cpp.async.testprofile b/java/cpp.async.testprofile index d4daf47632..3dd78c855e 100644 --- a/java/cpp.async.testprofile +++ b/java/cpp.async.testprofile @@ -1,6 +1,6 @@ broker.version=0-10 broker=${project.root}/../cpp/src/qpidd --data-dir ${build.data} -t --log-output ${build.data}/broker.log --load-module ${project.root}/../../cppStore/cpp/lib/.libs/libbdbstore.so --store-async yes -broker.clean=${build.data} +broker.clean=${project.root}/clean-dir ${build.data} java.naming.provider.url=${project.root}/test-provider.properties max_prefetch=1000 test.excludes=true @@ -14,4 +14,4 @@ test.mem=512M test=*Test test1=*Tests haltonfailure=no -haltonerror=no
\ No newline at end of file +haltonerror=no |