diff options
Diffstat (limited to 'java')
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 |