diff options
Diffstat (limited to 'java/client/src')
84 files changed, 4536 insertions, 3797 deletions
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java index 2c92cfb85e..ebbbac5e6e 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java @@ -20,34 +20,14 @@ */ package org.apache.qpid.client; -import java.io.IOException; -import java.net.ConnectException; -import java.nio.channels.UnresolvedAddressException; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.Map; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.jms.*; -import javax.jms.IllegalStateException; -import javax.naming.NamingException; -import javax.naming.Reference; -import javax.naming.Referenceable; -import javax.naming.StringRefAddr; - import org.apache.log4j.Logger; - import org.apache.qpid.AMQConnectionFailureException; import org.apache.qpid.AMQException; import org.apache.qpid.AMQUndeliveredException; import org.apache.qpid.AMQUnresolvedAddressException; -import org.apache.qpid.client.failover.FailoverSupport; +import org.apache.qpid.client.failover.FailoverException; +import org.apache.qpid.client.failover.FailoverProtectedOperation; +import org.apache.qpid.client.failover.FailoverRetrySupport; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.client.state.AMQState; import org.apache.qpid.client.transport.TransportConnection; @@ -68,6 +48,37 @@ import org.apache.qpid.jms.FailoverPolicy; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.url.URLSyntaxException; +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.QueueConnection; +import javax.jms.QueueSession; +import javax.jms.ServerSessionPool; +import javax.jms.Topic; +import javax.jms.TopicConnection; +import javax.jms.TopicSession; +import javax.naming.NamingException; +import javax.naming.Reference; +import javax.naming.Referenceable; +import javax.naming.StringRefAddr; +import java.io.IOException; +import java.net.ConnectException; +import java.nio.channels.UnresolvedAddressException; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + public class AMQConnection extends Closeable implements Connection, QueueConnection, TopicConnection, Referenceable { private static final Logger _logger = Logger.getLogger(AMQConnection.class); @@ -163,7 +174,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect * @throws URLSyntaxException */ public AMQConnection(String broker, String username, String password, String clientName, String virtualHost) - throws AMQException, URLSyntaxException + throws AMQException, URLSyntaxException { this(new AMQConnectionURL( ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@" @@ -182,7 +193,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect * @throws URLSyntaxException */ public AMQConnection(String broker, String username, String password, String clientName, String virtualHost, - SSLConfiguration sslConfig) throws AMQException, URLSyntaxException + SSLConfiguration sslConfig) throws AMQException, URLSyntaxException { this(new AMQConnectionURL( ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@" @@ -191,28 +202,28 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } public AMQConnection(String host, int port, String username, String password, String clientName, String virtualHost) - throws AMQException, URLSyntaxException + throws AMQException, URLSyntaxException { this(host, port, false, username, password, clientName, virtualHost, null); } public AMQConnection(String host, int port, String username, String password, String clientName, String virtualHost, - SSLConfiguration sslConfig) throws AMQException, URLSyntaxException + SSLConfiguration sslConfig) throws AMQException, URLSyntaxException { this(host, port, false, username, password, clientName, virtualHost, sslConfig); } public AMQConnection(String host, int port, boolean useSSL, String username, String password, String clientName, - String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException + String virtualHost, SSLConfiguration sslConfig) throws AMQException, URLSyntaxException { this(new AMQConnectionURL( useSSL ? (ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@" - + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port - + "'" + "," + ConnectionURL.OPTIONS_SSL + "='true'") + + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port + + "'" + "," + ConnectionURL.OPTIONS_SSL + "='true'") : (ConnectionURL.AMQ_PROTOCOL + "://" + username + ":" + password + "@" - + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port - + "'" + "," + ConnectionURL.OPTIONS_SSL + "='false'")), sslConfig); + + ((clientName == null) ? "" : clientName) + virtualHost + "?brokerlist='tcp://" + host + ":" + port + + "'" + "," + ConnectionURL.OPTIONS_SSL + "='false'")), sslConfig); } public AMQConnection(String connection) throws AMQException, URLSyntaxException @@ -226,8 +237,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } /** - * @todo Some horrible stuff going on here with setting exceptions to be non-null to detect if an exception - * was thrown during the connection! Intention not clear. Use a flag anyway, not exceptions... Will fix soon. + * @todo Some horrible stuff going on here with setting exceptions to be non-null to detect if an exception was + * thrown during the connection! Intention not clear. Use a flag anyway, not exceptions... Will fix soon. */ public AMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig) throws AMQException { @@ -294,7 +305,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect if (_logger.isInfoEnabled()) { _logger.info("Unable to connect to broker at " + _failoverPolicy.getCurrentBrokerDetails(), - e.getCause()); + e.getCause()); } } } @@ -332,7 +343,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect if (lastException instanceof UnresolvedAddressException) { e = new AMQUnresolvedAddressException(message, _failoverPolicy.getCurrentBrokerDetails().toString(), - null); + null); } if (e.getCause() != null) @@ -446,7 +457,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect if (_logger.isInfoEnabled()) { _logger.info(e.getMessage() + ":Unable to connect to broker at " - + _failoverPolicy.getCurrentBrokerDetails()); + + _failoverPolicy.getCurrentBrokerDetails()); } } } @@ -485,96 +496,96 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode, final int prefetch) - throws JMSException + throws JMSException { return createSession(transacted, acknowledgeMode, prefetch, prefetch); } public org.apache.qpid.jms.Session createSession(final boolean transacted, final int acknowledgeMode, - final int prefetchHigh, final int prefetchLow) throws JMSException + final int prefetchHigh, final int prefetchLow) throws JMSException { checkNotClosed(); + if (channelLimitReached()) { throw new ChannelLimitReachedException(_maximumChannelCount); } - else - { - return (org.apache.qpid.jms.Session) new FailoverSupport() + + return new FailoverRetrySupport<org.apache.qpid.jms.Session, JMSException>( + new FailoverProtectedOperation<org.apache.qpid.jms.Session, JMSException>() + { + public org.apache.qpid.jms.Session execute() throws JMSException, FailoverException { - public Object operation() throws JMSException + int channelId = _idFactory.incrementAndGet(); + + if (_logger.isDebugEnabled()) { - int channelId = _idFactory.incrementAndGet(); + _logger.debug("Write channel open frame for channel id " + channelId); + } - if (_logger.isDebugEnabled()) + // We must create the session and register it before actually sending the frame to the server to + // open it, so that there is no window where we could receive data on the channel and not be set + // up to handle it appropriately. + AMQSession session = + new AMQSession(AMQConnection.this, channelId, transacted, acknowledgeMode, prefetchHigh, + prefetchLow); + // _protocolHandler.addSessionByChannel(channelId, session); + registerSession(channelId, session); + + boolean success = false; + try + { + createChannelOverWire(channelId, prefetchHigh, prefetchLow, transacted); + success = true; + } + catch (AMQException e) + { + JMSException jmse = new JMSException("Error creating session: " + e); + jmse.setLinkedException(e); + throw jmse; + } + finally + { + if (!success) { - _logger.debug("Write channel open frame for channel id " + channelId); + deregisterSession(channelId); } + } - // We must create the session and register it before actually sending the frame to the server to - // open it, so that there is no window where we could receive data on the channel and not be set - // up to handle it appropriately. - AMQSession session = - new AMQSession(AMQConnection.this, channelId, transacted, acknowledgeMode, prefetchHigh, - prefetchLow); - // _protocolHandler.addSessionByChannel(channelId, session); - registerSession(channelId, session); - - boolean success = false; + if (_started) + { try { - createChannelOverWire(channelId, prefetchHigh, prefetchLow, transacted); - success = true; + session.start(); } catch (AMQException e) { - JMSException jmse = new JMSException("Error creating session: " + e); - jmse.setLinkedException(e); - throw jmse; + throw new JMSAMQException(e); } - finally - { - if (!success) - { - deregisterSession(channelId); - } - } - - if (_started) - { - try - { - session.start(); - } - catch (AMQException e) - { - throw new JMSAMQException(e); - } - } - - return session; } - }.execute(this); - } + + return session; + } + }, this).execute(); } private void createChannelOverWire(int channelId, int prefetchHigh, int prefetchLow, boolean transacted) - throws AMQException + throws AMQException, FailoverException { // TODO: Be aware of possible changes to parameter order as versions change. _protocolHandler.syncWrite(ChannelOpenBody.createAMQFrame(channelId, _protocolHandler.getProtocolMajorVersion(), - _protocolHandler.getProtocolMinorVersion(), null), // outOfBand - ChannelOpenOkBody.class); + _protocolHandler.getProtocolMinorVersion(), null), // outOfBand + ChannelOpenOkBody.class); // todo send low water mark when protocol allows. // todo Be aware of possible changes to parameter order as versions change. _protocolHandler.syncWrite(BasicQosBody.createAMQFrame(channelId, _protocolHandler.getProtocolMajorVersion(), - _protocolHandler.getProtocolMinorVersion(), false, // global - prefetchHigh, // prefetchCount - 0), // prefetchSize - BasicQosOkBody.class); + _protocolHandler.getProtocolMinorVersion(), false, // global + prefetchHigh, // prefetchCount + 0), // prefetchSize + BasicQosOkBody.class); if (transacted) { @@ -585,11 +596,12 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect // TODO: Be aware of possible changes to parameter order as versions change. _protocolHandler.syncWrite(TxSelectBody.createAMQFrame(channelId, _protocolHandler.getProtocolMajorVersion(), - _protocolHandler.getProtocolMinorVersion()), TxSelectOkBody.class); + _protocolHandler.getProtocolMinorVersion()), TxSelectOkBody.class); } } - private void reopenChannel(int channelId, int prefetchHigh, int prefetchLow, boolean transacted) throws AMQException + private void reopenChannel(int channelId, int prefetchHigh, int prefetchLow, boolean transacted) + throws AMQException, FailoverException { try { @@ -861,7 +873,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } public ConnectionConsumer createConnectionConsumer(Destination destination, String messageSelector, - ServerSessionPool sessionPool, int maxMessages) throws JMSException + ServerSessionPool sessionPool, int maxMessages) throws JMSException { checkNotClosed(); @@ -869,7 +881,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } public ConnectionConsumer createConnectionConsumer(Queue queue, String messageSelector, ServerSessionPool sessionPool, - int maxMessages) throws JMSException + int maxMessages) throws JMSException { checkNotClosed(); @@ -877,7 +889,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } public ConnectionConsumer createConnectionConsumer(Topic topic, String messageSelector, ServerSessionPool sessionPool, - int maxMessages) throws JMSException + int maxMessages) throws JMSException { checkNotClosed(); @@ -885,7 +897,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect } public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName, String messageSelector, - ServerSessionPool sessionPool, int maxMessages) throws JMSException + ServerSessionPool sessionPool, int maxMessages) throws JMSException { // TODO Auto-generated method stub checkNotClosed(); @@ -1077,8 +1089,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect if (code != null) { je = - new JMSException(Integer.toString(code.getCode()), "Exception thrown against " + toString() + ": " - + cause); + new JMSException(Integer.toString(code.getCode()), "Exception thrown against " + toString() + ": " + + cause); } else { @@ -1142,7 +1154,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect * For all sessions, and for all consumers in those sessions, resubscribe. This is called during failover handling. * The caller must hold the failover mutex before calling this method. */ - public void resubscribeSessions() throws JMSException, AMQException + public void resubscribeSessions() throws JMSException, AMQException, FailoverException { ArrayList sessions = new ArrayList(_sessions.values()); _logger.info(MessageFormat.format("Resubscribing sessions = {0} sessions.size={1}", sessions, sessions.size())); // FIXME: removeKey? @@ -1184,7 +1196,7 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect public Reference getReference() throws NamingException { return new Reference(AMQConnection.class.getName(), new StringRefAddr(AMQConnection.class.getName(), toURL()), - AMQConnectionFactory.class.getName(), null); // factory location + AMQConnectionFactory.class.getName(), null); // factory location } public SSLConfiguration getSSLConfiguration() diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java index 585991d905..cc5af07b20 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java @@ -60,9 +60,9 @@ public abstract class AMQDestination implements Destination, Referenceable private static final int IS_EXCLUSIVE_MASK = 0x2; private static final int IS_AUTODELETE_MASK = 0x4; - public static final byte QUEUE_TYPE = 1; - public static final byte TOPIC_TYPE = 2; - public static final byte UNKNOWN_TYPE = 3; + public static final Integer QUEUE_TYPE = Integer.valueOf(1); + public static final Integer TOPIC_TYPE = Integer.valueOf(2); + public static final Integer UNKNOWN_TYPE = Integer.valueOf(3); protected AMQDestination(String url) throws URLSyntaxException { @@ -213,7 +213,7 @@ public abstract class AMQDestination implements Destination, Referenceable } public String toURL() - { + { String url = _url; if(url == null) { diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java b/java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java index 4662f80c5b..28e5992b26 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQQueueBrowser.java @@ -20,9 +20,8 @@ */ package org.apache.qpid.client; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.concurrent.atomic.AtomicBoolean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.IllegalStateException; import javax.jms.JMSException; @@ -30,12 +29,13 @@ import javax.jms.Message; import javax.jms.Queue; import javax.jms.QueueBrowser; -import org.apache.log4j.Logger; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.concurrent.atomic.AtomicBoolean; public class AMQQueueBrowser implements QueueBrowser { - private static final Logger _logger = Logger.getLogger(AMQQueueBrowser.class); - + private static final Logger _logger = LoggerFactory.getLogger(AMQQueueBrowser.class); private AtomicBoolean _isClosed = new AtomicBoolean(); private final AMQSession _session; @@ -43,20 +43,21 @@ public class AMQQueueBrowser implements QueueBrowser private final ArrayList<BasicMessageConsumer> _consumers = new ArrayList<BasicMessageConsumer>(); private final String _messageSelector; - AMQQueueBrowser(AMQSession session, AMQQueue queue, String messageSelector) throws JMSException { _session = session; _queue = queue; - _messageSelector = (messageSelector == null) || (messageSelector.trim().length() == 0) ? null : messageSelector; + _messageSelector = ((messageSelector == null) || (messageSelector.trim().length() == 0)) ? null : messageSelector; // Create Consumer to verify message selector. - BasicMessageConsumer consumer = (BasicMessageConsumer) _session.createBrowserConsumer(_queue, _messageSelector, false); - consumer.close(); + BasicMessageConsumer consumer = + (BasicMessageConsumer) _session.createBrowserConsumer(_queue, _messageSelector, false); + consumer.close(); } public Queue getQueue() throws JMSException { checkState(); + return _queue; } @@ -66,6 +67,7 @@ public class AMQQueueBrowser implements QueueBrowser { throw new IllegalStateException("Queue Browser"); } + if (_session.isClosed()) { throw new IllegalStateException("Session is closed"); @@ -77,47 +79,48 @@ public class AMQQueueBrowser implements QueueBrowser { checkState(); + return _messageSelector; } public Enumeration getEnumeration() throws JMSException { checkState(); - final BasicMessageConsumer consumer = (BasicMessageConsumer) _session.createBrowserConsumer(_queue, _messageSelector, false); + final BasicMessageConsumer consumer = + (BasicMessageConsumer) _session.createBrowserConsumer(_queue, _messageSelector, false); _consumers.add(consumer); return new Enumeration() - { - - - Message _nextMessage = consumer.receive(); - - - public boolean hasMoreElements() { - _logger.info("QB:hasMoreElements:" + (_nextMessage != null)); - return (_nextMessage != null); - } - public Object nextElement() - { - Message msg = _nextMessage; - try + Message _nextMessage = consumer.receive(); + + public boolean hasMoreElements() { - _logger.info("QB:nextElement about to receive"); + _logger.info("QB:hasMoreElements:" + (_nextMessage != null)); - _nextMessage = consumer.receive(); - _logger.info("QB:nextElement received:" + _nextMessage); + return (_nextMessage != null); } - catch (JMSException e) + + public Object nextElement() { - _logger.warn("Exception caught while queue browsing", e); - _nextMessage = null; + Message msg = _nextMessage; + try + { + _logger.info("QB:nextElement about to receive"); + + _nextMessage = consumer.receive(); + _logger.info("QB:nextElement received:" + _nextMessage); + } + catch (JMSException e) + { + _logger.warn("Exception caught while queue browsing", e); + _nextMessage = null; + } + + return msg; } - - return msg; - } - }; + }; } public void close() throws JMSException @@ -126,8 +129,8 @@ public class AMQQueueBrowser implements QueueBrowser { consumer.close(); } + _consumers.clear(); } - } 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 8796a225ba..c2b7bc26c4 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java @@ -20,47 +20,15 @@ */ package org.apache.qpid.client; -import java.io.Serializable; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.Map; -import java.util.Arrays; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import javax.jms.BytesMessage; -import javax.jms.Destination; -import javax.jms.IllegalStateException; -import javax.jms.InvalidDestinationException; -import javax.jms.InvalidSelectorException; -import javax.jms.JMSException; -import javax.jms.MapMessage; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.ObjectMessage; -import javax.jms.Queue; -import javax.jms.QueueBrowser; -import javax.jms.QueueReceiver; -import javax.jms.QueueSender; -import javax.jms.QueueSession; -import javax.jms.StreamMessage; -import javax.jms.TemporaryQueue; -import javax.jms.TemporaryTopic; -import javax.jms.TextMessage; -import javax.jms.Topic; -import javax.jms.TopicPublisher; -import javax.jms.TopicSession; -import javax.jms.TopicSubscriber; - import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.AMQUndeliveredException; -import org.apache.qpid.AMQInvalidRoutingKeyException; import org.apache.qpid.AMQInvalidArgumentException; -import org.apache.qpid.client.failover.FailoverSupport; +import org.apache.qpid.AMQInvalidRoutingKeyException; +import org.apache.qpid.AMQUndeliveredException; +import org.apache.qpid.client.failover.FailoverException; +import org.apache.qpid.client.failover.FailoverNoopSupport; +import org.apache.qpid.client.failover.FailoverProtectedOperation; +import org.apache.qpid.client.failover.FailoverRetrySupport; import org.apache.qpid.client.message.AbstractJMSMessage; import org.apache.qpid.client.message.JMSBytesMessage; import org.apache.qpid.client.message.JMSMapMessage; @@ -70,21 +38,20 @@ import org.apache.qpid.client.message.JMSTextMessage; import org.apache.qpid.client.message.MessageFactoryRegistry; import org.apache.qpid.client.message.UnprocessedMessage; import org.apache.qpid.client.protocol.AMQProtocolHandler; -import org.apache.qpid.client.protocol.BlockingMethodFrameListener; import org.apache.qpid.client.util.FlowControllingBlockingQueue; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.AccessRequestBody; -import org.apache.qpid.framing.AccessRequestOkBody; import org.apache.qpid.framing.BasicAckBody; import org.apache.qpid.framing.BasicConsumeBody; import org.apache.qpid.framing.BasicConsumeOkBody; import org.apache.qpid.framing.BasicRecoverBody; +import org.apache.qpid.framing.BasicRecoverOkBody; +import org.apache.qpid.framing.BasicRejectBody; import org.apache.qpid.framing.ChannelCloseBody; import org.apache.qpid.framing.ChannelCloseOkBody; import org.apache.qpid.framing.ChannelFlowBody; +import org.apache.qpid.framing.ChannelFlowOkBody; import org.apache.qpid.framing.ExchangeBoundBody; import org.apache.qpid.framing.ExchangeBoundOkBody; import org.apache.qpid.framing.ExchangeDeclareBody; @@ -92,358 +59,242 @@ import org.apache.qpid.framing.ExchangeDeclareOkBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.FieldTableFactory; import org.apache.qpid.framing.QueueBindBody; +import org.apache.qpid.framing.QueueBindOkBody; import org.apache.qpid.framing.QueueDeclareBody; +import org.apache.qpid.framing.QueueDeclareOkBody; import org.apache.qpid.framing.QueueDeleteBody; import org.apache.qpid.framing.QueueDeleteOkBody; import org.apache.qpid.framing.TxCommitBody; import org.apache.qpid.framing.TxCommitOkBody; import org.apache.qpid.framing.TxRollbackBody; import org.apache.qpid.framing.TxRollbackOkBody; -import org.apache.qpid.framing.QueueBindOkBody; -import org.apache.qpid.framing.QueueDeclareOkBody; -import org.apache.qpid.framing.ChannelFlowOkBody; -import org.apache.qpid.framing.BasicRecoverOkBody; -import org.apache.qpid.framing.BasicRejectBody; import org.apache.qpid.jms.Session; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.url.AMQBindingURL; import org.apache.qpid.url.URLSyntaxException; +import javax.jms.BytesMessage; +import javax.jms.Destination; +import javax.jms.IllegalStateException; +import javax.jms.InvalidDestinationException; +import javax.jms.InvalidSelectorException; +import javax.jms.JMSException; +import javax.jms.MapMessage; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.QueueBrowser; +import javax.jms.QueueReceiver; +import javax.jms.QueueSender; +import javax.jms.QueueSession; +import javax.jms.StreamMessage; +import javax.jms.TemporaryQueue; +import javax.jms.TemporaryTopic; +import javax.jms.TextMessage; +import javax.jms.Topic; +import javax.jms.TopicPublisher; +import javax.jms.TopicSession; +import javax.jms.TopicSubscriber; +import java.io.Serializable; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +/** + */ public class AMQSession extends Closeable implements Session, QueueSession, TopicSession { + /** Used for debugging. */ private static final Logger _logger = Logger.getLogger(AMQSession.class); + /** Used for debugging in the dispatcher. */ + private static final Logger _dispatcherLogger = Logger.getLogger(Dispatcher.class); + + /** The default maximum number of prefetched message at which to suspend the channel. */ public static final int DEFAULT_PREFETCH_HIGH_MARK = 5000; + + /** The default minimum number of prefetched messages at which to resume the channel. */ public static final int DEFAULT_PREFETCH_LOW_MARK = 2500; + /** + * The default value for immediate flag used by producers created by this session is false. That is, a consumer does + * not need to be attached to a queue. + */ + protected static final boolean DEFAULT_IMMEDIATE = false; + + /** + * The default value for mandatory flag used by producers created by this session is true. That is, server will not + * silently drop messages where no queue is connected to the exchange for the message. + */ + protected static final boolean DEFAULT_MANDATORY = true; + + /** System property to enable strict AMQP compliance. */ + public static final String STRICT_AMQP = "STRICT_AMQP"; + + /** Strict AMQP default setting. */ + public static final String STRICT_AMQP_DEFAULT = "false"; + + /** System property to enable failure if strict AMQP compliance is violated. */ + public static final String STRICT_AMQP_FATAL = "STRICT_AMQP_FATAL"; + + /** Strickt AMQP failure default. */ + public static final String STRICT_AMQP_FATAL_DEFAULT = "true"; + + /** System property to enable immediate message prefetching. */ + public static final String IMMEDIATE_PREFETCH = "IMMEDIATE_PREFETCH"; + + /** Immediate message prefetch default. */ + public static final String IMMEDIATE_PREFETCH_DEFAULT = "false"; + + /** The connection to which this session belongs. */ private AMQConnection _connection; + /** Used to indicate whether or not this is a transactional session. */ private boolean _transacted; + /** Holds the sessions acknowledgement mode. */ private int _acknowledgeMode; + /** Holds this session unique identifier, used to distinguish it from other sessions. */ private int _channelId; + /** @todo This does not appear to be set? */ private int _ticket; + /** Holds the high mark for prefetched message, at which the session is suspended. */ private int _defaultPrefetchHighMark = DEFAULT_PREFETCH_HIGH_MARK; + + /** Holds the low mark for prefetched messages, below which the session is resumed. */ private int _defaultPrefetchLowMark = DEFAULT_PREFETCH_LOW_MARK; + /** Holds the message listener, if any, which is attached to this session. */ private MessageListener _messageListener = null; + /** Used to indicate that this session has been started at least once. */ private AtomicBoolean _startedAtLeastOnce = new AtomicBoolean(false); /** - * Used to reference durable subscribers so they requests for unsubscribe can be handled correctly. Note this only - * keeps a record of subscriptions which have been created in the current instance. It does not remember - * subscriptions between executions of the client + * Used to reference durable subscribers so that requests for unsubscribe can be handled correctly. Note this only + * keeps a record of subscriptions which have been created in the current instance. It does not remember + * subscriptions between executions of the client. */ private final ConcurrentHashMap<String, TopicSubscriberAdaptor> _subscriptions = new ConcurrentHashMap<String, TopicSubscriberAdaptor>(); + + /** + * Holds a mapping from message consumers to their identifying names, so that their subscriptions may be looked up + * in the {@link #_subscriptions} map. + */ private final ConcurrentHashMap<BasicMessageConsumer, String> _reverseSubscriptionMap = new ConcurrentHashMap<BasicMessageConsumer, String>(); - /** Used in the consume method. We generate the consume tag on the client so that we can use the nowait feature. */ - private int _nextTag = 1; - - /** This queue is bounded and is used to store messages before being dispatched to the consumer */ + /** + * Used to hold incoming messages. + * + * @todo Weaken the type once {@link FlowControllingBlockingQueue} implements Queue. + */ private final FlowControllingBlockingQueue _queue; + /** Holds the dispatcher thread for this session. */ private Dispatcher _dispatcher; + /** Holds the message factory factory for this session. */ private MessageFactoryRegistry _messageFactoryRegistry; - /** Set of all producers created by this session */ - private Map _producers = new ConcurrentHashMap(); - - /** Maps from consumer tag (String) to JMSMessageConsumer instance */ - private Map<AMQShortString, BasicMessageConsumer> _consumers = new ConcurrentHashMap<AMQShortString, BasicMessageConsumer>(); - - /** Maps from destination to count of JMSMessageConsumers */ - private ConcurrentHashMap<Destination, AtomicInteger> _destinationConsumerCount = - new ConcurrentHashMap<Destination, AtomicInteger>(); + /** Holds all of the producers created by this session, keyed by their unique identifiers. */ + private Map<Long, MessageProducer> _producers = new ConcurrentHashMap<Long, MessageProducer>(); /** - * Default value for immediate flag used by producers created by this session is false, i.e. a consumer does not - * need to be attached to a queue + * Used as a source of unique identifiers so that the consumers can be tagged to match them to BasicConsume + * methods. */ - protected static final boolean DEFAULT_IMMEDIATE = false; + private int _nextTag = 1; /** - * Default value for mandatory flag used by producers created by this sessio is true, i.e. server will not silently - * drop messages where no queue is connected to the exchange for the message + * Maps from identifying tags to message consumers, in order to pass dispatch incoming messages to the right + * consumer. */ - protected static final boolean DEFAULT_MANDATORY = true; + private Map<AMQShortString, BasicMessageConsumer> _consumers = + new ConcurrentHashMap<AMQShortString, BasicMessageConsumer>(); + + /** Provides a count of consumers on destinations, in order to be able to know if a destination has consumers. */ + private ConcurrentHashMap<Destination, AtomicInteger> _destinationConsumerCount = + new ConcurrentHashMap<Destination, AtomicInteger>(); /** - * The counter of the next producer id. This id is generated by the session and used only to allow the producer to - * identify itself to the session when deregistering itself. <p/> Access to this id does not require to be - * synchronized since according to the JMS specification only one thread of control is allowed to create producers - * for any given session instance. + * Used as a source of unique identifiers for producers within the session. + * + * <p/> Access to this id does not require to be synchronized since according to the JMS specification only one + * thread of control is allowed to create producers for any given session instance. */ private long _nextProducerId; - /** * Set when recover is called. This is to handle the case where recover() is called by application code during - * onMessage() processing. We need to make sure we do not send an auto ack if recover was called. + * onMessage() processing to enure that an auto ack is not sent. */ private boolean _inRecovery; + /** Used to indicates that the connection to which this session belongs, has been stopped. */ private boolean _connectionStopped; + /** Used to indicate that this session has a message listener attached to it. */ private boolean _hasMessageListeners; + /** Used to indicate that this session has been suspended. */ private boolean _suspended; + /** + * Used to protect the suspension of this session, so that critical code can be executed during suspension, without + * the session being resumed by other threads. + */ private final Object _suspensionLock = new Object(); - /** Boolean to control immediate prefetch . Records the first call to the dispatcher to prevent further flow(true) */ + /** + * Used to ensure that onlt the first call to start the dispatcher can unsuspend the channel. + * + * @todo This is accessed only within a synchronized method, so does not need to be atomic. + */ private final AtomicBoolean _firstDispatcher = new AtomicBoolean(true); - /** System property to enable strickt AMQP compliance */ - public static final String STRICT_AMQP = "STRICT_AMQP"; - /** Strickt AMQP default */ - public static final String STRICT_AMQP_DEFAULT = "false"; + /** Used to indicate that the session should start pre-fetching messages as soon as it is started. */ + private final boolean _immediatePrefetch; + /** Indicates that warnings should be generated on violations of the strict AMQP. */ private final boolean _strictAMQP; - /** System property to enable strickt AMQP compliance */ - public static final String STRICT_AMQP_FATAL = "STRICT_AMQP_FATAL"; - /** Strickt AMQP default */ - public static final String STRICT_AMQP_FATAL_DEFAULT = "true"; - + /** Indicates that runtime exceptions should be generated on vilations of the strict AMQP. */ private final boolean _strictAMQPFATAL; - /** System property to enable immediate message prefetching */ - public static final String IMMEDIATE_PREFETCH = "IMMEDIATE_PREFETCH"; - /** Immediate message prefetch default */ - public static final String IMMEDIATE_PREFETCH_DEFAULT = "false"; - - private final boolean _immediatePrefetch; - - private static final Logger _dispatcherLogger = Logger.getLogger(Dispatcher.class); - - /** Responsible for decoding a message fragment and passing it to the appropriate message consumer. */ - private class Dispatcher extends Thread - { - - /** Track the 'stopped' state of the dispatcher, a session starts in the stopped state. */ - private final AtomicBoolean _closed = new AtomicBoolean(false); - - private final Object _lock = new Object(); - - public Dispatcher() - { - super("Dispatcher-Channel-" + _channelId); - if (_dispatcherLogger.isInfoEnabled()) - { - _dispatcherLogger.info(getName() + " created"); - } - } - - public void run() - { - if (_dispatcherLogger.isInfoEnabled()) - { - _dispatcherLogger.info(getName() + " started"); - } - - UnprocessedMessage message; - - // Allow disptacher to start stopped - synchronized (_lock) - { - while (connectionStopped()) - { - try - { - _lock.wait(); - } - catch (InterruptedException e) - { - // ignore - } - } - } - - try - { - while (!_closed.get() && (message = (UnprocessedMessage) _queue.take()) != null) - { - synchronized (_lock) - { - - while (connectionStopped()) - { - _lock.wait(); - } - - dispatchMessage(message); - - while (connectionStopped()) - { - _lock.wait(); - } - - } - - } - } - catch (InterruptedException e) - { - //ignore - } - if (_dispatcherLogger.isInfoEnabled()) - { - _dispatcherLogger.info(getName() + " thread terminating for channel " + _channelId); - } - } - - // only call while holding lock - final boolean connectionStopped() - { - return _connectionStopped; - } - - boolean setConnectionStopped(boolean connectionStopped) - { - boolean currently; - synchronized (_lock) - { - currently = _connectionStopped; - _connectionStopped = connectionStopped; - _lock.notify(); - - if (_dispatcherLogger.isDebugEnabled()) - { - _dispatcherLogger.debug("Set Dispatcher Connection " + (connectionStopped ? "Stopped" : "Started") + - ": Currently " + (currently ? "Stopped" : "Started")); - } - } - return currently; - } - - private void dispatchMessage(UnprocessedMessage message) - { - if (message.getDeliverBody() != null) - { - final BasicMessageConsumer consumer = (BasicMessageConsumer) _consumers.get(message.getDeliverBody().consumerTag); - - if (consumer == null || consumer.isClosed()) - { - if (_dispatcherLogger.isInfoEnabled()) - { - if (consumer == null) - { - _dispatcherLogger.info("Received a message(" + System.identityHashCode(message) + ")" + - "[" + message.getDeliverBody().deliveryTag + "] from queue " + - message.getDeliverBody().consumerTag + - " )without a handler - rejecting(requeue)..."); - } - else - { - _dispatcherLogger.info("Received a message(" + System.identityHashCode(message) + ")" + - "[" + message.getDeliverBody().deliveryTag + "] from queue " + - " consumer(" + consumer.debugIdentity() + - ") is closed rejecting(requeue)..."); - } - } - // Don't reject if we're already closing - if (!_closed.get()) - { - rejectMessage(message, true); - } - } - else - { - consumer.notifyMessage(message, _channelId); - } - } - } - - public void close() - { - _closed.set(true); - interrupt(); - - //fixme awaitTermination - - } - - public void rollback() - { - - synchronized (_lock) - { - boolean isStopped = connectionStopped(); - - if (!isStopped) - { - setConnectionStopped(true); - } - - rejectAllMessages(true); - - _dispatcherLogger.debug("Session Pre Dispatch Queue cleared"); - - for (BasicMessageConsumer consumer : _consumers.values()) - { - if (!consumer.isNoConsume()) - { - consumer.rollback(); - } - else - { - // should perhaps clear the _SQ here. - //consumer._synchronousQueue.clear(); - consumer.clearReceiveQueue(); - } - - - } - - setConnectionStopped(isStopped); - } - - } - - public void rejectPending(BasicMessageConsumer consumer) - { - synchronized (_lock) - { - boolean stopped = _dispatcher.connectionStopped(); - - if (!stopped) - { - _dispatcher.setConnectionStopped(true); - } - - // Reject messages on pre-receive queue - consumer.rollback(); - - // Reject messages on pre-dispatch queue - rejectMessagesForConsumerTag(consumer.getConsumerTag(), true); - - // closeConsumer - consumer.markClosed(); - - _dispatcher.setConnectionStopped(stopped); - - } - } - } - - - + /** + * Creates a new session on a connection. + * + * @param con The connection on which to create the session. + * @param channelId The unique identifier for the session. + * @param transacted Indicates whether or not the session is transactional. + * @param acknowledgeMode The acknoledgement mode for the session. + * @param messageFactoryRegistry The message factory factory for the session. + * @param defaultPrefetchHighMark The maximum number of messages to prefetched before suspending the session. + * @param defaultPrefetchLowMark The number of prefetched messages at which to resume the session. + */ AMQSession(AMQConnection con, int channelId, boolean transacted, int acknowledgeMode, MessageFactoryRegistry messageFactoryRegistry, int defaultPrefetchHighMark, int defaultPrefetchLowMark) { _strictAMQP = Boolean.parseBoolean(System.getProperties().getProperty(STRICT_AMQP, STRICT_AMQP_DEFAULT)); - _strictAMQPFATAL = Boolean.parseBoolean(System.getProperties().getProperty(STRICT_AMQP_FATAL, STRICT_AMQP_FATAL_DEFAULT)); - _immediatePrefetch = _strictAMQP || Boolean.parseBoolean(System.getProperties().getProperty(IMMEDIATE_PREFETCH, IMMEDIATE_PREFETCH_DEFAULT)); + _strictAMQPFATAL = + Boolean.parseBoolean(System.getProperties().getProperty(STRICT_AMQP_FATAL, STRICT_AMQP_FATAL_DEFAULT)); + _immediatePrefetch = + _strictAMQP + || Boolean.parseBoolean(System.getProperties().getProperty(IMMEDIATE_PREFETCH, IMMEDIATE_PREFETCH_DEFAULT)); _connection = con; _transacted = transacted; @@ -455,6 +306,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi { _acknowledgeMode = acknowledgeMode; } + _channelId = channelId; _messageFactoryRegistry = messageFactoryRegistry; _defaultPrefetchHighMark = defaultPrefetchHighMark; @@ -462,27 +314,32 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi if (_acknowledgeMode == NO_ACKNOWLEDGE) { - _queue = new FlowControllingBlockingQueue(_defaultPrefetchHighMark, _defaultPrefetchLowMark, - new FlowControllingBlockingQueue.ThresholdListener() - { - public void aboveThreshold(int currentValue) - { - if (_acknowledgeMode == NO_ACKNOWLEDGE) - { - _logger.warn("Above threshold(" + _defaultPrefetchHighMark + ") so suspending channel. Current value is " + currentValue); - new Thread(new SuspenderRunner(true)).start(); - } - } - - public void underThreshold(int currentValue) - { - if (_acknowledgeMode == NO_ACKNOWLEDGE) - { - _logger.warn("Below threshold(" + _defaultPrefetchLowMark + ") so unsuspending channel. Current value is " + currentValue); - new Thread(new SuspenderRunner(false)).start(); - } - } - }); + _queue = + new FlowControllingBlockingQueue(_defaultPrefetchHighMark, _defaultPrefetchLowMark, + new FlowControllingBlockingQueue.ThresholdListener() + { + public void aboveThreshold(int currentValue) + { + if (_acknowledgeMode == NO_ACKNOWLEDGE) + { + _logger.debug( + "Above threshold(" + _defaultPrefetchHighMark + + ") so suspending channel. Current value is " + currentValue); + new Thread(new SuspenderRunner(true)).start(); + } + } + + public void underThreshold(int currentValue) + { + if (_acknowledgeMode == NO_ACKNOWLEDGE) + { + _logger.debug( + "Below threshold(" + _defaultPrefetchLowMark + + ") so unsuspending channel. Current value is " + currentValue); + new Thread(new SuspenderRunner(false)).start(); + } + } + }); } else { @@ -490,183 +347,141 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi } } - - AMQSession(AMQConnection con, int channelId, boolean transacted, int acknowledgeMode, int defaultPrefetchHigh, int defaultPrefetchLow) - { - this(con, channelId, transacted, acknowledgeMode, MessageFactoryRegistry.newDefaultRegistry(), defaultPrefetchHigh, defaultPrefetchLow); - } - - public AMQConnection getAMQConnection() - { - return _connection; - } - - public BytesMessage createBytesMessage() throws JMSException + /** + * Creates a new session on a connection with the default message factory factory. + * + * @param con The connection on which to create the session. + * @param channelId The unique identifier for the session. + * @param transacted Indicates whether or not the session is transactional. + * @param acknowledgeMode The acknoledgement mode for the session. + * @param defaultPrefetchHigh The maximum number of messages to prefetched before suspending the session. + * @param defaultPrefetchLow The number of prefetched messages at which to resume the session. + */ + AMQSession(AMQConnection con, int channelId, boolean transacted, int acknowledgeMode, int defaultPrefetchHigh, + int defaultPrefetchLow) { - synchronized (_connection.getFailoverMutex()) - { - checkNotClosed(); - return new JMSBytesMessage(); - } + this(con, channelId, transacted, acknowledgeMode, MessageFactoryRegistry.newDefaultRegistry(), defaultPrefetchHigh, + defaultPrefetchLow); } - public MapMessage createMapMessage() throws JMSException + /** + * Acknowledges all unacknowledged messages on the session, for all message consumers on the session. + * + * @throws IllegalStateException If the session is closed. + */ + public void acknowledge() throws IllegalStateException { - synchronized (_connection.getFailoverMutex()) + if (isClosed()) { - checkNotClosed(); - return new JMSMapMessage(); + throw new IllegalStateException("Session is already closed"); } - } - - public javax.jms.Message createMessage() throws JMSException - { - return createBytesMessage(); - } - public ObjectMessage createObjectMessage() throws JMSException - { - synchronized (_connection.getFailoverMutex()) + for (BasicMessageConsumer consumer : _consumers.values()) { - checkNotClosed(); - return (ObjectMessage) new JMSObjectMessage(); + consumer.acknowledge(); } } - public ObjectMessage createObjectMessage(Serializable object) throws JMSException - { - ObjectMessage msg = createObjectMessage(); - msg.setObject(object); - return msg; - } - - public StreamMessage createStreamMessage() throws JMSException + /** + * Acknowledge one or many messages. + * + * @param deliveryTag The tag of the last message to be acknowledged. + * @param multiple <tt>true</tt> to acknowledge all messages up to and including the one specified by the + * delivery tag, <tt>false</tt> to just acknowledge that message. + * + * @todo Be aware of possible changes to parameter order as versions change. + */ + public void acknowledgeMessage(long deliveryTag, boolean multiple) { - synchronized (_connection.getFailoverMutex()) - { - checkNotClosed(); - - return new JMSStreamMessage(); - } - } + final AMQFrame ackFrame = + BasicAckBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), deliveryTag, + multiple); - public TextMessage createTextMessage() throws JMSException - { - synchronized (_connection.getFailoverMutex()) + if (_logger.isDebugEnabled()) { - checkNotClosed(); - - return new JMSTextMessage(); + _logger.debug("Sending ack for delivery tag " + deliveryTag + " on channel " + _channelId); } - } - - public TextMessage createTextMessage(String text) throws JMSException - { - - TextMessage msg = createTextMessage(); - msg.setText(text); - return msg; - } - - public boolean getTransacted() throws JMSException - { - checkNotClosed(); - return _transacted; - } - - public int getAcknowledgeMode() throws JMSException - { - checkNotClosed(); - return _acknowledgeMode; - } - - public void commit() throws JMSException - { - checkTransacted(); - 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();) - { - //Sends acknowledgement to server - i.next().acknowledgeLastDelivered(); - } - - // Commits outstanding messages sent and outstanding acknowledgements. - // TODO: Be aware of possible changes to parameter order as versions change. - final AMQProtocolHandler handler = getProtocolHandler(); - handler.syncWrite(TxCommitBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), - getProtocolMinorVersion()), - TxCommitOkBody.class); - } - catch (AMQException e) - { - JMSException exception = new JMSException("Failed to commit: " + e.getMessage()); - exception.setLinkedException(e); - throw exception; - } + getProtocolHandler().writeFrame(ackFrame); } - - public void rollback() throws JMSException + /** + * Binds the named queue, with the specified routing key, to the named exchange. + * + * <p/>Note that this operation automatically retries in the event of fail-over. + * + * @param queueName The name of the queue to bind. + * @param routingKey The routing key to bind the queue with. + * @param arguments Additional arguments. + * @param exchangeName The exchange to bind the queue on. + * + * @throws AMQException If the queue cannot be bound for any reason. + * @todo Be aware of possible changes to parameter order as versions change. + * @todo Document the additional arguments that may be passed in the field table. Are these for headers exchanges? + */ + public void bindQueue(final AMQShortString queueName, final AMQShortString routingKey, final FieldTable arguments, + final AMQShortString exchangeName) throws AMQException { - synchronized (_suspensionLock) + /*new FailoverRetrySupport<Object, AMQException>(new FailoverProtectedOperation<Object, AMQException>()*/ + new FailoverNoopSupport<Object, AMQException>(new FailoverProtectedOperation<Object, AMQException>() { - checkTransacted(); - try - { - // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0) - // TODO: Connect this to the session version obtained from ProtocolInitiation for this session. - // Be aware of possible changes to parameter order as versions change. - - boolean isSuspended = isSuspended(); - - if (!isSuspended) - { - suspendChannel(true); - } - - if (_dispatcher != null) - { - _dispatcher.rollback(); - } - - _connection.getProtocolHandler().syncWrite( - TxRollbackBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion()), TxRollbackOkBody.class); - - - if (!isSuspended) - { - suspendChannel(false); - } - } - catch (AMQException e) + public Object execute() throws AMQException, FailoverException { - throw (JMSException) (new JMSException("Failed to rollback: " + e).initCause(e)); + AMQFrame queueBind = + QueueBindBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), + arguments, // arguments + exchangeName, // exchange + false, // nowait + queueName, // queue + routingKey, // routingKey + getTicket()); // ticket + + getProtocolHandler().syncWrite(queueBind, QueueBindOkBody.class); + + return null; } - } + }, _connection).execute(); } + /** + * Closes the session with no timeout. + * + * @throws JMSException If the JMS provider fails to close the session due to some internal error. + */ public void close() throws JMSException { close(-1); } + /** + * Closes the session. + * + * <p/>Note that this operation succeeds automatically if a fail-over interupts the sycnronous request to close the + * channel. This is because the channel is marked as closed before the request to close it is made, so the fail-over + * should not re-open it. + * + * @param timeout The timeout in milliseconds to wait for the session close acknoledgement from the broker. + * + * @throws JMSException If the JMS provider fails to close the session due to some internal error. + * @todo Be aware of possible changes to parameter order as versions change. + * @todo Not certain about the logic of ignoring the failover exception, because the channel won't be re-opened. May + * need to examine this more carefully. + * @todo Note that taking the failover mutex doesn't prevent this operation being interrupted by a failover, because + * the failover process sends the failover event before acquiring the mutex itself. + */ public void close(long timeout) throws JMSException { if (_logger.isInfoEnabled()) { - _logger.info("Closing session: " + this + ":" + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6)); + _logger.info("Closing session: " + this + ":" + + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6)); } // We must close down all producers and consumers in an orderly fashion. This is the only method - // that can be called from a different thread of control from the one controlling the session + // that can be called from a different thread of control from the one controlling the session. synchronized (_connection.getFailoverMutex()) { - //Ensure we only try and close an open session. + // Ensure we only try and close an open session. if (!_closed.getAndSet(true)) { // we pass null since this is not an error case @@ -676,18 +491,18 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi { getProtocolHandler().closeSession(this); - // TODO: Be aware of possible changes to parameter order as versions change. - final AMQFrame frame = ChannelCloseBody.createAMQFrame(getChannelId(), - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - 0, // classId - 0, // methodId - AMQConstant.REPLY_SUCCESS.getCode(), // replyCode - new AMQShortString("JMS client closing channel")); // replyText + + final AMQFrame frame = + ChannelCloseBody.createAMQFrame(getChannelId(), getProtocolMajorVersion(), getProtocolMinorVersion(), + 0, // classId + 0, // methodId + AMQConstant.REPLY_SUCCESS.getCode(), // replyCode + new AMQShortString("JMS client closing channel")); // replyText getProtocolHandler().syncWrite(frame, ChannelCloseOkBody.class, timeout); - // When control resumes at this point, a reply will have been received that - // indicates the broker has closed the channel successfully + // When control resumes at this point, a reply will have been received that + // indicates the broker has closed the channel successfully. } catch (AMQException e) { @@ -695,6 +510,13 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi jmse.setLinkedException(e); throw jmse; } + // This is ignored because the channel is already marked as closed so the fail-over process will + // not re-open it. + catch (FailoverException e) + { + _logger.debug( + "Got FailoverException during channel close, ignored as channel already marked as closed."); + } finally { _connection.deregisterSession(_channelId); @@ -703,65 +525,6 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi } } - private AMQProtocolHandler getProtocolHandler() - { - return _connection.getProtocolHandler(); - } - - - private byte getProtocolMinorVersion() - { - return getProtocolHandler().getProtocolMinorVersion(); - } - - private byte getProtocolMajorVersion() - { - return getProtocolHandler().getProtocolMajorVersion(); - } - - - /** - * Close all producers or consumers. This is called either in the error case or when closing the session normally. - * - * @param amqe the exception, may be null to indicate no error has occurred - */ - private void closeProducersAndConsumers(AMQException amqe) throws JMSException - { - JMSException jmse = null; - try - { - closeProducers(); - } - catch (JMSException e) - { - _logger.error("Error closing session: " + e, e); - jmse = e; - } - try - { - closeConsumers(amqe); - } - catch (JMSException e) - { - _logger.error("Error closing session: " + e, e); - if (jmse == null) - { - jmse = e; - } - } - if (jmse != null) - { - throw jmse; - } - } - - - public boolean isSuspended() - { - return _suspended; - } - - /** * Called when the server initiates the closure of the session unilaterally. * @@ -783,738 +546,341 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi { amqe = new AMQException(null, "Closing session forcibly", e); } + _connection.deregisterSession(_channelId); closeProducersAndConsumers(amqe); } } /** - * Called to mark the session as being closed. Useful when the session needs to be made invalid, e.g. after failover - * when the client has veoted resubscription. <p/> The caller of this method must already hold the failover mutex. + * Commits all messages done in this transaction and releases any locks currently held. + * + * <p/>If the commit fails, because the commit itself is interrupted by a fail-over between requesting that the + * commit be done, and receiving an acknowledgement that it has been done, then a JMSException will be thrown. The + * client will be unable to determine whether or not the commit actually happened on the broker in this case. + * + * @throws JMSException If the JMS provider fails to commit the transaction due to some internal error. This does + * not mean that the commit is known to have failed, merely that it is not known whether it + * failed or not. + * @todo Be aware of possible changes to parameter order as versions change. */ - void markClosed() + public void commit() throws JMSException { - _closed.set(true); - _connection.deregisterSession(_channelId); - markClosedProducersAndConsumers(); - - } + checkTransacted(); - private void markClosedProducersAndConsumers() - { - try - { - // no need for a markClosed* method in this case since there is no protocol traffic closing a producer - closeProducers(); - } - catch (JMSException e) - { - _logger.error("Error closing session: " + e, e); - } try { - markClosedConsumers(); - } - catch (JMSException e) - { - _logger.error("Error closing session: " + e, e); - } - } + // 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();) + { + // Sends acknowledgement to server + i.next().acknowledgeLastDelivered(); + } - /** - * Called to close message producers cleanly. This may or may <b>not</b> be as a result of an error. There is - * currently no way of propagating errors to message producers (this is a JMS limitation). - */ - private void closeProducers() throws JMSException - { - // we need to clone the list of producers since the close() method updates the _producers collection - // which would result in a concurrent modification exception - final ArrayList clonedProducers = new ArrayList(_producers.values()); + // Commits outstanding messages sent and outstanding acknowledgements. + final AMQProtocolHandler handler = getProtocolHandler(); - final Iterator it = clonedProducers.iterator(); - while (it.hasNext()) - { - final BasicMessageProducer prod = (BasicMessageProducer) it.next(); - prod.close(); + handler.syncWrite(TxCommitBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion()), + TxCommitOkBody.class); } - // at this point the _producers map is empty - } - - /** - * Called to close message consumers cleanly. This may or may <b>not</b> be as a result of an error. - * - * @param error not null if this is a result of an error occurring at the connection level - */ - private void closeConsumers(Throwable error) throws JMSException - { - if (_dispatcher != null) + catch (AMQException e) { - _dispatcher.close(); - _dispatcher = null; + throw new JMSAMQException("Failed to commit: " + e.getMessage(), e); } - // we need to clone the list of consumers since the close() method updates the _consumers collection - // which would result in a concurrent modification exception - final ArrayList<BasicMessageConsumer> clonedConsumers = new ArrayList(_consumers.values()); - - final Iterator<BasicMessageConsumer> it = clonedConsumers.iterator(); - while (it.hasNext()) + catch (FailoverException e) { - final BasicMessageConsumer con = it.next(); - if (error != null) - { - con.notifyError(error); - } - else - { - con.close(); - } + throw new JMSAMQException("Fail-over interrupted commit. Status of the commit is uncertain.", e); } - // at this point the _consumers map will be empty } - private void markClosedConsumers() throws JMSException + public void confirmConsumerCancelled(AMQShortString consumerTag) { - if (_dispatcher != null) - { - _dispatcher.close(); - _dispatcher = null; - } - // we need to clone the list of consumers since the close() method updates the _consumers collection - // which would result in a concurrent modification exception - final ArrayList<BasicMessageConsumer> clonedConsumers = new ArrayList<BasicMessageConsumer>(_consumers.values()); - - final Iterator<BasicMessageConsumer> it = clonedConsumers.iterator(); - while (it.hasNext()) - { - final BasicMessageConsumer con = it.next(); - con.markClosed(); - } - // at this point the _consumers map will be empty - } - /** - * Asks the broker to resend all unacknowledged messages for the session. - * - * @throws JMSException - */ - public void recover() throws JMSException - { - checkNotClosed(); - checkNotTransacted(); // throws IllegalStateException if a transacted session - // this is set only here, and the before the consumer's onMessage is called it is set to false - _inRecovery = true; - try + // Remove the consumer from the map + BasicMessageConsumer consumer = (BasicMessageConsumer) _consumers.get(consumerTag); + if (consumer != null) { - - boolean isSuspended = isSuspended(); - - if (!isSuspended) + // fixme this isn't right.. needs to check if _queue contains data for this consumer + if (consumer.isAutoClose()) // && _queue.isEmpty()) { - suspendChannel(true); + consumer.closeWhenNoMessages(true); } - for (BasicMessageConsumer consumer : _consumers.values()) + if (!consumer.isNoConsume()) { - consumer.clearUnackedMessages(); - } + // Clean the Maps up first + // Flush any pending messages for this consumerTag + if (_dispatcher != null) + { + _logger.info("Dispatcher is not null"); + } + else + { + _logger.info("Dispatcher is null so created stopped dispatcher"); - if (_dispatcher != null) - { - _dispatcher.rollback(); - } + startDistpatcherIfNecessary(true); + } - if (isStrictAMQP()) - { - // We can't use the BasicRecoverBody-OK method as it isn't part of the spec. - _connection.getProtocolHandler().writeFrame(BasicRecoverBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), - getProtocolMinorVersion(), - false)); // requeue - _logger.warn("Session Recover cannot be guaranteed with STRICT_AMQP. Messages may arrive out of order."); + _dispatcher.rejectPending(consumer); } else { + // Just close the consumer + // fixme the CancelOK is being processed before the arriving messages.. + // The dispatcher is still to process them so the server sent in order but the client + // has yet to receive before the close comes in. - // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0) - // TODO: Connect this to the session version obtained from ProtocolInitiation for this session. - // Be aware of possible changes to parameter order as versions change. - _connection.getProtocolHandler().syncWrite(BasicRecoverBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), - getProtocolMinorVersion(), - false) // requeue - , BasicRecoverOkBody.class); - } - if (!isSuspended) - { - suspendChannel(false); + // consumer.markClosed(); } } - catch (AMQException e) + else { - throw new JMSAMQException(e); + _logger.warn("Unable to confirm cancellation of consumer (" + consumerTag + "). Not found in consumer map."); } - } - - boolean isInRecovery() - { - return _inRecovery; - } - void setInRecovery(boolean inRecovery) - { - _inRecovery = inRecovery; } - public void acknowledge() throws JMSException + public QueueBrowser createBrowser(Queue queue) throws JMSException { - if (isClosed()) - { - throw new IllegalStateException("Session is already closed"); - } - for (BasicMessageConsumer consumer : _consumers.values()) + if (isStrictAMQP()) { - consumer.acknowledge(); + throw new UnsupportedOperationException(); } - - } - - - public MessageListener getMessageListener() throws JMSException - { -// checkNotClosed(); - return _messageListener; - } - - public void setMessageListener(MessageListener listener) throws JMSException - { -// checkNotClosed(); -// -// if (_dispatcher != null && !_dispatcher.connectionStopped()) -// { -// throw new javax.jms.IllegalStateException("Attempt to set listener while session is started."); -// } -// -// // We are stopped -// for (Iterator<BasicMessageConsumer> i = _consumers.values().iterator(); i.hasNext();) -// { -// BasicMessageConsumer consumer = i.next(); -// -// if (consumer.isReceiving()) -// { -// throw new javax.jms.IllegalStateException("Another thread is already receiving synchronously."); -// } -// } -// -// _messageListener = listener; -// -// for (Iterator<BasicMessageConsumer> i = _consumers.values().iterator(); i.hasNext();) -// { -// i.next().setMessageListener(_messageListener); -// } - + return createBrowser(queue, null); } - public void run() + public QueueBrowser createBrowser(Queue queue, String messageSelector) throws JMSException { - throw new java.lang.UnsupportedOperationException(); - } + if (isStrictAMQP()) + { + throw new UnsupportedOperationException(); + } - public BasicMessageProducer createProducer(Destination destination, boolean mandatory, - boolean immediate, boolean waitUntilSent) - throws JMSException - { - return createProducerImpl(destination, mandatory, immediate, waitUntilSent); - } + checkNotClosed(); + checkValidQueue(queue); - public BasicMessageProducer createProducer(Destination destination, boolean mandatory, boolean immediate) - throws JMSException - { - return createProducerImpl(destination, mandatory, immediate); + return new AMQQueueBrowser(this, (AMQQueue) queue, messageSelector); } - public BasicMessageProducer createProducer(Destination destination, boolean immediate) + public MessageConsumer createBrowserConsumer(Destination destination, String messageSelector, boolean noLocal) throws JMSException { - return createProducerImpl(destination, DEFAULT_MANDATORY, immediate); - } - - public BasicMessageProducer createProducer(Destination destination) throws JMSException - { - return createProducerImpl(destination, DEFAULT_MANDATORY, DEFAULT_IMMEDIATE); - } + checkValidDestination(destination); - private BasicMessageProducer createProducerImpl(Destination destination, boolean mandatory, - boolean immediate) - throws JMSException - { - return createProducerImpl(destination, mandatory, immediate, false); + return createConsumerImpl(destination, _defaultPrefetchHighMark, _defaultPrefetchLowMark, noLocal, false, + messageSelector, null, true, true); } - private BasicMessageProducer createProducerImpl(final Destination destination, final boolean mandatory, - final boolean immediate, final boolean waitUntilSent) - throws JMSException + public BytesMessage createBytesMessage() throws JMSException { - return (BasicMessageProducer) new FailoverSupport() + synchronized (_connection.getFailoverMutex()) { - public Object operation() throws JMSException - { - checkNotClosed(); - long producerId = getNextProducerId(); - BasicMessageProducer producer = new BasicMessageProducer(_connection, (AMQDestination) destination, _transacted, _channelId, - AMQSession.this, getProtocolHandler(), - producerId, immediate, mandatory, waitUntilSent); - registerProducer(producerId, producer); - return producer; - } - }.execute(_connection); - } - - /** - * Creates a QueueReceiver - * - * @param destination - * - * @return QueueReceiver - a wrapper around our MessageConsumer - * - * @throws JMSException - */ - public QueueReceiver createQueueReceiver(Destination destination) throws JMSException - { - checkValidDestination(destination); - AMQQueue dest = (AMQQueue) destination; - BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(destination); - return new QueueReceiverAdaptor(dest, consumer); - } + checkNotClosed(); - /** - * Creates a QueueReceiver using a message selector - * - * @param destination - * @param messageSelector - * - * @return QueueReceiver - a wrapper around our MessageConsumer - * - * @throws JMSException - */ - public QueueReceiver createQueueReceiver(Destination destination, String messageSelector) throws JMSException - { - checkValidDestination(destination); - AMQQueue dest = (AMQQueue) destination; - BasicMessageConsumer consumer = (BasicMessageConsumer) - createConsumer(destination, messageSelector); - return new QueueReceiverAdaptor(dest, consumer); + return new JMSBytesMessage(); + } } public MessageConsumer createConsumer(Destination destination) throws JMSException { checkValidDestination(destination); - return createConsumerImpl(destination, - _defaultPrefetchHighMark, - _defaultPrefetchLowMark, - false, - false, - null, - null, - false, - false); + + return createConsumerImpl(destination, _defaultPrefetchHighMark, _defaultPrefetchLowMark, false, false, null, null, + false, false); } public MessageConsumer createConsumer(Destination destination, String messageSelector) throws JMSException { checkValidDestination(destination); - return createConsumerImpl(destination, - _defaultPrefetchHighMark, - _defaultPrefetchLowMark, - false, - false, - messageSelector, - null, - false, - false); + + return createConsumerImpl(destination, _defaultPrefetchHighMark, _defaultPrefetchLowMark, false, false, + messageSelector, null, false, false); } public MessageConsumer createConsumer(Destination destination, String messageSelector, boolean noLocal) throws JMSException { checkValidDestination(destination); - return createConsumerImpl(destination, - _defaultPrefetchHighMark, - _defaultPrefetchLowMark, - noLocal, - false, - messageSelector, - null, - false, - false); + + return createConsumerImpl(destination, _defaultPrefetchHighMark, _defaultPrefetchLowMark, noLocal, false, + messageSelector, null, false, false); } - public MessageConsumer createBrowserConsumer(Destination destination, - String messageSelector, - boolean noLocal) - throws JMSException - { - checkValidDestination(destination); - return createConsumerImpl(destination, - _defaultPrefetchHighMark, - _defaultPrefetchLowMark, - noLocal, - false, - messageSelector, - null, - true, - true); - } - - public MessageConsumer createConsumer(Destination destination, - int prefetch, - boolean noLocal, - boolean exclusive, + public MessageConsumer createConsumer(Destination destination, int prefetch, boolean noLocal, boolean exclusive, String selector) throws JMSException { checkValidDestination(destination); + return createConsumerImpl(destination, prefetch, prefetch, noLocal, exclusive, selector, null, false, false); } - - public MessageConsumer createConsumer(Destination destination, - int prefetchHigh, - int prefetchLow, - boolean noLocal, - boolean exclusive, - String selector) throws JMSException + public MessageConsumer createConsumer(Destination destination, int prefetchHigh, int prefetchLow, boolean noLocal, + boolean exclusive, String selector) throws JMSException { checkValidDestination(destination); + return createConsumerImpl(destination, prefetchHigh, prefetchLow, noLocal, exclusive, selector, null, false, false); } - public MessageConsumer createConsumer(Destination destination, - int prefetch, - boolean noLocal, - boolean exclusive, - String selector, - FieldTable rawSelector) throws JMSException + public MessageConsumer createConsumer(Destination destination, int prefetch, boolean noLocal, boolean exclusive, + String selector, FieldTable rawSelector) throws JMSException { checkValidDestination(destination); - return createConsumerImpl(destination, prefetch, prefetch, noLocal, exclusive, - selector, rawSelector, false, false); + + return createConsumerImpl(destination, prefetch, prefetch, noLocal, exclusive, selector, rawSelector, false, false); } - public MessageConsumer createConsumer(Destination destination, - int prefetchHigh, - int prefetchLow, - boolean noLocal, - boolean exclusive, - String selector, - FieldTable rawSelector) throws JMSException + public MessageConsumer createConsumer(Destination destination, int prefetchHigh, int prefetchLow, boolean noLocal, + boolean exclusive, String selector, FieldTable rawSelector) throws JMSException { checkValidDestination(destination); - return createConsumerImpl(destination, prefetchHigh, prefetchLow, noLocal, exclusive, - selector, rawSelector, false, false); + + return createConsumerImpl(destination, prefetchHigh, prefetchLow, noLocal, exclusive, selector, rawSelector, false, + false); } - protected MessageConsumer createConsumerImpl(final Destination destination, - final int prefetchHigh, - final int prefetchLow, - final boolean noLocal, - final boolean exclusive, - String selector, - final FieldTable rawSelector, - final boolean noConsume, - final boolean autoClose) throws JMSException + public TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException { - checkTemporaryDestination(destination); - - final String messageSelector; - if (_strictAMQP && !(selector == null || selector.equals(""))) + checkNotClosed(); + AMQTopic origTopic = checkValidTopic(topic); + AMQTopic dest = AMQTopic.createDurableTopic(origTopic, name, _connection); + TopicSubscriberAdaptor subscriber = _subscriptions.get(name); + if (subscriber != null) { - if (_strictAMQPFATAL) + if (subscriber.getTopic().equals(topic)) { - throw new UnsupportedOperationException("Selectors not currently supported by AMQP."); + throw new IllegalStateException("Already subscribed to topic " + topic + " with subscription exchange " + + name); } else { - messageSelector = null; + unsubscribe(name); } } else { - messageSelector = selector; - } - - return (org.apache.qpid.jms.MessageConsumer) new FailoverSupport() - { - public Object operation() throws JMSException + AMQShortString topicName; + if (topic instanceof AMQTopic) { - checkNotClosed(); - - AMQDestination amqd = (AMQDestination) destination; + topicName = ((AMQTopic) topic).getDestinationName(); + } + else + { + topicName = new AMQShortString(topic.getTopicName()); + } - final AMQProtocolHandler protocolHandler = getProtocolHandler(); - // TODO: Define selectors in AMQP - // TODO: construct the rawSelector from the selector string if rawSelector == null - final FieldTable ft = FieldTableFactory.newFieldTable(); - //if (rawSelector != null) - // ft.put("headers", rawSelector.getDataAsBytes()); - if (rawSelector != null) + if (_strictAMQP) + { + if (_strictAMQPFATAL) { - ft.addAll(rawSelector); + throw new UnsupportedOperationException("JMS Durable not currently supported by AMQP."); } - - BasicMessageConsumer consumer = new BasicMessageConsumer(_channelId, _connection, amqd, messageSelector, noLocal, - _messageFactoryRegistry, AMQSession.this, - protocolHandler, ft, prefetchHigh, prefetchLow, exclusive, - _acknowledgeMode, noConsume, autoClose); - - if (_messageListener != null) + else { - consumer.setMessageListener(_messageListener); + _logger.warn("Unable to determine if subscription already exists for '" + topicName + "' " + + "for creation durableSubscriber. Requesting queue deletion regardless."); } - try - { - registerConsumer(consumer, false); - } - catch (AMQInvalidArgumentException ise) - { - JMSException ex = new InvalidSelectorException(ise.getMessage()); - ex.setLinkedException(ise); - throw ex; - } - catch (AMQInvalidRoutingKeyException e) + deleteQueue(dest.getAMQQueueName()); + } + else + { + // if the queue is bound to the exchange but NOT for this topic, then the JMS spec + // says we must trash the subscription. + if (isQueueBound(dest.getExchangeName(), dest.getAMQQueueName()) + && !isQueueBound(dest.getExchangeName(), dest.getAMQQueueName(), topicName)) { - JMSException ide = new InvalidDestinationException("Invalid routing key:" + amqd.getRoutingKey().toString()); - ide.setLinkedException(e); - throw ide; + deleteQueue(dest.getAMQQueueName()); } - catch (AMQException e) - { - JMSException ex = new JMSException("Error registering consumer: " + e); + } + } - if (_logger.isDebugEnabled()) - { - e.printStackTrace(); - } - ex.setLinkedException(e); - throw ex; - } + subscriber = new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createConsumer(dest)); - synchronized (destination) - { - _destinationConsumerCount.putIfAbsent(destination, new AtomicInteger()); - _destinationConsumerCount.get(destination).incrementAndGet(); - } + _subscriptions.put(name, subscriber); + _reverseSubscriptionMap.put(subscriber.getMessageConsumer(), name); - return consumer; - } - }.execute(_connection); + return subscriber; } - private void checkTemporaryDestination(Destination destination) + /** Note, currently this does not handle reuse of the same name with different topics correctly. */ + public TopicSubscriber createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal) throws JMSException { - if ((destination instanceof TemporaryDestination)) - { - _logger.debug("destination is temporary"); - final TemporaryDestination tempDest = (TemporaryDestination) destination; - if (tempDest.getSession() != this) - { - _logger.debug("destination is on different session"); - throw new JMSException("Cannot consume from a temporary destination created onanother session"); - } - if (tempDest.isDeleted()) - { - _logger.debug("destination is deleted"); - throw new JMSException("Cannot consume from a deleted destination"); - } - } - } + checkNotClosed(); + checkValidTopic(topic); + AMQTopic dest = AMQTopic.createDurableTopic((AMQTopic) topic, name, _connection); + BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(dest, messageSelector, noLocal); + TopicSubscriberAdaptor subscriber = new TopicSubscriberAdaptor(dest, consumer); + _subscriptions.put(name, subscriber); + _reverseSubscriptionMap.put(subscriber.getMessageConsumer(), name); + return subscriber; + } - public boolean hasConsumer(Destination destination) + public MapMessage createMapMessage() throws JMSException { - AtomicInteger counter = _destinationConsumerCount.get(destination); + synchronized (_connection.getFailoverMutex()) + { + checkNotClosed(); - return (counter != null) && (counter.get() != 0); + return new JMSMapMessage(); + } } - public void declareExchange(AMQShortString name, AMQShortString type, boolean nowait) throws AMQException + public javax.jms.Message createMessage() throws JMSException { - declareExchange(name, type, getProtocolHandler(), nowait); + return createBytesMessage(); } - private void declareExchange(AMQDestination amqd, AMQProtocolHandler protocolHandler, boolean nowait) throws AMQException + public ObjectMessage createObjectMessage() throws JMSException { - declareExchange(amqd.getExchangeName(), amqd.getExchangeClass(), protocolHandler, nowait); + synchronized (_connection.getFailoverMutex()) + { + checkNotClosed(); + + return (ObjectMessage) new JMSObjectMessage(); + } } - private void declareExchange(AMQShortString name, AMQShortString type, AMQProtocolHandler protocolHandler, boolean nowait) throws AMQException + public ObjectMessage createObjectMessage(Serializable object) throws JMSException { - // TODO: Be aware of possible changes to parameter order as versions change. - AMQFrame exchangeDeclare = ExchangeDeclareBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - null, // arguments - false, // autoDelete - false, // durable - name, // exchange - false, // internal - nowait, // nowait - false, // passive - getTicket(), // ticket - type); // type + ObjectMessage msg = createObjectMessage(); + msg.setObject(object); - protocolHandler.syncWrite(exchangeDeclare, ExchangeDeclareOkBody.class); + return msg; } - - public void createQueue(AMQShortString name, boolean autoDelete, boolean durable, boolean exclusive) throws AMQException + public BasicMessageProducer createProducer(Destination destination) throws JMSException { - AMQFrame queueDeclare = QueueDeclareBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - null, // arguments - autoDelete, // autoDelete - durable, // durable - exclusive, // exclusive - false, // nowait - false, // passive - name, // queue - getTicket()); // ticket - - getProtocolHandler().syncWrite(queueDeclare, QueueDeclareOkBody.class); - + return createProducerImpl(destination, DEFAULT_MANDATORY, DEFAULT_IMMEDIATE); } - - public void bindQueue(AMQShortString queueName, AMQShortString routingKey, FieldTable arguments, AMQShortString exchangeName) throws AMQException + public BasicMessageProducer createProducer(Destination destination, boolean immediate) throws JMSException { - // TODO: Be aware of possible changes to parameter order as versions change. - AMQFrame queueBind = QueueBindBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - arguments, // arguments - exchangeName, // exchange - false, // nowait - queueName, // queue - routingKey, // routingKey - getTicket()); // ticket - - - getProtocolHandler().syncWrite(queueBind, QueueBindOkBody.class); + return createProducerImpl(destination, DEFAULT_MANDATORY, immediate); } - /** - * Declare the queue. - * - * @param amqd - * @param protocolHandler - * - * @return the queue name. This is useful where the broker is generating a queue name on behalf of the client. - * - * @throws AMQException - */ - private AMQShortString declareQueue(AMQDestination amqd, AMQProtocolHandler protocolHandler) throws AMQException + public BasicMessageProducer createProducer(Destination destination, boolean mandatory, boolean immediate) + throws JMSException { - // For queues (but not topics) we generate the name in the client rather than the - // server. This allows the name to be reused on failover if required. In general, - // the destination indicates whether it wants a name generated or not. - if (amqd.isNameRequired()) - { - amqd.setQueueName(protocolHandler.generateQueueName()); - } - - //TODO verify the destiation is valid. else throw - - // TODO: Be aware of possible changes to parameter order as versions change. - AMQFrame queueDeclare = QueueDeclareBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - null, // arguments - amqd.isAutoDelete(), // autoDelete - amqd.isDurable(), // durable - amqd.isExclusive(), // exclusive - false, // nowait - false, // passive - amqd.getAMQQueueName(), // queue - getTicket()); // ticket - - protocolHandler.syncWrite(queueDeclare, QueueDeclareOkBody.class); - return amqd.getAMQQueueName(); + return createProducerImpl(destination, mandatory, immediate); } - private void bindQueue(AMQDestination amqd, AMQShortString queueName, AMQProtocolHandler protocolHandler, FieldTable ft) throws AMQException + public BasicMessageProducer createProducer(Destination destination, boolean mandatory, boolean immediate, + boolean waitUntilSent) throws JMSException { - // TODO: Be aware of possible changes to parameter order as versions change. - AMQFrame queueBind = QueueBindBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - ft, // arguments - amqd.getExchangeName(), // exchange - false, // nowait - queueName, // queue - amqd.getRoutingKey(), // routingKey - getTicket()); // ticket - - - protocolHandler.syncWrite(queueBind, QueueBindOkBody.class); + return createProducerImpl(destination, mandatory, immediate, waitUntilSent); } - /** - * Register to consume from the queue. - * - * @param queueName - * - * @return the consumer tag generated by the broker - */ - private void consumeFromQueue(BasicMessageConsumer consumer, AMQShortString queueName, AMQProtocolHandler protocolHandler, - boolean nowait, String messageSelector) throws AMQException + public TopicPublisher createPublisher(Topic topic) throws JMSException { - //need to generate a consumer tag on the client so we can exploit the nowait flag - AMQShortString tag = new AMQShortString(Integer.toString(_nextTag++)); - - FieldTable arguments = FieldTableFactory.newFieldTable(); - if (messageSelector != null && !messageSelector.equals("")) - { - arguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue(), messageSelector); - } - if (consumer.isAutoClose()) - { - arguments.put(AMQPFilterTypes.AUTO_CLOSE.getValue(), Boolean.TRUE); - } - if (consumer.isNoConsume()) - { - arguments.put(AMQPFilterTypes.NO_CONSUME.getValue(), Boolean.TRUE); - } - - consumer.setConsumerTag(tag); - // we must register the consumer in the map before we actually start listening - _consumers.put(tag, consumer); + checkNotClosed(); - try - { - // TODO: Be aware of possible changes to parameter order as versions change. - AMQFrame jmsConsume = BasicConsumeBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - arguments, // arguments - tag, // consumerTag - consumer.isExclusive(), // exclusive - consumer.getAcknowledgeMode() == Session.NO_ACKNOWLEDGE, // noAck - consumer.isNoLocal(), // noLocal - nowait, // nowait - queueName, // queue - getTicket()); // ticket - if (nowait) - { - protocolHandler.writeFrame(jmsConsume); - } - else - { - protocolHandler.syncWrite(jmsConsume, BasicConsumeOkBody.class); - } - } - catch (AMQException e) - { - // clean-up the map in the event of an error - _consumers.remove(tag); - throw e; - } + return new TopicPublisherAdapter((BasicMessageProducer) createProducer(topic), topic); } public Queue createQueue(String queueName) throws JMSException @@ -1540,9 +906,79 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi } } - public AMQShortString getDefaultQueueExchangeName() + /** + * Declares the named queue. + * + * <p/>Note that this operation automatically retries in the event of fail-over. + * + * @param name The name of the queue to declare. + * @param autoDelete + * @param durable Flag to indicate that the queue is durable. + * @param exclusive Flag to indicate that the queue is exclusive to this client. + * + * @throws AMQException If the queue cannot be declared for any reason. + * @todo Be aware of possible changes to parameter order as versions change. + */ + public void createQueue(final AMQShortString name, final boolean autoDelete, final boolean durable, + final boolean exclusive) throws AMQException { - return _connection.getDefaultQueueExchangeName(); + new FailoverRetrySupport<Object, AMQException>(new FailoverProtectedOperation<Object, AMQException>() + { + public Object execute() throws AMQException, FailoverException + { + AMQFrame queueDeclare = + QueueDeclareBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), + null, // arguments + autoDelete, // autoDelete + durable, // durable + exclusive, // exclusive + false, // nowait + false, // passive + name, // queue + getTicket()); // ticket + + getProtocolHandler().syncWrite(queueDeclare, QueueDeclareOkBody.class); + + return null; + } + }, _connection).execute(); + } + + /** + * Creates a QueueReceiver + * + * @param destination + * + * @return QueueReceiver - a wrapper around our MessageConsumer + * + * @throws JMSException + */ + public QueueReceiver createQueueReceiver(Destination destination) throws JMSException + { + checkValidDestination(destination); + AMQQueue dest = (AMQQueue) destination; + BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(destination); + + return new QueueReceiverAdaptor(dest, consumer); + } + + /** + * Creates a QueueReceiver using a message selector + * + * @param destination + * @param messageSelector + * + * @return QueueReceiver - a wrapper around our MessageConsumer + * + * @throws JMSException + */ + public QueueReceiver createQueueReceiver(Destination destination, String messageSelector) throws JMSException + { + checkValidDestination(destination); + AMQQueue dest = (AMQQueue) destination; + BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(destination, messageSelector); + + return new QueueReceiverAdaptor(dest, consumer); } /** @@ -1559,6 +995,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi checkNotClosed(); AMQQueue dest = (AMQQueue) queue; BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(dest); + return new QueueReceiverAdaptor(dest, consumer); } @@ -1576,47 +1013,29 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi { checkNotClosed(); AMQQueue dest = (AMQQueue) queue; - BasicMessageConsumer consumer = (BasicMessageConsumer) - createConsumer(dest, messageSelector); + BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(dest, messageSelector); + return new QueueReceiverAdaptor(dest, consumer); } public QueueSender createSender(Queue queue) throws JMSException { checkNotClosed(); - //return (QueueSender) createProducer(queue); + + // return (QueueSender) createProducer(queue); return new QueueSenderAdapter(createProducer(queue), queue); } - public Topic createTopic(String topicName) throws JMSException + public StreamMessage createStreamMessage() throws JMSException { - checkNotClosed(); - - if (topicName.indexOf('/') == -1) - { - return new AMQTopic(getDefaultTopicExchangeName(), new AMQShortString(topicName)); - } - else + synchronized (_connection.getFailoverMutex()) { - try - { - return new AMQTopic(new AMQBindingURL(topicName)); - } - catch (URLSyntaxException urlse) - { - JMSException jmse = new JMSException(urlse.getReason()); - jmse.setLinkedException(urlse); + checkNotClosed(); - throw jmse; - } + return new JMSStreamMessage(); } } - public AMQShortString getDefaultTopicExchangeName() - { - return _connection.getDefaultTopicExchangeName(); - } - /** * Creates a non-durable subscriber * @@ -1630,7 +1049,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi { checkNotClosed(); AMQTopic dest = checkValidTopic(topic); - //AMQTopic dest = new AMQTopic(topic.getTopicName()); + + // AMQTopic dest = new AMQTopic(topic.getTopicName()); return new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createConsumer(dest)); } @@ -1649,150 +1069,396 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi { checkNotClosed(); AMQTopic dest = checkValidTopic(topic); - //AMQTopic dest = new AMQTopic(topic.getTopicName()); + + // AMQTopic dest = new AMQTopic(topic.getTopicName()); return new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createConsumer(dest, messageSelector, noLocal)); } - public TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException + public TemporaryQueue createTemporaryQueue() throws JMSException { + checkNotClosed(); + return new AMQTemporaryQueue(this); + } + public TemporaryTopic createTemporaryTopic() throws JMSException + { checkNotClosed(); - AMQTopic origTopic = checkValidTopic(topic); - AMQTopic dest = AMQTopic.createDurableTopic(origTopic, name, _connection); - TopicSubscriberAdaptor subscriber = _subscriptions.get(name); - if (subscriber != null) + + return new AMQTemporaryTopic(this); + } + + public TextMessage createTextMessage() throws JMSException + { + synchronized (_connection.getFailoverMutex()) { - if (subscriber.getTopic().equals(topic)) + checkNotClosed(); + + return new JMSTextMessage(); + } + } + + public TextMessage createTextMessage(String text) throws JMSException + { + + TextMessage msg = createTextMessage(); + msg.setText(text); + + return msg; + } + + public Topic createTopic(String topicName) throws JMSException + { + checkNotClosed(); + + if (topicName.indexOf('/') == -1) + { + return new AMQTopic(getDefaultTopicExchangeName(), new AMQShortString(topicName)); + } + else + { + try { - throw new IllegalStateException("Already subscribed to topic " + topic + " with subscription exchange " + - name); + return new AMQTopic(new AMQBindingURL(topicName)); } - else + catch (URLSyntaxException urlse) { - unsubscribe(name); + JMSException jmse = new JMSException(urlse.getReason()); + jmse.setLinkedException(urlse); + + throw jmse; } } + } + + public void declareExchange(AMQShortString name, AMQShortString type, boolean nowait) throws AMQException + { + declareExchange(name, type, getProtocolHandler(), nowait); + } + + public int getAcknowledgeMode() throws JMSException + { + checkNotClosed(); + + return _acknowledgeMode; + } + + public AMQConnection getAMQConnection() + { + return _connection; + } + + public int getChannelId() + { + return _channelId; + } + + public int getDefaultPrefetch() + { + return _defaultPrefetchHighMark; + } + + public int getDefaultPrefetchHigh() + { + return _defaultPrefetchHighMark; + } + + public int getDefaultPrefetchLow() + { + return _defaultPrefetchLowMark; + } + + public AMQShortString getDefaultQueueExchangeName() + { + return _connection.getDefaultQueueExchangeName(); + } + + public AMQShortString getDefaultTopicExchangeName() + { + return _connection.getDefaultTopicExchangeName(); + } + + public MessageListener getMessageListener() throws JMSException + { + // checkNotClosed(); + return _messageListener; + } + + public AMQShortString getTemporaryQueueExchangeName() + { + return _connection.getTemporaryQueueExchangeName(); + } + + public AMQShortString getTemporaryTopicExchangeName() + { + return _connection.getTemporaryTopicExchangeName(); + } + + public int getTicket() + { + return _ticket; + } + + public boolean getTransacted() throws JMSException + { + checkNotClosed(); + + return _transacted; + } + + public boolean hasConsumer(Destination destination) + { + AtomicInteger counter = _destinationConsumerCount.get(destination); + + return (counter != null) && (counter.get() != 0); + } + + public boolean isStrictAMQP() + { + return _strictAMQP; + } + + public boolean isSuspended() + { + return _suspended; + } + + /** + * 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. + * + * @param message the message that has been received + */ + public void messageReceived(UnprocessedMessage message) + { + if (_logger.isDebugEnabled()) + { + _logger.debug("Message[" + + ((message.getDeliverBody() == null) ? ("B:" + message.getBounceBody()) : ("D:" + message.getDeliverBody())) + + "] received in session with channel id " + _channelId); + } + + if (message.getDeliverBody() == null) + { + // Return of the bounced message. + returnBouncedMessage(message); + } else { - AMQShortString topicName; - if (topic instanceof AMQTopic) + _queue.add(message); + } + } + + /** + * Stops message delivery in this session, and restarts message delivery with the oldest unacknowledged message. + * + * <p/>All consumers deliver messages in a serial order. Acknowledging a received message automatically acknowledges + * all messages that have been delivered to the client. + * + * <p/>Restarting a session causes it to take the following actions: + * + * <ul> <li>Stop message delivery.</li> <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.</li> </ul> + * + * <p/>If the recover operation is interrupted by a fail-over, between asking that the broker begin recovery and + * receiving acknolwedgement that it hasm then a JMSException will be thrown. In this case it will not be possible + * for the client to determine whether the broker is going to recover the session or not. + * + * @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. + * @todo Be aware of possible changes to parameter order as versions change. + */ + public void recover() throws JMSException + { + // Ensure that the session is open. + checkNotClosed(); + + // Ensure that the session is not transacted. + checkNotTransacted(); + + // this is set only here, and the before the consumer's onMessage is called it is set to false + _inRecovery = true; + try + { + + boolean isSuspended = isSuspended(); + + if (!isSuspended) { - topicName = ((AMQTopic) topic).getDestinationName(); + suspendChannel(true); } - else + + for (BasicMessageConsumer consumer : _consumers.values()) { - topicName = new AMQShortString(topic.getTopicName()); + consumer.clearUnackedMessages(); } - if (_strictAMQP) + if (_dispatcher != null) { - if (_strictAMQPFATAL) - { - throw new UnsupportedOperationException("JMS Durable not currently supported by AMQP."); - } - else - { - _logger.warn("Unable to determine if subscription already exists for '" + topicName + "' " - + "for creation durableSubscriber. Requesting queue deletion regardless."); - } + _dispatcher.rollback(); + } - deleteQueue(dest.getAMQQueueName()); + if (isStrictAMQP()) + { + // We can't use the BasicRecoverBody-OK method as it isn't part of the spec. + _connection.getProtocolHandler().writeFrame(BasicRecoverBody.createAMQFrame(_channelId, + getProtocolMajorVersion(), getProtocolMinorVersion(), false)); // requeue + _logger.warn("Session Recover cannot be guaranteed with STRICT_AMQP. Messages may arrive out of order."); } else { - // if the queue is bound to the exchange but NOT for this topic, then the JMS spec - // says we must trash the subscription. - if (isQueueBound(dest.getExchangeName(), dest.getAMQQueueName()) && - !isQueueBound(dest.getExchangeName(), dest.getAMQQueueName(), topicName)) - { - deleteQueue(dest.getAMQQueueName()); - } - } - } - - subscriber = new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createConsumer(dest)); - _subscriptions.put(name, subscriber); - _reverseSubscriptionMap.put(subscriber.getMessageConsumer(), name); - - return subscriber; - } + _connection.getProtocolHandler().syncWrite( + BasicRecoverBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), false) // requeue + , BasicRecoverOkBody.class); + } - void deleteQueue(AMQShortString queueName) throws JMSException - { - try - { - // TODO: Be aware of possible changes to parameter order as versions change. - AMQFrame queueDeleteFrame = QueueDeleteBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - false, // ifEmpty - false, // ifUnused - true, // nowait - queueName, // queue - getTicket()); // ticket - getProtocolHandler().syncWrite(queueDeleteFrame, QueueDeleteOkBody.class); + if (!isSuspended) + { + suspendChannel(false); + } } catch (AMQException e) { - throw new JMSAMQException(e); + throw new JMSAMQException("Recover failed: " + e.getMessage(), e); + } + catch (FailoverException e) + { + throw new JMSAMQException("Recovery was interrupted by fail-over. Recovery status is not known.", e); } } - /** Note, currently this does not handle reuse of the same name with different topics correctly. */ - public TopicSubscriber createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal) - throws JMSException + public void rejectMessage(UnprocessedMessage message, boolean requeue) { - checkNotClosed(); - checkValidTopic(topic); - AMQTopic dest = AMQTopic.createDurableTopic((AMQTopic) topic, name, _connection); - BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(dest, messageSelector, noLocal); - TopicSubscriberAdaptor subscriber = new TopicSubscriberAdaptor(dest, consumer); - _subscriptions.put(name, subscriber); - _reverseSubscriptionMap.put(subscriber.getMessageConsumer(), name); - return subscriber; - } - public TopicPublisher createPublisher(Topic topic) throws JMSException - { - checkNotClosed(); - return new TopicPublisherAdapter((BasicMessageProducer) createProducer(topic), topic); + if (_logger.isTraceEnabled()) + { + _logger.trace("Rejecting Unacked message:" + message.getDeliverBody().deliveryTag); + } + + rejectMessage(message.getDeliverBody().deliveryTag, requeue); } - public QueueBrowser createBrowser(Queue queue) throws JMSException + public void rejectMessage(AbstractJMSMessage message, boolean requeue) { - if (isStrictAMQP()) + if (_logger.isTraceEnabled()) { - throw new UnsupportedOperationException(); + _logger.trace("Rejecting Abstract message:" + message.getDeliveryTag()); } - return createBrowser(queue, null); + rejectMessage(message.getDeliveryTag(), requeue); + } - public QueueBrowser createBrowser(Queue queue, String messageSelector) throws JMSException + public void rejectMessage(long deliveryTag, boolean requeue) { - if (isStrictAMQP()) + if ((_acknowledgeMode == CLIENT_ACKNOWLEDGE) || (_acknowledgeMode == SESSION_TRANSACTED)) { - throw new UnsupportedOperationException(); - } + if (_logger.isDebugEnabled()) + { + _logger.debug("Rejecting delivery tag:" + deliveryTag); + } - checkNotClosed(); - checkValidQueue(queue); - return new AMQQueueBrowser(this, (AMQQueue) queue, messageSelector); + AMQFrame basicRejectBody = + BasicRejectBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), deliveryTag, + requeue); + + _connection.getProtocolHandler().writeFrame(basicRejectBody); + } } - public TemporaryQueue createTemporaryQueue() throws JMSException + /** + * Commits all messages done in this transaction and releases any locks currently held. + * + * <p/>If the rollback fails, because the rollback itself is interrupted by a fail-over between requesting that the + * rollback be done, and receiving an acknowledgement that it has been done, then a JMSException will be thrown. The + * client will be unable to determine whether or not the rollback actually happened on the broker in this case. + * + * @throws JMSException If the JMS provider fails to rollback the transaction due to some internal error. This does + * not mean that the rollback is known to have failed, merely that it is not known whether it + * failed or not. + * @todo Be aware of possible changes to parameter order as versions change. + */ + public void rollback() throws JMSException { - checkNotClosed(); - return new AMQTemporaryQueue(this); + synchronized (_suspensionLock) + { + checkTransacted(); + + try + { + boolean isSuspended = isSuspended(); + + if (!isSuspended) + { + suspendChannel(true); + } + + if (_dispatcher != null) + { + _dispatcher.rollback(); + } + + _connection.getProtocolHandler().syncWrite(TxRollbackBody.createAMQFrame(_channelId, + getProtocolMajorVersion(), getProtocolMinorVersion()), TxRollbackOkBody.class); + + if (!isSuspended) + { + suspendChannel(false); + } + } + catch (AMQException e) + { + throw new JMSAMQException("Failed to rollback: " + e, e); + } + catch (FailoverException e) + { + throw new JMSAMQException("Fail-over interrupted rollback. Status of the rollback is uncertain.", e); + } + } } - public TemporaryTopic createTemporaryTopic() throws JMSException + public void run() { - checkNotClosed(); - return new AMQTemporaryTopic(this); + throw new java.lang.UnsupportedOperationException(); } + public void setMessageListener(MessageListener listener) throws JMSException + { + // checkNotClosed(); + // + // if (_dispatcher != null && !_dispatcher.connectionStopped()) + // { + // throw new javax.jms.IllegalStateException("Attempt to set listener while session is started."); + // } + // + // // We are stopped + // for (Iterator<BasicMessageConsumer> i = _consumers.values().iterator(); i.hasNext();) + // { + // BasicMessageConsumer consumer = i.next(); + // + // if (consumer.isReceiving()) + // { + // throw new javax.jms.IllegalStateException("Another thread is already receiving synchronously."); + // } + // } + // + // _messageListener = listener; + // + // for (Iterator<BasicMessageConsumer> i = _consumers.values().iterator(); i.hasNext();) + // { + // i.next().setMessageListener(_messageListener); + // } + + } + + /*public void setTicket(int ticket) + { + _ticket = ticket; + }*/ + public void unsubscribe(String name) throws JMSException { checkNotClosed(); @@ -1835,189 +1501,246 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi } } - boolean isQueueBound(AMQShortString exchangeName, AMQShortString queueName) throws JMSException + protected MessageConsumer createConsumerImpl(final Destination destination, final int prefetchHigh, + final int prefetchLow, final boolean noLocal, final boolean exclusive, String selector, final FieldTable rawSelector, + final boolean noConsume, final boolean autoClose) throws JMSException { - return isQueueBound(exchangeName, queueName, null); - } + checkTemporaryDestination(destination); - boolean isQueueBound(AMQShortString exchangeName, AMQShortString queueName, AMQShortString routingKey) throws JMSException - { + final String messageSelector; - // TODO: Be aware of possible changes to parameter order as versions change. - AMQFrame boundFrame = ExchangeBoundBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - exchangeName, // exchange - queueName, // queue - routingKey); // routingKey - AMQMethodEvent response = null; - try + if (_strictAMQP && !((selector == null) || selector.equals(""))) { - response = getProtocolHandler().syncWrite(boundFrame, ExchangeBoundOkBody.class); + if (_strictAMQPFATAL) + { + throw new UnsupportedOperationException("Selectors not currently supported by AMQP."); + } + else + { + messageSelector = null; + } } - catch (AMQException e) + else { - throw new JMSAMQException(e); + messageSelector = selector; } - ExchangeBoundOkBody responseBody = (ExchangeBoundOkBody) response.getMethod(); - return (responseBody.replyCode == 0); //ExchangeBoundHandler.OK); Remove Broker compile dependency - } - private void checkTransacted() throws JMSException - { - if (!getTransacted()) - { - throw new IllegalStateException("Session is not transacted"); - } - } + return new FailoverRetrySupport<MessageConsumer, JMSException>( + new FailoverProtectedOperation<MessageConsumer, JMSException>() + { + public MessageConsumer execute() throws JMSException, FailoverException + { + checkNotClosed(); - private void checkNotTransacted() throws JMSException - { - if (getTransacted()) - { - throw new IllegalStateException("Session is transacted"); - } + AMQDestination amqd = (AMQDestination) destination; + + final AMQProtocolHandler protocolHandler = getProtocolHandler(); + // TODO: Define selectors in AMQP + // TODO: construct the rawSelector from the selector string if rawSelector == null + final FieldTable ft = FieldTableFactory.newFieldTable(); + // if (rawSelector != null) + // ft.put("headers", rawSelector.getDataAsBytes()); + if (rawSelector != null) + { + ft.addAll(rawSelector); + } + + BasicMessageConsumer consumer = + new BasicMessageConsumer(_channelId, _connection, amqd, messageSelector, noLocal, + _messageFactoryRegistry, AMQSession.this, protocolHandler, ft, prefetchHigh, prefetchLow, + exclusive, _acknowledgeMode, noConsume, autoClose); + + if (_messageListener != null) + { + consumer.setMessageListener(_messageListener); + } + + try + { + registerConsumer(consumer, false); + } + catch (AMQInvalidArgumentException ise) + { + JMSException ex = new InvalidSelectorException(ise.getMessage()); + ex.setLinkedException(ise); + throw ex; + } + catch (AMQInvalidRoutingKeyException e) + { + JMSException ide = + new InvalidDestinationException("Invalid routing key:" + amqd.getRoutingKey().toString()); + ide.setLinkedException(e); + throw ide; + } + catch (AMQException e) + { + JMSException ex = new JMSException("Error registering consumer: " + e); + + if (_logger.isDebugEnabled()) + { + e.printStackTrace(); + } + + ex.setLinkedException(e); + throw ex; + } + + synchronized (destination) + { + _destinationConsumerCount.putIfAbsent(destination, new AtomicInteger()); + _destinationConsumerCount.get(destination).incrementAndGet(); + } + + return consumer; + } + }, _connection).execute(); } /** - * 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. + * Called by the MessageConsumer when closing, to deregister the consumer from the map from consumerTag to consumer + * instance. * - * @param message the message that has been received + * @param consumer the consum */ - public void messageReceived(UnprocessedMessage message) + void deregisterConsumer(BasicMessageConsumer consumer) { - if (_logger.isDebugEnabled()) + if (_consumers.remove(consumer.getConsumerTag()) != null) { - _logger.debug("Message[" + (message.getDeliverBody() == null ? - "B:" + message.getBounceBody() : "D:" + message.getDeliverBody()) - + "] received in session with channel id " + _channelId); - } + String subscriptionName = _reverseSubscriptionMap.remove(consumer); + if (subscriptionName != null) + { + _subscriptions.remove(subscriptionName); + } - if (message.getDeliverBody() == null) - { - // Return of the bounced message. - returnBouncedMessage(message); - } - else - { - _queue.add(message); + Destination dest = consumer.getDestination(); + synchronized (dest) + { + if (_destinationConsumerCount.get(dest).decrementAndGet() == 0) + { + _destinationConsumerCount.remove(dest); + } + } } } - private void returnBouncedMessage(final UnprocessedMessage message) + void deregisterProducer(long producerId) { - _connection.performConnectionTask( - new Runnable() - { - public void run() - { - try - { - // Bounced message is processed here, away from the mina thread - AbstractJMSMessage bouncedMessage = _messageFactoryRegistry.createMessage(0, - false, - message.getBounceBody().exchange, - message.getBounceBody().routingKey, - message.getContentHeader(), - message.getBodies()); - - AMQConstant errorCode = AMQConstant.getConstant(message.getBounceBody().replyCode); - AMQShortString reason = message.getBounceBody().replyText; - _logger.debug("Message returned with error code " + errorCode + " (" + reason + ")"); - - //@TODO should this be moved to an exception handler of sorts. Somewhere errors are converted to correct execeptions. - if (errorCode == AMQConstant.NO_CONSUMERS) - { - _connection.exceptionReceived(new AMQNoConsumersException("Error: " + reason, bouncedMessage, null)); - } - else if (errorCode == AMQConstant.NO_ROUTE) - { - _connection.exceptionReceived(new AMQNoRouteException("Error: " + reason, bouncedMessage, null)); - } - else - { - _connection.exceptionReceived(new AMQUndeliveredException(errorCode, "Error: " + reason, bouncedMessage, null)); - } + _producers.remove(new Long(producerId)); + } - } - catch (Exception e) - { - _logger.error("Caught exception trying to raise undelivered message exception (dump follows) - ignoring...", e); - } - } - }); + boolean isInRecovery() + { + return _inRecovery; + } + + boolean isQueueBound(AMQShortString exchangeName, AMQShortString queueName) throws JMSException + { + return isQueueBound(exchangeName, queueName, null); } /** - * Acknowledge a message or several messages. This method can be called via AbstractJMSMessage or from a - * BasicConsumer. The former where the mode is CLIENT_ACK and the latter where the mode is AUTO_ACK or similar. + * Tests whether or not the specified queue is bound to the specified exchange under a particular routing key. * - * @param deliveryTag the tag of the last message to be acknowledged - * @param multiple if true will acknowledge all messages up to and including the one specified by the delivery - * tag + * <p/>Note that this operation automatically retries in the event of fail-over. + * + * @param exchangeName The exchange name to test for binding against. + * @param queueName The queue name to check if bound. + * @param routingKey The routing key to check if the queue is bound under. + * + * @return <tt>true</tt> if the queue is bound to the exchange and routing key, <tt>false</tt> if not. + * + * @throws JMSException If the query fails for any reason. + * @todo Be aware of possible changes to parameter order as versions change. */ - public void acknowledgeMessage(long deliveryTag, boolean multiple) + boolean isQueueBound(final AMQShortString exchangeName, final AMQShortString queueName, final AMQShortString routingKey) + throws JMSException { - // TODO: Be aware of possible changes to parameter order as versions change. - final AMQFrame ackFrame = BasicAckBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), getProtocolMinorVersion(), // AMQP version (major, minor) - deliveryTag, // deliveryTag - multiple); // multiple - if (_logger.isDebugEnabled()) + try { - _logger.debug("Sending ack for delivery tag " + deliveryTag + " on channel " + _channelId); + AMQMethodEvent response = + new FailoverRetrySupport<AMQMethodEvent, AMQException>( + new FailoverProtectedOperation<AMQMethodEvent, AMQException>() + { + public AMQMethodEvent execute() throws AMQException, FailoverException + { + AMQFrame boundFrame = + ExchangeBoundBody.createAMQFrame(_channelId, getProtocolMajorVersion(), + getProtocolMinorVersion(), exchangeName, // exchange + queueName, // queue + routingKey); // routingKey + + return getProtocolHandler().syncWrite(boundFrame, ExchangeBoundOkBody.class); + + } + }, _connection).execute(); + + // Extract and return the response code from the query. + ExchangeBoundOkBody responseBody = (ExchangeBoundOkBody) response.getMethod(); + + return (responseBody.replyCode == 0); + } + catch (AMQException e) + { + throw new JMSAMQException("Queue bound query failed: " + e.getMessage(), e); } - getProtocolHandler().writeFrame(ackFrame); } - public int getDefaultPrefetch() + /** + * Called to mark the session as being closed. Useful when the session needs to be made invalid, e.g. after failover + * when the client has veoted resubscription. <p/> The caller of this method must already hold the failover mutex. + */ + void markClosed() { - return _defaultPrefetchHighMark; + _closed.set(true); + _connection.deregisterSession(_channelId); + markClosedProducersAndConsumers(); + } - public int getDefaultPrefetchHigh() + /** + * Resubscribes all producers and consumers. This is called when performing failover. + * + * @throws AMQException + */ + void resubscribe() throws AMQException { - return _defaultPrefetchHighMark; + resubscribeProducers(); + resubscribeConsumers(); } - public int getDefaultPrefetchLow() + void setHasMessageListeners() { - return _defaultPrefetchLowMark; + _hasMessageListeners = true; } - public int getChannelId() + void setInRecovery(boolean inRecovery) { - return _channelId; + _inRecovery = inRecovery; } + /** + * Starts the session, which ensures that it is not suspended and that its event dispatcher is running. + * + * @throws AMQException If the session cannot be started for any reason. + * @todo This should be controlled by _stopped as it pairs with the stop method fixme or check the + * FlowControlledBlockingQueue _queue to see if we have flow controlled. will result in sending Flow messages for + * each subsequent call to flow.. only need to do this if we have called stop. + */ void start() throws AMQException { - //fixme This should be controlled by _stopped as it pairs with the stop method - //fixme or check the FlowControlledBlockingQueue _queue to see if we have flow controlled. - //will result in sending Flow messages for each subsequent call to flow.. only need to do this - // if we have called stop. + // Check if the session has perviously been started and suspended, in which case it must be unsuspended. if (_startedAtLeastOnce.getAndSet(true)) { - //then we stopped this and are restarting, so signal server to resume delivery suspendChannel(false); } + // If the event dispatcher is not running then start it too. if (hasMessageListeners()) { startDistpatcherIfNecessary(); } } - private boolean hasMessageListeners() - { - return _hasMessageListeners; - } - - void setHasMessageListeners() - { - _hasMessageListeners = true; - } - synchronized void startDistpatcherIfNecessary() { // If IMMEDIATE_PREFETCH is not set then we need to start fetching @@ -2032,7 +1755,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi } catch (AMQException e) { - _logger.info("Suspending channel threw an exception:" + e); + _logger.info("Unsuspending channel threw an exception:" + e); } } } @@ -2057,7 +1780,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi void stop() throws AMQException { - //stop the server delivering messages to this session + // Stop the server delivering messages to this session. suspendChannel(true); if (_dispatcher != null) @@ -2066,320 +1789,552 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi } } - /** - * Callers must hold the failover mutex before calling this method. + /* + * Binds the named queue, with the specified routing key, to the named exchange. * - * @param consumer + * <p/>Note that this operation automatically retries in the event of fail-over. * - * @throws AMQException + * @param queueName The name of the queue to bind. + * @param routingKey The routing key to bind the queue with. + * @param arguments Additional arguments. + * @param exchangeName The exchange to bind the queue on. + * + * @throws AMQException If the queue cannot be bound for any reason. */ - void registerConsumer(BasicMessageConsumer consumer, boolean nowait) throws AMQException + /*private void bindQueue(AMQDestination amqd, AMQShortString queueName, AMQProtocolHandler protocolHandler, FieldTable ft) + throws AMQException, FailoverException { - AMQDestination amqd = consumer.getDestination(); - - AMQProtocolHandler protocolHandler = getProtocolHandler(); - - declareExchange(amqd, protocolHandler, false); - - AMQShortString queueName = declareQueue(amqd, protocolHandler); - - bindQueue(amqd, queueName, protocolHandler, consumer.getRawSelectorFieldTable()); + AMQFrame queueBind = + QueueBindBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), ft, // arguments + amqd.getExchangeName(), // exchange + false, // nowait + queueName, // queue + amqd.getRoutingKey(), // routingKey + getTicket()); // ticket - // If IMMEDIATE_PREFETCH is not required then suspsend the channel to delay prefetch - if (!_immediatePrefetch) - { - // The dispatcher will be null if we have just created this session - // so suspend the channel before we register our consumer so that we don't - // start prefetching until a receive/mListener is set. - if (_dispatcher == null) - { - if (!isSuspended()) - { - try - { - suspendChannel(true); - _logger.info("Prefetching delayed existing messages will not flow until requested via receive*() or setML()."); - } - catch (AMQException e) - { - _logger.info("Suspending channel threw an exception:" + e); - } - } - } - } - else - { - _logger.info("Immediately prefetching existing messages to new consumer."); - } + protocolHandler.syncWrite(queueBind, QueueBindOkBody.class); + }*/ - try - { - consumeFromQueue(consumer, queueName, protocolHandler, nowait, consumer.getMessageSelector()); - } - catch (JMSException e) //thrown by getMessageSelector + private void checkNotTransacted() throws JMSException + { + if (getTransacted()) { - throw new AMQException(null, e.getMessage(), e); + throw new IllegalStateException("Session is transacted"); } } - /** - * Called by the MessageConsumer when closing, to deregister the consumer from the map from consumerTag to consumer - * instance. - * - * @param consumer the consum - */ - void deregisterConsumer(BasicMessageConsumer consumer) + private void checkTemporaryDestination(Destination destination) throws JMSException { - if (_consumers.remove(consumer.getConsumerTag()) != null) + if ((destination instanceof TemporaryDestination)) { - String subscriptionName = _reverseSubscriptionMap.remove(consumer); - if (subscriptionName != null) + _logger.debug("destination is temporary"); + final TemporaryDestination tempDest = (TemporaryDestination) destination; + if (tempDest.getSession() != this) { - _subscriptions.remove(subscriptionName); + _logger.debug("destination is on different session"); + throw new JMSException("Cannot consume from a temporary destination created onanother session"); } - Destination dest = consumer.getDestination(); - synchronized (dest) + if (tempDest.isDeleted()) { - if (_destinationConsumerCount.get(dest).decrementAndGet() == 0) - { - _destinationConsumerCount.remove(dest); - } + _logger.debug("destination is deleted"); + throw new JMSException("Cannot consume from a deleted destination"); } } } - private void registerProducer(long producerId, MessageProducer producer) + private void checkTransacted() throws JMSException { - _producers.put(new Long(producerId), producer); + if (!getTransacted()) + { + throw new IllegalStateException("Session is not transacted"); + } } - void deregisterProducer(long producerId) + private void checkValidDestination(Destination destination) throws InvalidDestinationException { - _producers.remove(new Long(producerId)); + if (destination == null) + { + throw new javax.jms.InvalidDestinationException("Invalid Queue"); + } } - private long getNextProducerId() + private void checkValidQueue(Queue queue) throws InvalidDestinationException { - return ++_nextProducerId; + if (queue == null) + { + throw new javax.jms.InvalidDestinationException("Invalid Queue"); + } } - /** - * Resubscribes all producers and consumers. This is called when performing failover. - * - * @throws AMQException + /* + * I could have combined the last 3 methods, but this way it improves readability */ - void resubscribe() throws AMQException + private AMQTopic checkValidTopic(Topic topic) throws JMSException { - resubscribeProducers(); - resubscribeConsumers(); + if (topic == null) + { + throw new javax.jms.InvalidDestinationException("Invalid Topic"); + } + + if ((topic instanceof TemporaryDestination) && (((TemporaryDestination) topic).getSession() != this)) + { + throw new javax.jms.InvalidDestinationException( + "Cannot create a subscription on a temporary topic created in another session"); + } + + if (!(topic instanceof AMQTopic)) + { + throw new javax.jms.InvalidDestinationException( + "Cannot create a subscription on topic created for another JMS Provider, class of topic provided is: " + + topic.getClass().getName()); + } + + return (AMQTopic) topic; } - private void resubscribeProducers() throws AMQException + /** + * Called to close message consumers cleanly. This may or may <b>not</b> be as a result of an error. + * + * @param error not null if this is a result of an error occurring at the connection level + */ + private void closeConsumers(Throwable error) throws JMSException { - ArrayList producers = new ArrayList(_producers.values()); - _logger.info(MessageFormat.format("Resubscribing producers = {0} producers.size={1}", producers, producers.size())); // FIXME: removeKey - for (Iterator it = producers.iterator(); it.hasNext();) + if (_dispatcher != null) { - BasicMessageProducer producer = (BasicMessageProducer) it.next(); - producer.resubscribe(); + _dispatcher.close(); + _dispatcher = null; } + // we need to clone the list of consumers since the close() method updates the _consumers collection + // which would result in a concurrent modification exception + final ArrayList<BasicMessageConsumer> clonedConsumers = new ArrayList<BasicMessageConsumer>(_consumers.values()); + + final Iterator<BasicMessageConsumer> it = clonedConsumers.iterator(); + while (it.hasNext()) + { + final BasicMessageConsumer con = it.next(); + if (error != null) + { + con.notifyError(error); + } + else + { + con.close(); + } + } + // at this point the _consumers map will be empty } - private void resubscribeConsumers() throws AMQException + /** + * Called to close message producers cleanly. This may or may <b>not</b> be as a result of an error. There is + * currently no way of propagating errors to message producers (this is a JMS limitation). + */ + private void closeProducers() throws JMSException { - ArrayList consumers = new ArrayList(_consumers.values()); - _consumers.clear(); + // we need to clone the list of producers since the close() method updates the _producers collection + // which would result in a concurrent modification exception + final ArrayList clonedProducers = new ArrayList(_producers.values()); - for (Iterator it = consumers.iterator(); it.hasNext();) + final Iterator it = clonedProducers.iterator(); + while (it.hasNext()) { - BasicMessageConsumer consumer = (BasicMessageConsumer) it.next(); - registerConsumer(consumer, true); + final BasicMessageProducer prod = (BasicMessageProducer) it.next(); + prod.close(); } + // at this point the _producers map is empty } - private void suspendChannel(boolean suspend) throws AMQException + /** + * Close all producers or consumers. This is called either in the error case or when closing the session normally. + * + * @param amqe the exception, may be null to indicate no error has occurred + */ + private void closeProducersAndConsumers(AMQException amqe) throws JMSException { - synchronized (_suspensionLock) + JMSException jmse = null; + try { - if (_logger.isDebugEnabled()) + closeProducers(); + } + catch (JMSException e) + { + _logger.error("Error closing session: " + e, e); + jmse = e; + } + + try + { + closeConsumers(amqe); + } + catch (JMSException e) + { + _logger.error("Error closing session: " + e, e); + if (jmse == null) { - _logger.debug("Setting channel flow : " + (suspend ? "suspended" : "unsuspended")); + jmse = e; } + } - _suspended = suspend; - - // TODO: Connect this to the session version obtained from ProtocolInitiation for this session. - // Be aware of possible changes to parameter order as versions change. - AMQFrame channelFlowFrame = ChannelFlowBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), - getProtocolMinorVersion(), - !suspend); // active - - _connection.getProtocolHandler().syncWrite(channelFlowFrame, ChannelFlowOkBody.class); + if (jmse != null) + { + throw jmse; } } - - public void confirmConsumerCancelled(AMQShortString consumerTag) + /** + * Register to consume from the queue. + * + * @param queueName + */ + private void consumeFromQueue(BasicMessageConsumer consumer, AMQShortString queueName, + AMQProtocolHandler protocolHandler, boolean nowait, String messageSelector) throws AMQException, FailoverException { + // need to generate a consumer tag on the client so we can exploit the nowait flag + AMQShortString tag = new AMQShortString(Integer.toString(_nextTag++)); - // Remove the consumer from the map - BasicMessageConsumer consumer = (BasicMessageConsumer) _consumers.get(consumerTag); - if (consumer != null) + FieldTable arguments = FieldTableFactory.newFieldTable(); + if ((messageSelector != null) && !messageSelector.equals("")) { -// fixme this isn't right.. needs to check if _queue contains data for this consumer - if (consumer.isAutoClose())// && _queue.isEmpty()) - { - consumer.closeWhenNoMessages(true); - } + arguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue(), messageSelector); + } - if (!consumer.isNoConsume()) - { - //Clean the Maps up first - //Flush any pending messages for this consumerTag - if (_dispatcher != null) - { - _logger.info("Dispatcher is not null"); - } - else - { - _logger.info("Dispatcher is null so created stopped dispatcher"); + if (consumer.isAutoClose()) + { + arguments.put(AMQPFilterTypes.AUTO_CLOSE.getValue(), Boolean.TRUE); + } - startDistpatcherIfNecessary(true); - } + if (consumer.isNoConsume()) + { + arguments.put(AMQPFilterTypes.NO_CONSUME.getValue(), Boolean.TRUE); + } - _dispatcher.rejectPending(consumer); + consumer.setConsumerTag(tag); + // we must register the consumer in the map before we actually start listening + _consumers.put(tag, consumer); + + try + { + // TODO: Be aware of possible changes to parameter order as versions change. + AMQFrame jmsConsume = + BasicConsumeBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), arguments, // arguments + tag, // consumerTag + consumer.isExclusive(), // exclusive + consumer.getAcknowledgeMode() == Session.NO_ACKNOWLEDGE, // noAck + consumer.isNoLocal(), // noLocal + nowait, // nowait + queueName, // queue + getTicket()); // ticket + + if (nowait) + { + protocolHandler.writeFrame(jmsConsume); } else { - //Just close the consumer - //fixme the CancelOK is being processed before the arriving messages.. - // The dispatcher is still to process them so the server sent in order but the client - // has yet to receive before the close comes in. - -// consumer.markClosed(); + protocolHandler.syncWrite(jmsConsume, BasicConsumeOkBody.class); } } - else + catch (AMQException e) { - _logger.warn("Unable to confirm cancellation of consumer (" + consumerTag + "). Not found in consumer map."); + // clean-up the map in the event of an error + _consumers.remove(tag); + throw e; } + } + private BasicMessageProducer createProducerImpl(Destination destination, boolean mandatory, boolean immediate) + throws JMSException + { + return createProducerImpl(destination, mandatory, immediate, false); + } + private BasicMessageProducer createProducerImpl(final Destination destination, final boolean mandatory, + final boolean immediate, final boolean waitUntilSent) throws JMSException + { + return new FailoverRetrySupport<BasicMessageProducer, JMSException>( + new FailoverProtectedOperation<BasicMessageProducer, JMSException>() + { + public BasicMessageProducer execute() throws JMSException, FailoverException + { + checkNotClosed(); + long producerId = getNextProducerId(); + BasicMessageProducer producer = + new BasicMessageProducer(_connection, (AMQDestination) destination, _transacted, _channelId, + AMQSession.this, getProtocolHandler(), producerId, immediate, mandatory, waitUntilSent); + registerProducer(producerId, producer); + + return producer; + } + }, _connection).execute(); } - /* - * I could have combined the last 3 methods, but this way it improves readability - */ - private AMQTopic checkValidTopic(Topic topic) throws JMSException + private void declareExchange(AMQDestination amqd, AMQProtocolHandler protocolHandler, boolean nowait) throws AMQException { - if (topic == null) - { - throw new javax.jms.InvalidDestinationException("Invalid Topic"); - } - if ((topic instanceof TemporaryDestination) && ((TemporaryDestination) topic).getSession() != this) - { - throw new javax.jms.InvalidDestinationException("Cannot create a subscription on a temporary topic created in another session"); - } - if (!(topic instanceof AMQTopic)) - { - throw new javax.jms.InvalidDestinationException("Cannot create a subscription on topic created for another JMS Provider, class of topic provided is: " + topic.getClass().getName()); - } - return (AMQTopic) topic; + declareExchange(amqd.getExchangeName(), amqd.getExchangeClass(), protocolHandler, nowait); } - private void checkValidQueue(Queue queue) throws InvalidDestinationException + /** + * Declares the named exchange and type of exchange. + * + * <p/>Note that this operation automatically retries in the event of fail-over. + * + * @param name The name of the exchange to declare. + * @param type The type of the exchange to declare. + * @param protocolHandler The protocol handler to process the communication through. + * @param nowait + * + * @throws AMQException If the exchange cannot be declared for any reason. + * @todo Be aware of possible changes to parameter order as versions change. + */ + private void declareExchange(final AMQShortString name, final AMQShortString type, + final AMQProtocolHandler protocolHandler, final boolean nowait) throws AMQException { - if (queue == null) + new FailoverNoopSupport<Object, AMQException>(new FailoverProtectedOperation<Object, AMQException>() { - throw new javax.jms.InvalidDestinationException("Invalid Queue"); - } + public Object execute() throws AMQException, FailoverException + { + AMQFrame exchangeDeclare = + ExchangeDeclareBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), + null, // arguments + false, // autoDelete + false, // durable + name, // exchange + false, // internal + nowait, // nowait + false, // passive + getTicket(), // ticket + type); // type + + protocolHandler.syncWrite(exchangeDeclare, ExchangeDeclareOkBody.class); + + return null; + } + }, _connection).execute(); } - private void checkValidDestination(Destination destination) throws InvalidDestinationException + /** + * Declares a queue for a JMS destination. + * + * <p/>Note that for queues but not topics the name is generated in the client rather than the server. This allows + * the name to be reused on failover if required. In general, the destination indicates whether it wants a name + * generated or not. + * + * <p/>Note that this operation automatically retries in the event of fail-over. + * + * @param amqd The destination to declare as a queue. + * @param protocolHandler The protocol handler to communicate through. + * + * @return The name of the decalred queue. This is useful where the broker is generating a queue name on behalf of + * the client. + * + * @throws AMQException If the queue cannot be declared for any reason. + * @todo Verify the destiation is valid or throw an exception. + * @todo Be aware of possible changes to parameter order as versions change. + */ + private AMQShortString declareQueue(final AMQDestination amqd, final AMQProtocolHandler protocolHandler) + throws AMQException { - if (destination == null) + /*return new FailoverRetrySupport<AMQShortString, AMQException>(*/ + return new FailoverNoopSupport<AMQShortString, AMQException>( + new FailoverProtectedOperation<AMQShortString, AMQException>() + { + public AMQShortString execute() throws AMQException, FailoverException + { + // Generate the queue name if the destination indicates that a client generated name is to be used. + if (amqd.isNameRequired()) + { + amqd.setQueueName(protocolHandler.generateQueueName()); + } + + AMQFrame queueDeclare = + QueueDeclareBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), + null, // arguments + amqd.isAutoDelete(), // autoDelete + amqd.isDurable(), // durable + amqd.isExclusive(), // exclusive + false, // nowait + false, // passive + amqd.getAMQQueueName(), // queue + getTicket()); // ticket + + protocolHandler.syncWrite(queueDeclare, QueueDeclareOkBody.class); + + return amqd.getAMQQueueName(); + } + }, _connection).execute(); + } + + /** + * Undeclares the specified queue. + * + * <p/>Note that this operation automatically retries in the event of fail-over. + * + * @param queueName The name of the queue to delete. + * + * @throws JMSException If the queue could not be deleted for any reason. + * @todo Be aware of possible changes to parameter order as versions change. + */ + private void deleteQueue(final AMQShortString queueName) throws JMSException + { + try { - throw new javax.jms.InvalidDestinationException("Invalid Queue"); + new FailoverRetrySupport<Object, AMQException>(new FailoverProtectedOperation<Object, AMQException>() + { + public Object execute() throws AMQException, FailoverException + { + AMQFrame queueDeleteFrame = + QueueDeleteBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), + false, // ifEmpty + false, // ifUnused + true, // nowait + queueName, // queue + getTicket()); // ticket + + getProtocolHandler().syncWrite(queueDeleteFrame, QueueDeleteOkBody.class); + + return null; + } + }, _connection).execute(); + } + catch (AMQException e) + { + throw new JMSAMQException("The queue deletion failed: " + e.getMessage(), e); } } - - public AMQShortString getTemporaryTopicExchangeName() + private long getNextProducerId() { - return _connection.getTemporaryTopicExchangeName(); + return ++_nextProducerId; } - public AMQShortString getTemporaryQueueExchangeName() + private AMQProtocolHandler getProtocolHandler() { - return _connection.getTemporaryQueueExchangeName(); + return _connection.getProtocolHandler(); } - - public int getTicket() + private byte getProtocolMajorVersion() { - return _ticket; + return getProtocolHandler().getProtocolMajorVersion(); } - public void setTicket(int ticket) + private byte getProtocolMinorVersion() { - _ticket = ticket; + return getProtocolHandler().getProtocolMinorVersion(); } + private boolean hasMessageListeners() + { + return _hasMessageListeners; + } - public void requestAccess(AMQShortString realm, boolean exclusive, boolean passive, boolean active, boolean write, boolean read) throws AMQException + private void markClosedConsumers() throws JMSException { - getProtocolHandler().writeCommandFrameAndWaitForReply(AccessRequestBody.createAMQFrame(getChannelId(), - getProtocolMajorVersion(), - getProtocolMinorVersion(), - active, - exclusive, - passive, - read, - realm, - write), - new BlockingMethodFrameListener(_channelId) - { - - public boolean processMethod(int channelId, AMQMethodBody frame) throws AMQException - { - if (frame instanceof AccessRequestOkBody) - { - setTicket(((AccessRequestOkBody) frame).getTicket()); - return true; - } - else - { - return false; - } - } - }); + if (_dispatcher != null) + { + _dispatcher.close(); + _dispatcher = null; + } + // we need to clone the list of consumers since the close() method updates the _consumers collection + // which would result in a concurrent modification exception + final ArrayList<BasicMessageConsumer> clonedConsumers = new ArrayList<BasicMessageConsumer>(_consumers.values()); + final Iterator<BasicMessageConsumer> it = clonedConsumers.iterator(); + while (it.hasNext()) + { + final BasicMessageConsumer con = it.next(); + con.markClosed(); + } + // at this point the _consumers map will be empty } - private class SuspenderRunner implements Runnable + private void markClosedProducersAndConsumers() { - private boolean _suspend; + try + { + // no need for a markClosed* method in this case since there is no protocol traffic closing a producer + closeProducers(); + } + catch (JMSException e) + { + _logger.error("Error closing session: " + e, e); + } - public SuspenderRunner(boolean suspend) + try { - _suspend = suspend; + markClosedConsumers(); } + catch (JMSException e) + { + _logger.error("Error closing session: " + e, e); + } + } - public void run() + /** + * Callers must hold the failover mutex before calling this method. + * + * @param consumer + * + * @throws AMQException + */ + private void registerConsumer(BasicMessageConsumer consumer, boolean nowait) throws AMQException // , FailoverException + { + AMQDestination amqd = consumer.getDestination(); + + AMQProtocolHandler protocolHandler = getProtocolHandler(); + + declareExchange(amqd, protocolHandler, false); + + AMQShortString queueName = declareQueue(amqd, protocolHandler); + + // bindQueue(amqd, queueName, protocolHandler, consumer.getRawSelectorFieldTable()); + bindQueue(queueName, amqd.getRoutingKey(), consumer.getRawSelectorFieldTable(), amqd.getExchangeName()); + + // If IMMEDIATE_PREFETCH is not required then suspsend the channel to delay prefetch + if (!_immediatePrefetch) { - try - { - suspendChannel(_suspend); - } - catch (AMQException e) + // The dispatcher will be null if we have just created this session + // so suspend the channel before we register our consumer so that we don't + // start prefetching until a receive/mListener is set. + if (_dispatcher == null) { - _logger.warn("Unable to suspend channel"); + if (!isSuspended()) + { + try + { + suspendChannel(true); + _logger.info( + "Prefetching delayed existing messages will not flow until requested via receive*() or setML()."); + } + catch (AMQException e) + { + _logger.info("Suspending channel threw an exception:" + e); + } + } } } + else + { + _logger.info("Immediately prefetching existing messages to new consumer."); + } + + try + { + consumeFromQueue(consumer, queueName, protocolHandler, nowait, consumer.getMessageSelector()); + } + catch (JMSException e) // thrown by getMessageSelector + { + throw new AMQException(null, e.getMessage(), e); + } + catch (FailoverException e) + { + throw new AMQException(null, "Fail-over exception interrupted basic consume.", e); + } } + private void registerProducer(long producerId, MessageProducer producer) + { + _producers.put(new Long(producerId), producer); + } private void rejectAllMessages(boolean requeue) { @@ -2396,8 +2351,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi Iterator messages = _queue.iterator(); if (_logger.isInfoEnabled()) { - _logger.info("Rejecting messages from _queue for Consumer tag(" + consumerTag + - ") (PDispatchQ) requeue:" + requeue); + _logger.info("Rejecting messages from _queue for Consumer tag(" + consumerTag + ") (PDispatchQ) requeue:" + + requeue); if (messages.hasNext()) { @@ -2412,12 +2367,12 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi { UnprocessedMessage message = (UnprocessedMessage) messages.next(); - if (consumerTag == null || message.getDeliverBody().consumerTag.equals(consumerTag)) + if ((consumerTag == null) || message.getDeliverBody().consumerTag.equals(consumerTag)) { if (_logger.isDebugEnabled()) { - _logger.debug("Removing message(" + System.identityHashCode(message) + - ") from _queue DT:" + message.getDeliverBody().deliveryTag); + _logger.debug("Removing message(" + System.identityHashCode(message) + ") from _queue DT:" + + message.getDeliverBody().deliveryTag); } messages.remove(); @@ -2432,50 +2387,360 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi } } - - public void rejectMessage(UnprocessedMessage message, boolean requeue) + private void resubscribeConsumers() throws AMQException { + ArrayList consumers = new ArrayList(_consumers.values()); + _consumers.clear(); - if (_logger.isTraceEnabled()) + for (Iterator it = consumers.iterator(); it.hasNext();) { - _logger.trace("Rejecting Unacked message:" + message.getDeliverBody().deliveryTag); + BasicMessageConsumer consumer = (BasicMessageConsumer) it.next(); + registerConsumer(consumer, true); } - - rejectMessage(message.getDeliverBody().deliveryTag, requeue); } - public void rejectMessage(AbstractJMSMessage message, boolean requeue) + private void resubscribeProducers() throws AMQException { - if (_logger.isTraceEnabled()) + ArrayList producers = new ArrayList(_producers.values()); + _logger.info(MessageFormat.format("Resubscribing producers = {0} producers.size={1}", producers, producers.size())); // FIXME: removeKey + for (Iterator it = producers.iterator(); it.hasNext();) { - _logger.trace("Rejecting Abstract message:" + message.getDeliveryTag()); + BasicMessageProducer producer = (BasicMessageProducer) it.next(); + producer.resubscribe(); } - rejectMessage(message.getDeliveryTag(), requeue); - } - public void rejectMessage(long deliveryTag, boolean requeue) + private void returnBouncedMessage(final UnprocessedMessage message) { - if (_acknowledgeMode == CLIENT_ACKNOWLEDGE || - _acknowledgeMode == SESSION_TRANSACTED) + _connection.performConnectionTask(new Runnable() { - if (_logger.isDebugEnabled()) + public void run() { - _logger.debug("Rejecting delivery tag:" + deliveryTag); + try + { + // Bounced message is processed here, away from the mina thread + AbstractJMSMessage bouncedMessage = + _messageFactoryRegistry.createMessage(0, false, message.getBounceBody().exchange, + message.getBounceBody().routingKey, message.getContentHeader(), message.getBodies()); + + AMQConstant errorCode = AMQConstant.getConstant(message.getBounceBody().replyCode); + AMQShortString reason = message.getBounceBody().replyText; + _logger.debug("Message returned with error code " + errorCode + " (" + reason + ")"); + + // @TODO should this be moved to an exception handler of sorts. Somewhere errors are converted to correct execeptions. + if (errorCode == AMQConstant.NO_CONSUMERS) + { + _connection.exceptionReceived(new AMQNoConsumersException("Error: " + reason, bouncedMessage, null)); + } + else if (errorCode == AMQConstant.NO_ROUTE) + { + _connection.exceptionReceived(new AMQNoRouteException("Error: " + reason, bouncedMessage, null)); + } + else + { + _connection.exceptionReceived( + new AMQUndeliveredException(errorCode, "Error: " + reason, bouncedMessage, null)); + } + + } + catch (Exception e) + { + _logger.error( + "Caught exception trying to raise undelivered message exception (dump follows) - ignoring...", + e); + } } - AMQFrame basicRejectBody = BasicRejectBody.createAMQFrame(_channelId, - getProtocolMajorVersion(), - getProtocolMinorVersion(), - deliveryTag, - requeue); + }); + } - _connection.getProtocolHandler().writeFrame(basicRejectBody); + /** + * Suspends or unsuspends this session. + * + * @param suspend <tt>true</tt> indicates that the session should be suspended, <tt>false<tt> indicates that it + * should be unsuspended. + * + * @throws AMQException If the session cannot be suspended for any reason. + * @todo Be aware of possible changes to parameter order as versions change. + */ + private void suspendChannel(boolean suspend) throws AMQException // , FailoverException + { + synchronized (_suspensionLock) + { + try + { + if (_logger.isDebugEnabled()) + { + _logger.debug("Setting channel flow : " + (suspend ? "suspended" : "unsuspended")); + } + + _suspended = suspend; + + AMQFrame channelFlowFrame = + ChannelFlowBody.createAMQFrame(_channelId, getProtocolMajorVersion(), getProtocolMinorVersion(), + !suspend); + + _connection.getProtocolHandler().syncWrite(channelFlowFrame, ChannelFlowOkBody.class); + } + catch (FailoverException e) + { + throw new AMQException(null, "Fail-over interrupted suspend/unsuspend channel.", e); + } } } - public boolean isStrictAMQP() + /** Responsible for decoding a message fragment and passing it to the appropriate message consumer. */ + private class Dispatcher extends Thread { - return _strictAMQP; + + /** Track the 'stopped' state of the dispatcher, a session starts in the stopped state. */ + private final AtomicBoolean _closed = new AtomicBoolean(false); + + private final Object _lock = new Object(); + + public Dispatcher() + { + super("Dispatcher-Channel-" + _channelId); + if (_dispatcherLogger.isInfoEnabled()) + { + _dispatcherLogger.info(getName() + " created"); + } + } + + public void close() + { + _closed.set(true); + interrupt(); + + // fixme awaitTermination + + } + + public void rejectPending(BasicMessageConsumer consumer) + { + synchronized (_lock) + { + boolean stopped = _dispatcher.connectionStopped(); + + if (!stopped) + { + _dispatcher.setConnectionStopped(true); + } + + // Reject messages on pre-receive queue + consumer.rollback(); + + // Reject messages on pre-dispatch queue + rejectMessagesForConsumerTag(consumer.getConsumerTag(), true); + + // closeConsumer + consumer.markClosed(); + + _dispatcher.setConnectionStopped(stopped); + + } + } + + public void rollback() + { + + synchronized (_lock) + { + boolean isStopped = connectionStopped(); + + if (!isStopped) + { + setConnectionStopped(true); + } + + rejectAllMessages(true); + + _dispatcherLogger.debug("Session Pre Dispatch Queue cleared"); + + for (BasicMessageConsumer consumer : _consumers.values()) + { + if (!consumer.isNoConsume()) + { + consumer.rollback(); + } + else + { + // should perhaps clear the _SQ here. + // consumer._synchronousQueue.clear(); + consumer.clearReceiveQueue(); + } + + } + + setConnectionStopped(isStopped); + } + + } + + public void run() + { + if (_dispatcherLogger.isInfoEnabled()) + { + _dispatcherLogger.info(getName() + " started"); + } + + UnprocessedMessage message; + + // Allow disptacher to start stopped + synchronized (_lock) + { + while (connectionStopped()) + { + try + { + _lock.wait(); + } + catch (InterruptedException e) + { + // ignore + } + } + } + + try + { + while (!_closed.get() && ((message = (UnprocessedMessage) _queue.take()) != null)) + { + synchronized (_lock) + { + + while (connectionStopped()) + { + _lock.wait(); + } + + dispatchMessage(message); + + while (connectionStopped()) + { + _lock.wait(); + } + + } + + } + } + catch (InterruptedException e) + { + // ignore + } + + if (_dispatcherLogger.isInfoEnabled()) + { + _dispatcherLogger.info(getName() + " thread terminating for channel " + _channelId); + } + } + + // only call while holding lock + final boolean connectionStopped() + { + return _connectionStopped; + } + + boolean setConnectionStopped(boolean connectionStopped) + { + boolean currently; + synchronized (_lock) + { + currently = _connectionStopped; + _connectionStopped = connectionStopped; + _lock.notify(); + + if (_dispatcherLogger.isDebugEnabled()) + { + _dispatcherLogger.debug("Set Dispatcher Connection " + (connectionStopped ? "Stopped" : "Started") + + ": Currently " + (currently ? "Stopped" : "Started")); + } + } + + return currently; + } + + private void dispatchMessage(UnprocessedMessage message) + { + if (message.getDeliverBody() != null) + { + final BasicMessageConsumer consumer = + (BasicMessageConsumer) _consumers.get(message.getDeliverBody().consumerTag); + + if ((consumer == null) || consumer.isClosed()) + { + if (_dispatcherLogger.isInfoEnabled()) + { + if (consumer == null) + { + _dispatcherLogger.info("Received a message(" + System.identityHashCode(message) + ")" + "[" + + message.getDeliverBody().deliveryTag + "] from queue " + + message.getDeliverBody().consumerTag + " )without a handler - rejecting(requeue)..."); + } + else + { + _dispatcherLogger.info("Received a message(" + System.identityHashCode(message) + ")" + "[" + + message.getDeliverBody().deliveryTag + "] from queue " + " consumer(" + + consumer.debugIdentity() + ") is closed rejecting(requeue)..."); + } + } + // Don't reject if we're already closing + if (!_closed.get()) + { + rejectMessage(message, true); + } + } + else + { + consumer.notifyMessage(message, _channelId); + } + } + } } + /*public void requestAccess(AMQShortString realm, boolean exclusive, boolean passive, boolean active, boolean write, + boolean read) throws AMQException + { + getProtocolHandler().writeCommandFrameAndWaitForReply(AccessRequestBody.createAMQFrame(getChannelId(), + getProtocolMajorVersion(), getProtocolMinorVersion(), active, exclusive, passive, read, realm, write), + new BlockingMethodFrameListener(_channelId) + { + + public boolean processMethod(int channelId, AMQMethodBody frame) // throws AMQException + { + if (frame instanceof AccessRequestOkBody) + { + setTicket(((AccessRequestOkBody) frame).getTicket()); + + return true; + } + else + { + return false; + } + } + }); + }*/ + + private class SuspenderRunner implements Runnable + { + private boolean _suspend; + + public SuspenderRunner(boolean suspend) + { + _suspend = suspend; + } + + public void run() + { + try + { + suspendChannel(_suspend); + } + catch (AMQException e) + { + _logger.warn("Unable to suspend channel"); + } + } + } } 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 1c3cdbcb65..dfac0d45a8 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 @@ -20,22 +20,8 @@ */ package org.apache.qpid.client; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; - -import org.apache.log4j.Logger; - import org.apache.qpid.AMQException; +import org.apache.qpid.client.failover.FailoverException; import org.apache.qpid.client.message.AbstractJMSMessage; import org.apache.qpid.client.message.MessageFactoryRegistry; import org.apache.qpid.client.message.UnprocessedMessage; @@ -48,9 +34,25 @@ import org.apache.qpid.framing.FieldTable; import org.apache.qpid.jms.MessageConsumer; import org.apache.qpid.jms.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + public class BasicMessageConsumer extends Closeable implements MessageConsumer { - private static final Logger _logger = Logger.getLogger(BasicMessageConsumer.class); + private static final Logger _logger = LoggerFactory.getLogger(BasicMessageConsumer.class); /** The connection being used by this consumer */ private AMQConnection _connection; @@ -140,9 +142,9 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer private List<StackTraceElement> _closedStack = null; protected BasicMessageConsumer(int channelId, AMQConnection connection, AMQDestination destination, - String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory, AMQSession session, - AMQProtocolHandler protocolHandler, FieldTable rawSelectorFieldTable, int prefetchHigh, int prefetchLow, - boolean exclusive, int acknowledgeMode, boolean noConsume, boolean autoClose) + String messageSelector, boolean noLocal, MessageFactoryRegistry messageFactory, AMQSession session, + AMQProtocolHandler protocolHandler, FieldTable rawSelectorFieldTable, int prefetchHigh, int prefetchLow, + boolean exclusive, int acknowledgeMode, boolean noConsume, boolean autoClose) { _channelId = channelId; _connection = connection; @@ -219,7 +221,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer if (_logger.isDebugEnabled()) { _logger.debug("Session stopped : Message listener(" + messageListener + ") set for destination " - + _destination); + + _destination); } } else @@ -468,7 +470,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer if (_closedStack != null) { _logger.trace(_consumerTag + " close():" - + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6)); + + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 6)); _logger.trace(_consumerTag + " previously:" + _closedStack.toString()); } else @@ -481,9 +483,9 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer { // TODO: Be aware of possible changes to parameter order as versions change. final AMQFrame cancelFrame = - BasicCancelBody.createAMQFrame(_channelId, _protocolHandler.getProtocolMajorVersion(), - _protocolHandler.getProtocolMinorVersion(), _consumerTag, // consumerTag - false); // nowait + BasicCancelBody.createAMQFrame(_channelId, _protocolHandler.getProtocolMajorVersion(), + _protocolHandler.getProtocolMinorVersion(), _consumerTag, // consumerTag + false); // nowait try { @@ -497,10 +499,11 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer } catch (AMQException e) { - // _logger.error("Error closing consumer: " + e, e); - JMSException jmse = new JMSException("Error closing consumer: " + e); - jmse.setLinkedException(e); - throw jmse; + throw new JMSAMQException("Error closing consumer: " + e, e); + } + catch (FailoverException e) + { + throw new JMSAMQException("FailoverException interrupted basic cancel.", e); } } else @@ -540,7 +543,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer if (_closedStack != null) { _logger.trace(_consumerTag + " markClosed():" - + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8)); + + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8)); _logger.trace(_consumerTag + " previously:" + _closedStack.toString()); } else @@ -572,9 +575,9 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer try { AbstractJMSMessage jmsMessage = - _messageFactory.createMessage(messageFrame.getDeliverBody().deliveryTag, - messageFrame.getDeliverBody().redelivered, messageFrame.getDeliverBody().exchange, - messageFrame.getDeliverBody().routingKey, messageFrame.getContentHeader(), messageFrame.getBodies()); + _messageFactory.createMessage(messageFrame.getDeliverBody().deliveryTag, + messageFrame.getDeliverBody().redelivered, messageFrame.getDeliverBody().exchange, + messageFrame.getDeliverBody().routingKey, messageFrame.getContentHeader(), messageFrame.getBodies()); if (debug) { @@ -659,15 +662,15 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer switch (_acknowledgeMode) { - case Session.PRE_ACKNOWLEDGE: - _session.acknowledgeMessage(msg.getDeliveryTag(), false); - break; + case Session.PRE_ACKNOWLEDGE: + _session.acknowledgeMessage(msg.getDeliveryTag(), false); + break; - case Session.CLIENT_ACKNOWLEDGE: - // we set the session so that when the user calls acknowledge() it can call the method on session - // to send out the appropriate frame - msg.setAMQSession(_session); - break; + case Session.CLIENT_ACKNOWLEDGE: + // we set the session so that when the user calls acknowledge() it can call the method on session + // to send out the appropriate frame + msg.setAMQSession(_session); + break; } } @@ -677,55 +680,55 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer switch (_acknowledgeMode) { - case Session.CLIENT_ACKNOWLEDGE: - if (isNoConsume()) - { - _session.acknowledgeMessage(msg.getDeliveryTag(), false); - } + case Session.CLIENT_ACKNOWLEDGE: + if (isNoConsume()) + { + _session.acknowledgeMessage(msg.getDeliveryTag(), false); + } - break; + break; - case Session.DUPS_OK_ACKNOWLEDGE: - if (++_outstanding >= _prefetchHigh) - { - _dups_ok_acknowledge_send = true; - } + case Session.DUPS_OK_ACKNOWLEDGE: + if (++_outstanding >= _prefetchHigh) + { + _dups_ok_acknowledge_send = true; + } - if (_outstanding <= _prefetchLow) - { - _dups_ok_acknowledge_send = false; - } + if (_outstanding <= _prefetchLow) + { + _dups_ok_acknowledge_send = false; + } - if (_dups_ok_acknowledge_send) + if (_dups_ok_acknowledge_send) + { + if (!_session.isInRecovery()) { - if (!_session.isInRecovery()) - { - _session.acknowledgeMessage(msg.getDeliveryTag(), true); - } + _session.acknowledgeMessage(msg.getDeliveryTag(), true); } + } - break; + break; - case Session.AUTO_ACKNOWLEDGE: - // we do not auto ack a message if the application code called recover() - if (!_session.isInRecovery()) - { - _session.acknowledgeMessage(msg.getDeliveryTag(), false); - } + case Session.AUTO_ACKNOWLEDGE: + // we do not auto ack a message if the application code called recover() + if (!_session.isInRecovery()) + { + _session.acknowledgeMessage(msg.getDeliveryTag(), false); + } - break; + break; - case Session.SESSION_TRANSACTED: - if (isNoConsume()) - { - _session.acknowledgeMessage(msg.getDeliveryTag(), false); - } - else - { - _receivedDeliveryTags.add(msg.getDeliveryTag()); - } + case Session.SESSION_TRANSACTED: + if (isNoConsume()) + { + _session.acknowledgeMessage(msg.getDeliveryTag(), false); + } + else + { + _receivedDeliveryTags.add(msg.getDeliveryTag()); + } - break; + break; } } @@ -757,7 +760,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer if (_closedStack != null) { _logger.trace(_consumerTag + " notifyError():" - + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8)); + + Arrays.asList(Thread.currentThread().getStackTrace()).subList(3, 8)); _logger.trace(_consumerTag + " previously" + _closedStack.toString()); } else @@ -817,7 +820,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer } } - public void acknowledge() throws JMSException + public void acknowledge() // throws JMSException { if (!isClosed()) { @@ -877,7 +880,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer if (_logger.isDebugEnabled()) { _logger.debug("Rejecting the messages(" + _receivedDeliveryTags.size() + ") in _receivedDTs (RQ)" - + "for consumer with tag:" + _consumerTag); + + "for consumer with tag:" + _consumerTag); } Long tag = _receivedDeliveryTags.poll(); @@ -907,7 +910,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer if (_logger.isDebugEnabled()) { _logger.debug("Rejecting the messages(" + _synchronousQueue.size() + ") in _syncQueue (PRQ)" - + "for consumer with tag:" + _consumerTag); + + "for consumer with tag:" + _consumerTag); } Iterator iterator = _synchronousQueue.iterator(); @@ -931,7 +934,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer else { _logger.error("Queue contained a :" + o.getClass() - + " unable to reject as it is not an AbstractJMSMessage. Will be cleared"); + + " unable to reject as it is not an AbstractJMSMessage. Will be cleared"); iterator.remove(); } } diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java index bd7cc94582..0ee4882ec2 100644 --- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java +++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java @@ -20,8 +20,23 @@ */ package org.apache.qpid.client; -import java.io.UnsupportedEncodingException; -import java.util.UUID; +import org.apache.mina.common.ByteBuffer; + +import org.apache.qpid.AMQException; +import org.apache.qpid.client.message.AbstractJMSMessage; +import org.apache.qpid.client.message.MessageConverter; +import org.apache.qpid.client.protocol.AMQProtocolHandler; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.BasicConsumeBody; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.BasicPublishBody; +import org.apache.qpid.framing.CompositeAMQDataBlock; +import org.apache.qpid.framing.ContentBody; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.ExchangeDeclareBody; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.BytesMessage; import javax.jms.DeliveryMode; @@ -36,24 +51,12 @@ import javax.jms.StreamMessage; import javax.jms.TextMessage; import javax.jms.Topic; -import org.apache.log4j.Logger; -import org.apache.mina.common.ByteBuffer; -import org.apache.qpid.AMQException; -import org.apache.qpid.client.message.AbstractJMSMessage; -import org.apache.qpid.client.message.MessageConverter; -import org.apache.qpid.client.protocol.AMQProtocolHandler; -import org.apache.qpid.framing.AMQFrame; -import org.apache.qpid.framing.BasicConsumeBody; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.BasicPublishBody; -import org.apache.qpid.framing.CompositeAMQDataBlock; -import org.apache.qpid.framing.ContentBody; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.ExchangeDeclareBody; +import java.io.UnsupportedEncodingException; +import java.util.UUID; public class BasicMessageProducer extends Closeable implements org.apache.qpid.jms.MessageProducer { - protected final Logger _logger = Logger.getLogger(getClass()); + protected final Logger _logger = LoggerFactory.getLogger(getClass()); private AMQConnection _connection; @@ -119,14 +122,14 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j private final boolean _mandatory; private final boolean _waitUntilSent; - + private boolean _disableMessageId; - + private static final ContentBody[] NO_CONTENT_BODIES = new ContentBody[0]; protected BasicMessageProducer(AMQConnection connection, AMQDestination destination, boolean transacted, int channelId, - AMQSession session, AMQProtocolHandler protocolHandler, long producerId, - boolean immediate, boolean mandatory, boolean waitUntilSent) + AMQSession session, AMQProtocolHandler protocolHandler, long producerId, boolean immediate, boolean mandatory, + boolean waitUntilSent) { _connection = connection; _destination = destination; @@ -160,15 +163,15 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j // TODO: Be aware of possible changes to parameter order as versions change. AMQFrame declare = ExchangeDeclareBody.createAMQFrame(_channelId, _protocolHandler.getProtocolMajorVersion(), - _protocolHandler.getProtocolMinorVersion(), null, // arguments - false, // autoDelete - false, // durable - destination.getExchangeName(), // exchange - false, // internal - true, // nowait - false, // passive - _session.getTicket(), // ticket - destination.getExchangeClass()); // type + _protocolHandler.getProtocolMinorVersion(), null, // arguments + false, // autoDelete + false, // durable + destination.getExchangeName(), // exchange + false, // internal + true, // nowait + false, // passive + _session.getTicket(), // ticket + destination.getExchangeClass()); // type _protocolHandler.writeFrame(declare); } @@ -205,7 +208,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j if ((i != DeliveryMode.NON_PERSISTENT) && (i != DeliveryMode.PERSISTENT)) { throw new JMSException("DeliveryMode must be either NON_PERSISTENT or PERSISTENT. Value of " + i - + " is illegal"); + + " is illegal"); } _deliveryMode = i; @@ -317,12 +320,12 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j { validateDestination(destination); sendImpl((AMQDestination) destination, message, _deliveryMode, _messagePriority, _timeToLive, _mandatory, - _immediate); + _immediate); } } public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive) - throws JMSException + throws JMSException { checkPreConditions(); checkDestination(destination); @@ -334,7 +337,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j } public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, - boolean mandatory) throws JMSException + boolean mandatory) throws JMSException { checkPreConditions(); checkDestination(destination); @@ -346,7 +349,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j } public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, - boolean mandatory, boolean immediate) throws JMSException + boolean mandatory, boolean immediate) throws JMSException { checkPreConditions(); checkDestination(destination); @@ -358,7 +361,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j } public void send(Destination destination, Message message, int deliveryMode, int priority, long timeToLive, - boolean mandatory, boolean immediate, boolean waitUntilSent) throws JMSException + boolean mandatory, boolean immediate, boolean waitUntilSent) throws JMSException { checkPreConditions(); checkDestination(destination); @@ -366,7 +369,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j { validateDestination(destination); sendImpl((AMQDestination) destination, message, deliveryMode, priority, timeToLive, mandatory, immediate, - waitUntilSent); + waitUntilSent); } } @@ -412,7 +415,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j else { throw new JMSException("Unable to send message, due to class conversion error: " - + message.getClass().getName()); + + message.getClass().getName()); } } } @@ -422,14 +425,14 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j if (!(destination instanceof AMQDestination)) { throw new JMSException("Unsupported destination class: " - + ((destination != null) ? destination.getClass() : null)); + + ((destination != null) ? destination.getClass() : null)); } declareDestination((AMQDestination) destination); } protected void sendImpl(AMQDestination destination, Message message, int deliveryMode, int priority, long timeToLive, - boolean mandatory, boolean immediate) throws JMSException + boolean mandatory, boolean immediate) throws JMSException { sendImpl(destination, message, deliveryMode, priority, timeToLive, mandatory, immediate, _waitUntilSent); } @@ -447,23 +450,23 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j * @throws JMSException */ protected void sendImpl(AMQDestination destination, Message origMessage, int deliveryMode, int priority, long timeToLive, - boolean mandatory, boolean immediate, boolean wait) throws JMSException + boolean mandatory, boolean immediate, boolean wait) throws JMSException { checkTemporaryDestination(destination); origMessage.setJMSDestination(destination); AbstractJMSMessage message = convertToNativeMessage(origMessage); - - if(_disableMessageId) + + if (_disableMessageId) { - message.setJMSMessageID(null); + message.setJMSMessageID(null); } else { - if (message.getJMSMessageID() == null) - { - message.setJMSMessageID(UUID.randomUUID().toString()); - } + if (message.getJMSMessageID() == null) + { + message.setJMSMessageID(UUID.randomUUID().toString()); + } } int type; @@ -486,9 +489,8 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j // TODO: Connect this to the session version obtained from ProtocolInitiation for this session. // Be aware of possible changes to parameter order as versions change. AMQFrame publishFrame = - BasicPublishBody.createAMQFrame( - _channelId, _protocolHandler.getProtocolMajorVersion(), _protocolHandler.getProtocolMinorVersion(), - destination.getExchangeName(), // exchange + BasicPublishBody.createAMQFrame(_channelId, _protocolHandler.getProtocolMajorVersion(), + _protocolHandler.getProtocolMinorVersion(), destination.getExchangeName(), // exchange immediate, // immediate mandatory, // mandatory destination.getRoutingKey(), // routingKey @@ -535,9 +537,8 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j // TODO: Connect this to the session version obtained from ProtocolInitiation for this session. AMQFrame contentHeaderFrame = ContentHeaderBody.createAMQFrame(_channelId, - BasicConsumeBody.getClazz(_protocolHandler.getProtocolMajorVersion(), - _protocolHandler.getProtocolMinorVersion()), 0, - contentHeaderProperties, size); + BasicConsumeBody.getClazz(_protocolHandler.getProtocolMajorVersion(), + _protocolHandler.getProtocolMinorVersion()), 0, contentHeaderProperties, size); if (_logger.isDebugEnabled()) { _logger.debug("Sending content header frame to " + destination); @@ -685,6 +686,6 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j public boolean isBound(AMQDestination destination) throws JMSException { - return _session.isQueueBound(destination.getExchangeName(),null,destination.getRoutingKey()); + return _session.isQueueBound(destination.getExchangeName(), null, destination.getRoutingKey()); } } diff --git a/java/client/src/main/java/org/apache/qpid/client/Closeable.java b/java/client/src/main/java/org/apache/qpid/client/Closeable.java index d246dc3931..7e119343a1 100644 --- a/java/client/src/main/java/org/apache/qpid/client/Closeable.java +++ b/java/client/src/main/java/org/apache/qpid/client/Closeable.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,12 +20,29 @@ */ package org.apache.qpid.client; -import java.util.concurrent.atomic.AtomicBoolean; - import javax.jms.IllegalStateException; import javax.jms.JMSException; -/** Provides support for orderly shutdown of an object. */ +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Captures the 'closed' state of an object, that is initially open, can be tested to see if it is closed, and provides + * a 'close' method to close it. + * + * <p/><table id="crc"><caption>CRC Card</caption> + * <tr><th> Responsibilities <th> Collaborations + * <tr><td> Mark an object as closed. + * <tr><td> Check if an object is closed. + * <tr><td> Raise a JMS exception if an object is closed. + * </table> + * + * @todo Might be better to make this an interface. This whole class doesn't really encapsulate a terribly neat + * piece of re-usable functionality. A simple interface defining a close method would suffice. + * + * @todo The convenience method {@link #checkNotClosed} is not that helpfull, what if the caller wants to do something + * other than throw an exception? It doesn't really represent a very usefull re-usable piece of code. Consider + * inlining it and dropping the method. + */ public abstract class Closeable { /** @@ -34,6 +51,11 @@ public abstract class Closeable */ protected final AtomicBoolean _closed = new AtomicBoolean(false); + /** + * Checks if this is closed, and raises a JMSException if it is. + * + * @throws JMSException If this is closed. + */ protected void checkNotClosed() throws JMSException { if (isClosed()) @@ -42,13 +64,20 @@ public abstract class Closeable } } + /** + * Checks if this is closed. + * + * @return <tt>true</tt> if this is closed, <tt>false</tt> otherwise. + */ public boolean isClosed() { -// synchronized (_closed) - { - return _closed.get(); - } + return _closed.get(); } + /** + * Closes this object. + * + * @throws JMSException If this cannot be closed for any reason. + */ public abstract void close() throws JMSException; } diff --git a/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java b/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java index d1237cff49..0927ca3625 100644 --- a/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java +++ b/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java @@ -18,29 +18,12 @@ * under the License. * */ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ package org.apache.qpid.client; -import javax.jms.JMSException; - import org.apache.qpid.AMQException; +import javax.jms.JMSException; + /** * JMSException does not accept wrapped exceptions in its constructor. Presumably this is because it is a relatively old * Java exception class, before this was added as a default to Throwable. This exception class accepts wrapped exceptions @@ -50,8 +33,6 @@ import org.apache.qpid.AMQException; * <tr><th> Responsibilities <th> Collaborations * <tr><td> Accept wrapped exceptions as a JMSException. * </table> - * - * @author Apache Software Foundation */ public class JMSAMQException extends JMSException { @@ -71,6 +52,11 @@ public class JMSAMQException extends JMSException } } + /** + * @param s The underlying exception. + * + * @deprecated Use the other constructor and write a helpfull message. This one will be deleted. + */ public JMSAMQException(AMQException s) { super(s.getMessage(), String.valueOf(s.getErrorCode())); diff --git a/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java b/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java index a219f7d655..9eb826ba62 100644 --- a/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java +++ b/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java @@ -2,12 +2,12 @@ package org.apache.qpid.client; import javax.jms.Destination; import javax.jms.IllegalStateException; +import javax.jms.InvalidDestinationException; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.QueueSender; -import javax.jms.InvalidDestinationException; public class QueueSenderAdapter implements QueueSender { @@ -25,6 +25,7 @@ public class QueueSenderAdapter implements QueueSender public Queue getQueue() throws JMSException { checkPreConditions(); + return _queue; } @@ -40,15 +41,13 @@ public class QueueSenderAdapter implements QueueSender _delegate.send(queue, msg); } - public void publish(Message msg, int deliveryMode, int priority, long timeToLive) - throws JMSException + public void publish(Message msg, int deliveryMode, int priority, long timeToLive) throws JMSException { checkPreConditions(); _delegate.send(msg, deliveryMode, priority, timeToLive); } - public void send(Queue queue, Message msg, int deliveryMode, int priority, long timeToLive) - throws JMSException + public void send(Queue queue, Message msg, int deliveryMode, int priority, long timeToLive) throws JMSException { checkPreConditions(queue); _delegate.send(queue, msg, deliveryMode, priority, timeToLive); @@ -63,36 +62,42 @@ public class QueueSenderAdapter implements QueueSender public int getDeliveryMode() throws JMSException { checkPreConditions(); + return _delegate.getDeliveryMode(); } public Destination getDestination() throws JMSException { checkPreConditions(); + return _delegate.getDestination(); } public boolean getDisableMessageID() throws JMSException { checkPreConditions(); + return _delegate.getDisableMessageID(); } public boolean getDisableMessageTimestamp() throws JMSException { checkPreConditions(); + return _delegate.getDisableMessageTimestamp(); } public int getPriority() throws JMSException { checkPreConditions(); + return _delegate.getPriority(); } public long getTimeToLive() throws JMSException { checkPreConditions(); + return _delegate.getTimeToLive(); } @@ -102,8 +107,7 @@ public class QueueSenderAdapter implements QueueSender _delegate.send(dest, msg); } - public void send(Message msg, int deliveryMode, int priority, long timeToLive) - throws JMSException + public void send(Message msg, int deliveryMode, int priority, long timeToLive) throws JMSException { checkPreConditions(); _delegate.send(msg, deliveryMode, priority, timeToLive); @@ -159,15 +163,21 @@ public class QueueSenderAdapter implements QueueSender AMQSession session = ((BasicMessageProducer) _delegate).getSession(); - if (session == null || session.isClosed()) + if ((session == null) || session.isClosed()) { throw new javax.jms.IllegalStateException("Invalid Session"); } + if (queue == null) + { + throw new UnsupportedOperationException("Queue is null."); + } + if (!(queue instanceof AMQDestination)) { throw new InvalidDestinationException("Queue: " + queue + " is not a valid Qpid queue"); } + AMQDestination destination = (AMQDestination) queue; if (!destination.isValidated() && checkQueueBeforePublish()) { @@ -185,7 +195,8 @@ public class QueueSenderAdapter implements QueueSender } else { - throw new InvalidDestinationException("Queue: " + queue + " is not a valid destination (no bindings on server"); + throw new InvalidDestinationException("Queue: " + queue + + " is not a valid destination (no bindings on server"); } } } diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverException.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverException.java index 95899d533a..037b0dc2d1 100644 --- a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverException.java +++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverException.java @@ -21,14 +21,26 @@ package org.apache.qpid.client.failover; /** - * This exception is thrown when failover is taking place and otherparts of the client need to know about this. + * FailoverException is used to indicate that a synchronous request has failed to receive the reply that it is waiting + * for because the fail-over process has been started whilst it was waiting for its reply. Synchronous methods generally + * raise this exception to indicate that they must be re-tried once the fail-over process has completed. + * + * <p/><table id="crc"><caption>CRC Card</caption> + * <tr><th> Responsibilities <th> Collaborations + * <tr><td> Used to indicate failure of a synchronous request due to fail-over. + * </table> * * @todo This exception is created and passed as an argument to a method, rather than thrown. The exception is being - * used to represent a signal, passed out to other threads. Use of exceptions as arguments rather than as - * exceptions is extremly confusing. Eliminate. Use a Condition or set a flag and check it instead. Also - * FailoverException is Runtime but handled and should only use Runtimes for non-handleable conditions. + * used to represent an event, passed out to other threads. Use of exceptions as arguments rather than as + * exceptions is extremly confusing. Ideally use a condition or set a flag and check it instead. + * This exceptions-as-events pattern seems to be in a similar style to Mina code, which is not pretty, but + * potentially acceptable for that reason. We have the option of extending the mina model to add more events + * to it, that is, anything that is interested in handling failover as an event occurs below the main + * amq event handler, which knows the specific interface of the qpid handlers, which can pass this down as + * an explicit event, without it being an exception. Add failover method to BlockingMethodFrameListener, + * have it set a flag or interrupt the waiting thread, which then creates and raises this exception. */ -public class FailoverException extends RuntimeException +public class FailoverException extends Exception { public FailoverException(String message) { diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java index 00eac7f2af..8e66aec0d6 100644 --- a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,59 +20,108 @@ */ package org.apache.qpid.client.failover; -import java.util.concurrent.CountDownLatch; - import org.apache.log4j.Logger; + import org.apache.mina.common.IoSession; + import org.apache.qpid.AMQDisconnectedException; import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.client.state.AMQStateManager; +import java.util.concurrent.CountDownLatch; + /** - * When failover is required, we need a separate thread to handle the establishment of the new connection and - * the transfer of subscriptions. - * </p> - * The reason this needs to be a separate thread is because you cannot do this work inside the MINA IO processor - * thread. One significant task is the connection setup which involves a protocol exchange until a particular state - * is achieved. However if you do this in the MINA thread, you have to block until the state is achieved which means - * the IO processor is not able to do anything at all. + * FailoverHandler is a continuation that performs the failover procedure on a protocol session. As described in the + * class level comment for {@link AMQProtocolHandler}, a protocol connection can span many physical transport + * connections, failing over to a new connection if the transport connection fails. The procedure to establish a new + * connection is expressed as a continuation, in order that it may be run in a seperate thread to the i/o thread that + * detected the failure and is used to handle the communication to establish a new connection. + * + * </p>The reason this needs to be a separate thread is because this work cannot be done inside the i/o processor + * thread. The significant task is the connection setup which involves a protocol exchange until a particular state + * is achieved. This procedure waits until the state is achieved which would prevent the i/o thread doing the work + * it needs to do to achieve the new state. + * + * <p/>The failover procedure does the following: + * + * <ol> + * <li>Sets the failing over condition to true.</li> + * <li>Creates a {@link FailoverException} and gets the protocol connection handler to propagate this event to all + * interested parties.</li> + * <li>Takes the failover mutex on the protocol connection handler.</li> + * <li>Abandons the fail over if any of the interested parties vetoes it. The mutex is released and the condition + * reset.</li> + * <li>Creates a new {@link AMQStateManager} and re-established the connection through it.</li> + * <li>Informs the AMQConnection if the connection cannot be re-established.</li> + * <li>Recreates all sessions from the old connection to the new.</li> + * <li>Resets the failing over condition and releases the mutex.</li> + * </ol> + * + * <p/><table id="crc"><caption>CRC Card</caption> + * <tr><th> Responsibilities <th> Collaborations + * <tr><td> Update fail-over state <td> {@link AMQProtocolHandler} + * </table> + * + * @todo The failover latch and mutex are used like a lock and condition. If the retrotranlator supports lock/condition + * then could change over to using them. 1.4 support still needed. + * + * @todo If the condition is set to null on a vetoes fail-over and there are already other threads waiting on the + * condition, they will never be released. It might be an idea to reset the condition in a finally block. + * + * @todo Creates a {@link AMQDisconnectedException} and passes it to the AMQConnection. No need to use an + * exception-as-argument here, could just as easily call a specific method for this purpose on AMQConnection. + * + * @todo Creates a {@link FailoverException} and propagates it to the MethodHandlers. No need to use an + * exception-as-argument here, could just as easily call a specific method for this purpose on + * {@link org.apache.qpid.protocol.AMQMethodListener}. */ public class FailoverHandler implements Runnable { + /** Used for debugging. */ private static final Logger _logger = Logger.getLogger(FailoverHandler.class); + /** Holds the MINA session for the connection that has failed, not the connection that is being failed onto. */ private final IoSession _session; + + /** Holds the protocol handler for the failed connection, upon which the new connection is to be set up. */ private AMQProtocolHandler _amqProtocolHandler; - /** - * Used where forcing the failover host - */ + /** Used to hold the host to fail over to. This is optional and if not set a reconnect to the previous host is tried. */ private String _host; - /** - * Used where forcing the failover port - */ + /** Used to hold the port to fail over to. */ private int _port; + /** + * Creates a failover handler on a protocol session, for a particular MINA session (network connection). + * + * @param amqProtocolHandler The protocol handler that spans the failover. + * @param session The MINA session, for the failing connection. + */ public FailoverHandler(AMQProtocolHandler amqProtocolHandler, IoSession session) { _amqProtocolHandler = amqProtocolHandler; _session = session; } + /** + * Performs the failover procedure. See the class level comment, {@link FailoverHandler}, for a description of the + * failover procedure. + */ public void run() { if (Thread.currentThread().isDaemon()) { throw new IllegalStateException("FailoverHandler must run on a non-daemon thread."); } - //Thread.currentThread().setName("Failover Thread"); + // Create a latch, upon which tasks that must not run in parallel with a failover can wait for completion of + // the fail over. _amqProtocolHandler.setFailoverLatch(new CountDownLatch(1)); // We wake up listeners. If they can handle failover, they will extend the - // FailoverSupport class and will in turn block on the latch until failover - // has completed before retrying the operation + // FailoverRetrySupport class and will in turn block on the latch until failover + // has completed before retrying the operation. _amqProtocolHandler.propagateExceptionToWaiters(new FailoverException("Failing over about to start")); // Since failover impacts several structures we protect them all with a single mutex. These structures @@ -99,8 +148,10 @@ public class FailoverHandler implements Runnable { _amqProtocolHandler.getConnection().exceptionReceived(new AMQDisconnectedException("Failover was vetoed by client", null)); } + _amqProtocolHandler.getFailoverLatch().countDown(); _amqProtocolHandler.setFailoverLatch(null); + return; } @@ -119,6 +170,7 @@ public class FailoverHandler implements Runnable { failoverSucceeded = _amqProtocolHandler.getConnection().attemptReconnection(); } + if (!failoverSucceeded) { _amqProtocolHandler.setStateManager(existingStateManager); @@ -140,6 +192,7 @@ public class FailoverHandler implements Runnable { _logger.info("Client vetoed automatic resubscription"); } + _amqProtocolHandler.getConnection().fireFailoverComplete(); _amqProtocolHandler.setFailoverState(FailoverState.NOT_STARTED); _logger.info("Connection failover completed successfully"); @@ -148,35 +201,36 @@ public class FailoverHandler implements Runnable { _logger.info("Failover process failed - exception being propagated by protocol handler"); _amqProtocolHandler.setFailoverState(FailoverState.FAILED); - try - { - _amqProtocolHandler.exceptionCaught(_session, e); - } + /*try + {*/ + _amqProtocolHandler.exceptionCaught(_session, e); + /*} catch (Exception ex) { _logger.error("Error notifying protocol session of error: " + ex, ex); - } + }*/ } } } - _amqProtocolHandler.getFailoverLatch().countDown(); - } - public String getHost() - { - return _host; + _amqProtocolHandler.getFailoverLatch().countDown(); } + /** + * Sets the host name to fail over to. This is optional and if not set a reconnect to the previous host is tried. + * + * @param host The host name to fail over to. + */ public void setHost(String host) { _host = host; } - public int getPort() - { - return _port; - } - + /** + * Sets the port to fail over to. + * + * @param port The port to fail over to. + */ public void setPort(int port) { _port = port; diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverNoopSupport.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverNoopSupport.java new file mode 100644 index 0000000000..8c05db3232 --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverNoopSupport.java @@ -0,0 +1,54 @@ +package org.apache.qpid.client.failover;
+
+import org.apache.qpid.client.AMQConnection;
+
+/**
+ * FailoverNoopSupport is a {@link FailoverSupport} implementation that does not really provide any failover support
+ * at all. It wraps a {@link FailoverProtectedOperation} but should that operation throw {@link FailoverException} this
+ * support class simply re-raises that exception as an IllegalStateException. This support wrapper should only be
+ * used where the caller can be certain that the failover protected operation cannot acutally throw a failover exception,
+ * for example, because the caller already holds a lock preventing that condition from arising.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Perform a fail-over protected operation raising providing no handling of fail-over conditions.
+ * </table>
+ */
+public class FailoverNoopSupport<T, E extends Exception> implements FailoverSupport<T, E>
+{
+ /** The protected operation that is to be retried in the event of fail-over. */
+ FailoverProtectedOperation<T, E> operation;
+
+ /** The connection on which the fail-over protected operation is to be performed. */
+ AMQConnection connection;
+
+ /**
+ * Creates an automatic retrying fail-over handler for the specified operation.
+ *
+ * @param operation The fail-over protected operation to wrap in this handler.
+ */
+ public FailoverNoopSupport(FailoverProtectedOperation<T, E> operation, AMQConnection con)
+ {
+ this.operation = operation;
+ this.connection = con;
+ }
+
+ /**
+ * Delegates to another continuation which is to be provided with fail-over handling.
+ *
+ * @return The return value from the delegated to continuation.
+ * @throws E Any exception that the delegated to continuation may raise.
+ */
+ public T execute() throws E
+ {
+ try
+ {
+ return operation.execute();
+ }
+ catch (FailoverException e)
+ {
+ throw new IllegalStateException("Fail-over interupted no-op failover support. "
+ + "No-op support should only be used where the caller is certain fail-over cannot occur.", e);
+ }
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverProtectedOperation.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverProtectedOperation.java new file mode 100644 index 0000000000..054add07f7 --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverProtectedOperation.java @@ -0,0 +1,28 @@ +package org.apache.qpid.client.failover;
+
+/**
+ * FailoverProtectedOperation is a continuation for an operation that may throw a {@link FailoverException} because
+ * it has been interrupted by the fail-over process. The {@link FailoverRetrySupport} class defines support wrappers
+ * for failover protected operations, in order to provide different handling schemes when failovers occurr.
+ *
+ * <p/>The type of checked exception that the operation may perform has been generified, in order that fail over
+ * protected operations can be defined that raise arbitrary exceptions. The actuall exception types used should not
+ * be sub-classes of FailoverException, or else catching FailoverException in the {@link FailoverRetrySupport} classes
+ * will mask the exception.
+ *
+ * <p><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities
+ * <tr><td> Perform an operation that may be interrupted by fail-over.
+ * </table>
+ */
+public interface FailoverProtectedOperation<T, E extends Exception>
+{
+ /**
+ * Performs the continuations work.
+ *
+ * @return Provdes scope for the continuation to return an arbitrary value.
+ *
+ * @throws FailoverException If the operation is interrupted by a fail-over notification.
+ */
+ public abstract T execute() throws E, FailoverException;
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java new file mode 100644 index 0000000000..120a07f0fc --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverRetrySupport.java @@ -0,0 +1,128 @@ +/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.client.failover;
+
+import org.apache.qpid.client.AMQConnection;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * FailoverRetrySupport is a continuation that wraps another continuation, delaying its execution until it is notified
+ * that a blocking condition has been met, and executing the continuation within a mutex. If the continuation fails, due
+ * to the original condition being broken, whilst the continuation is waiting for a reponse to a synchronous request,
+ * FailoverRetrySupport automatcally rechecks the condition and re-acquires the mutex and re-runs the continution. This
+ * automatic retrying is continued until the continuation succeeds, or throws an exception (different to
+ * FailoverException, which is used to signal the failure of the original condition).
+ *
+ * <p/>The blocking condition used is that the connection is not currently failing over, and the mutex used is the
+ * connection failover mutex, which guards against the fail-over process being run during fail-over vulnerable methods.
+ * These are used like a lock and condition variable.
+ *
+ * <p/>The wrapped operation may throw a FailoverException, this is an exception that can be raised by a
+ * {@link org.apache.qpid.client.protocol.BlockingMethodFrameListener}, in response to it being notified that a
+ * fail-over wants to start whilst it was waiting. Methods that are vulnerable to fail-over are those that are
+ * synchronous, where a failure will prevent them from getting the reply they are waiting for and asynchronous
+ * methods that should not be attempted when a fail-over is in progress.
+ *
+ * <p/>Wrapping a synchronous method in a FailoverRetrySupport will have the effect that the operation will not be
+ * started during fail-over, but be delayed until any current fail-over has completed. Should a fail-over process want
+ * to start whilst waiting for the synchrnous reply, the FailoverRetrySupport will detect this and rety the operation
+ * until it succeeds. Synchronous methods are usually coordinated with a
+ * {@link org.apache.qpid.client.protocol.BlockingMethodFrameListener} which is notified when a fail-over process wants
+ * to start and throws a FailoverException in response to this.
+ *
+ * <p/>Wrapping an asynchronous method in a FailoverRetrySupport will have the effect that the operation will not be
+ * started during fail-over, but be delayed until any current fail-over has completed.
+ *
+ * <p/><table id="crc"><caption>CRC Card</caption>
+ * <tr><th> Responsibilities <th> Collaborations
+ * <tr><td> Provide a continuation synchronized on a fail-over lock and condition.
+ * <tr><td> Automatically retry the continuation accross fail-overs until it succeeds, or raises an exception.
+ * </table>
+ *
+ * @todo Another continuation. Could use an interface Continuation (as described in other todos, for example, see
+ * {@link org.apache.qpid.pool.Job}). Then have a wrapping continuation (this), which blocks on an arbitrary
+ * Condition or Latch (specified in constructor call), that this blocks on before calling the wrapped Continuation.
+ * Must work on Java 1.4, so check retrotranslator works on Lock/Condition or latch first. Argument and return type
+ * to match wrapped condition as type parameters. Rename to AsyncConditionalContinuation or something like that.
+ *
+ * @todo InterruptedException not handled well.
+ */
+public class FailoverRetrySupport<T, E extends Exception> implements FailoverSupport<T, E>
+{
+ /** Used for debugging. */
+ private static final Logger _log = LoggerFactory.getLogger(FailoverRetrySupport.class);
+
+ /** The protected operation that is to be retried in the event of fail-over. */
+ FailoverProtectedOperation<T, E> operation;
+
+ /** The connection on which the fail-over protected operation is to be performed. */
+ AMQConnection connection;
+
+ /**
+ * Creates an automatic retrying fail-over handler for the specified operation.
+ *
+ * @param operation The fail-over protected operation to wrap in this handler.
+ */
+ public FailoverRetrySupport(FailoverProtectedOperation<T, E> operation, AMQConnection con)
+ {
+ this.operation = operation;
+ this.connection = con;
+ }
+
+ /**
+ * Delays a continuation until the "not failing over" condition is met on the specified connection. Repeats
+ * until the operation throws AMQException or succeeds without being interrupted by fail-over.
+ *
+ * @return The result of executing the continuation.
+ *
+ * @throws E Any underlying exception is allowed to fall through.
+ */
+ public T execute() throws E
+ {
+ while (true)
+ {
+ try
+ {
+ connection.blockUntilNotFailingOver();
+ }
+ catch (InterruptedException e)
+ {
+ _log.debug("Interrupted: " + e, e);
+
+ return null;
+ }
+
+ synchronized (connection.getFailoverMutex())
+ {
+ try
+ {
+ return operation.execute();
+ }
+ catch (FailoverException e)
+ {
+ _log.debug("Failover exception caught during operation: " + e, e);
+ }
+ }
+ }
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverState.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverState.java index e5787439ec..807a5f7d13 100644 --- a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverState.java +++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverState.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -21,27 +21,42 @@ package org.apache.qpid.client.failover; /** - * Enumeration of failover states. Used to handle failover from within AMQProtocolHandler where MINA events need to be - * dealt with and can happen during failover. + * Defines the possible states of the failover process; not started, in progress, failed. + * + * <p/><table id="crc"><caption>CRC Card</caption> + * <tr><th> Responsibilities <th> Collaborations + * <tr><td> Represent a one of the states of the fail-over process. + * </table> */ public final class FailoverState { + /** The string description on this state. */ private final String _state; - /** Failover has not yet been attempted on this connection */ + /** Failover has not yet been attempted on this connection. */ public static final FailoverState NOT_STARTED = new FailoverState("NOT STARTED"); - /** Failover has been requested on this connection but has not completed */ + /** Failover has been requested on this connection but has not completed. */ public static final FailoverState IN_PROGRESS = new FailoverState("IN PROGRESS"); - /** Failover has been attempted and failed */ + /** Failover has been attempted and failed. */ public static final FailoverState FAILED = new FailoverState("FAILED"); + /** + * Creates a type safe enumeration of a fail-over state. + * + * @param state The fail-over state description string. + */ private FailoverState(String state) { _state = state; } + /** + * Prints this state, mainly for debugging purposes. + * + * @return The string description of this state. + */ public String toString() { return "FailoverState: " + _state; diff --git a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverSupport.java b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverSupport.java index a005bc5fdf..478482741c 100644 --- a/java/client/src/main/java/org/apache/qpid/client/failover/FailoverSupport.java +++ b/java/client/src/main/java/org/apache/qpid/client/failover/FailoverSupport.java @@ -1,65 +1,26 @@ -/* +package org.apache.qpid.client.failover; + +/** + * FailoverSupport defines an interface for different types of fail-over handlers, that provide different types of + * behaviour for handling fail-overs during operations that can be interrupted by the fail-over process. For example, + * the support could automatically retry once the fail-over process completes, could prevent an operation from being + * started whilst fail-over is running, or could quietly abandon the operation or raise an exception, and so on. * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. + * <p><table id="crc"><caption>CRC Card</caption> + * <tr><th> Responsibilities + * <tr><td> Perform a fail-over protected operation with handling for fail-over conditions. + * </table> * + * @todo Continuation, extend some sort of re-usable Continuation interface, which might look very like this one. */ -package org.apache.qpid.client.failover; - -import javax.jms.JMSException; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.AMQConnection; - -public abstract class FailoverSupport +public interface FailoverSupport<T, E extends Exception> { - private static final Logger _log = Logger.getLogger(FailoverSupport.class); - - public Object execute(AMQConnection con) throws JMSException - { - // We wait until we are not in the middle of failover before acquiring the mutex and then proceeding. - // Any method that can potentially block for any reason should use this class so that deadlock will not - // occur. The FailoverException is propagated by the AMQProtocolHandler to any listeners (e.g. frame listeners) - // that might be causing a block. When that happens, the exception is caught here and the mutex is released - // before waiting for the failover to complete (either successfully or unsuccessfully). - while (true) - { - try - { - con.blockUntilNotFailingOver(); - } - catch (InterruptedException e) - { - _log.info("Interrupted: " + e, e); - return null; - } - synchronized (con.getFailoverMutex()) - { - try - { - return operation(); - } - catch (FailoverException e) - { - _log.info("Failover exception caught during operation: " + e, e); - } - } - } - } - - protected abstract Object operation() throws JMSException; + /** + * Delegates to another continuation which is to be provided with fail-over handling. + * + * @return The return value from the delegated to continuation. + * + * @throws E Any exception that the delegated to continuation may raise. + */ + public T execute() throws E; } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java index bd8177feb6..8f0ee05b3e 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/BasicCancelOkMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.client.state.AMQStateManager; @@ -28,9 +27,13 @@ import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.framing.BasicCancelOkBody; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class BasicCancelOkMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(BasicCancelOkMethodHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(BasicCancelOkMethodHandler.class); + private static final BasicCancelOkMethodHandler _instance = new BasicCancelOkMethodHandler(); public static BasicCancelOkMethodHandler getInstance() @@ -39,10 +42,10 @@ public class BasicCancelOkMethodHandler implements StateAwareMethodListener } private BasicCancelOkMethodHandler() - { - } + { } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { BasicCancelOkBody body = (BasicCancelOkBody) evt.getMethod(); diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java index d34d6688c1..51120da55c 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/BasicDeliverMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.message.UnprocessedMessage; import org.apache.qpid.client.protocol.AMQProtocolSession; @@ -29,9 +28,12 @@ import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.framing.BasicDeliverBody; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class BasicDeliverMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(BasicDeliverMethodHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(BasicDeliverMethodHandler.class); private static final BasicDeliverMethodHandler _instance = new BasicDeliverMethodHandler(); @@ -40,7 +42,8 @@ public class BasicDeliverMethodHandler implements StateAwareMethodListener return _instance; } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { final UnprocessedMessage msg = new UnprocessedMessage(evt.getChannelId(), (BasicDeliverBody) evt.getMethod()); _logger.debug("New JmsDeliver method received"); diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java index 02573c5d00..0f00c6a26e 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/BasicReturnMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.message.UnprocessedMessage; import org.apache.qpid.client.protocol.AMQProtocolSession; @@ -29,9 +28,12 @@ import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.framing.BasicReturnBody; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class BasicReturnMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(BasicReturnMethodHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(BasicReturnMethodHandler.class); private static final BasicReturnMethodHandler _instance = new BasicReturnMethodHandler(); @@ -40,10 +42,11 @@ public class BasicReturnMethodHandler implements StateAwareMethodListener return _instance; } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { _logger.debug("New JmsBounce method received"); - final UnprocessedMessage msg = new UnprocessedMessage(evt.getChannelId(),(BasicReturnBody)evt.getMethod()); + final UnprocessedMessage msg = new UnprocessedMessage(evt.getChannelId(), (BasicReturnBody) evt.getMethod()); protocolSession.unprocessedMessageReceived(msg); } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java index fbf4d96647..9ed3ef7a60 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQChannelClosedException; import org.apache.qpid.AMQException; import org.apache.qpid.AMQInvalidRoutingKeyException; @@ -36,9 +35,12 @@ import org.apache.qpid.framing.ChannelCloseOkBody; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class ChannelCloseMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(ChannelCloseMethodHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(ChannelCloseMethodHandler.class); private static ChannelCloseMethodHandler _handler = new ChannelCloseMethodHandler(); @@ -47,7 +49,8 @@ public class ChannelCloseMethodHandler implements StateAwareMethodListener return _handler; } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { _logger.debug("ChannelClose method received"); ChannelCloseBody method = (ChannelCloseBody) evt.getMethod(); @@ -68,6 +71,7 @@ public class ChannelCloseMethodHandler implements StateAwareMethodListener { _logger.debug("Channel close received with errorCode " + errorCode + ", and reason " + reason); } + if (errorCode == AMQConstant.NO_CONSUMERS) { throw new AMQNoConsumersException("Error: " + reason, null, null); @@ -94,7 +98,7 @@ public class ChannelCloseMethodHandler implements StateAwareMethodListener } } - //fixme why is this only done when the close is expected... + // fixme why is this only done when the close is expected... // should the above forced closes not also cause a close? protocolSession.channelClosed(evt.getChannelId(), errorCode, String.valueOf(reason)); } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java index 0826deb2f4..e1fe2697e5 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelCloseOkMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,16 +20,18 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.client.state.AMQStateManager; import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class ChannelCloseOkMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(ChannelCloseOkMethodHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(ChannelCloseOkMethodHandler.class); private static final ChannelCloseOkMethodHandler _instance = new ChannelCloseOkMethodHandler(); @@ -38,10 +40,11 @@ public class ChannelCloseOkMethodHandler implements StateAwareMethodListener return _instance; } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { _logger.info("Received channel-close-ok for channel-id " + evt.getChannelId()); - //todo this should do the local closure + // todo this should do the local closure } } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java index 1f003649c0..ca3f46d08b 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/ChannelFlowOkMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.client.state.AMQStateManager; @@ -28,23 +27,26 @@ import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.framing.ChannelFlowOkBody; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class ChannelFlowOkMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(ChannelFlowOkMethodHandler.class); - private static final ChannelFlowOkMethodHandler _instance = new ChannelFlowOkMethodHandler(); + private static final Logger _logger = LoggerFactory.getLogger(ChannelFlowOkMethodHandler.class); + private static final ChannelFlowOkMethodHandler _instance = new ChannelFlowOkMethodHandler(); - public static ChannelFlowOkMethodHandler getInstance() - { - return _instance; - } + public static ChannelFlowOkMethodHandler getInstance() + { + return _instance; + } - private ChannelFlowOkMethodHandler() - { - } + private ChannelFlowOkMethodHandler() + { } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException - { - ChannelFlowOkBody method = (ChannelFlowOkBody) evt.getMethod(); - _logger.debug("Received Channel.Flow-Ok message, active = " + method.active); - } + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException + { + ChannelFlowOkBody method = (ChannelFlowOkBody) evt.getMethod(); + _logger.debug("Received Channel.Flow-Ok message, active = " + method.active); + } } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java index d8153f9c97..752f44237d 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionCloseMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQConnectionClosedException; import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQAuthenticationException; @@ -34,9 +33,12 @@ import org.apache.qpid.framing.ConnectionCloseOkBody; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class ConnectionCloseMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(ConnectionCloseMethodHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(ConnectionCloseMethodHandler.class); private static ConnectionCloseMethodHandler _handler = new ConnectionCloseMethodHandler(); @@ -46,16 +48,16 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener } private ConnectionCloseMethodHandler() - { - } + { } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { _logger.info("ConnectionClose frame received"); ConnectionCloseBody method = (ConnectionCloseBody) evt.getMethod(); // does it matter - //stateManager.changeState(AMQState.CONNECTION_CLOSING); + // stateManager.changeState(AMQState.CONNECTION_CLOSING); AMQConstant errorCode = AMQConstant.getConstant(method.replyCode); AMQShortString reason = method.replyText; @@ -64,7 +66,8 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener { // TODO: check whether channel id of zero is appropriate // Be aware of possible changes to parameter order as versions change. - protocolSession.writeFrame(ConnectionCloseOkBody.createAMQFrame((short) 0, method.getMajor(), method.getMinor())); + protocolSession.writeFrame(ConnectionCloseOkBody.createAMQFrame((short) 0, method.getMajor(), + method.getMinor())); if (errorCode != AMQConstant.REPLY_SUCCESS) { @@ -74,7 +77,7 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener protocolSession.closeProtocolSession(); - //todo this is a bit of a fudge (could be conssidered such as each new connection needs a new state manager or at least a fresh state. + // todo this is a bit of a fudge (could be conssidered such as each new connection needs a new state manager or at least a fresh state. stateManager.changeState(AMQState.CONNECTION_NOT_STARTED); throw new AMQAuthenticationException(errorCode, reason == null ? null : reason.toString(), null); @@ -83,7 +86,6 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener { _logger.info("Connection close received with error code " + errorCode); - throw new AMQConnectionClosedException(errorCode, "Error: " + reason, null); } } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java index 866f65b384..213c0eba6e 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionRedirectMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.client.state.AMQStateManager; @@ -28,9 +27,12 @@ import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.framing.ConnectionRedirectBody; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class ConnectionRedirectMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(ConnectionRedirectMethodHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(ConnectionRedirectMethodHandler.class); private static final int DEFAULT_REDIRECT_PORT = 5672; @@ -42,10 +44,10 @@ public class ConnectionRedirectMethodHandler implements StateAwareMethodListener } private ConnectionRedirectMethodHandler() - { - } + { } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { _logger.info("ConnectionRedirect frame received"); ConnectionRedirectBody method = (ConnectionRedirectBody) evt.getMethod(); @@ -65,6 +67,7 @@ public class ConnectionRedirectMethodHandler implements StateAwareMethodListener host = host.substring(0, portIndex); } + protocolSession.failover(host, port); } } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java index 157128aebc..59b493a6f7 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java @@ -20,16 +20,6 @@ */ package org.apache.qpid.client.handler; -import java.io.UnsupportedEncodingException; -import java.util.HashSet; -import java.util.StringTokenizer; - -import javax.security.sasl.Sasl; -import javax.security.sasl.SaslClient; -import javax.security.sasl.SaslException; - -import org.apache.log4j.Logger; - import org.apache.qpid.AMQException; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.client.security.AMQCallbackHandler; @@ -47,9 +37,20 @@ import org.apache.qpid.framing.FieldTableFactory; import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslClient; +import javax.security.sasl.SaslException; + +import java.io.UnsupportedEncodingException; +import java.util.HashSet; +import java.util.StringTokenizer; + public class ConnectionStartMethodHandler implements StateAwareMethodListener { - private static final Logger _log = Logger.getLogger(ConnectionStartMethodHandler.class); + private static final Logger _log = LoggerFactory.getLogger(ConnectionStartMethodHandler.class); private static final ConnectionStartMethodHandler _instance = new ConnectionStartMethodHandler(); @@ -62,15 +63,14 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener { } public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) - throws AMQException + throws AMQException { _log.debug("public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, " - + "AMQMethodEvent evt): called"); + + "AMQMethodEvent evt): called"); ConnectionStartBody body = (ConnectionStartBody) evt.getMethod(); - ProtocolVersion pv = new ProtocolVersion((byte) body.versionMajor,(byte) body.versionMinor); - + ProtocolVersion pv = new ProtocolVersion((byte) body.versionMajor, (byte) body.versionMinor); // For the purposes of interop, we can make the client accept the broker's version string. // If it does, it then internally records the version as being the latest one that it understands. @@ -110,7 +110,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener { SaslClient sc = Sasl.createSaslClient(new String[] { mechanism }, null, "AMQP", "localhost", null, - createCallbackHandler(mechanism, protocolSession)); + createCallbackHandler(mechanism, protocolSession)); if (sc == null) { throw new AMQException(null, "Client SASL configuration error: no SaslClient could be created for mechanism " + mechanism @@ -148,23 +148,22 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener FieldTable clientProperties = FieldTableFactory.newFieldTable(); clientProperties.setString(new AMQShortString(ClientProperties.instance.toString()), - protocolSession.getClientID()); + protocolSession.getClientID()); clientProperties.setString(new AMQShortString(ClientProperties.product.toString()), - QpidProperties.getProductName()); + QpidProperties.getProductName()); clientProperties.setString(new AMQShortString(ClientProperties.version.toString()), - QpidProperties.getReleaseVersion()); + QpidProperties.getReleaseVersion()); clientProperties.setString(new AMQShortString(ClientProperties.platform.toString()), getFullSystemInfo()); // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0) // TODO: Connect this to the session version obtained from ProtocolInitiation for this session. // Be aware of possible changes to parameter order as versions change. protocolSession.writeFrame(ConnectionStartOkBody.createAMQFrame(evt.getChannelId(), - protocolSession.getProtocolMajorVersion(), - protocolSession.getProtocolMinorVersion(), - clientProperties, // clientProperties - new AMQShortString(selectedLocale), // locale - new AMQShortString(mechanism), // mechanism - saslResponse)); // response + protocolSession.getProtocolMajorVersion(), protocolSession.getProtocolMinorVersion(), + clientProperties, // clientProperties + new AMQShortString(selectedLocale), // locale + new AMQShortString(mechanism), // mechanism + saslResponse)); // response } catch (UnsupportedEncodingException e) @@ -175,13 +174,12 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener else { _log.error("Broker requested Protocol [" + body.versionMajor + "-" + body.versionMinor - + "] which is not supported by this version of the client library"); + + "] which is not supported by this version of the client library"); protocolSession.closeProtocolSession(); } } - private String getFullSystemInfo() { StringBuffer fullSystemInfo = new StringBuffer(); @@ -221,7 +219,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener } private AMQCallbackHandler createCallbackHandler(String mechanism, AMQProtocolSession protocolSession) - throws AMQException + throws AMQException { Class mechanismClass = CallbackHandlerRegistry.getInstance().getCallbackHandlerClass(mechanism); try diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java index 67f1a6519f..68556991d7 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionTuneMethodHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.ConnectionTuneParameters; import org.apache.qpid.client.protocol.AMQProtocolSession; @@ -34,9 +33,12 @@ import org.apache.qpid.framing.ConnectionTuneBody; import org.apache.qpid.framing.ConnectionTuneOkBody; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class ConnectionTuneMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(ConnectionTuneMethodHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(ConnectionTuneMethodHandler.class); private static final ConnectionTuneMethodHandler _instance = new ConnectionTuneMethodHandler(); @@ -46,10 +48,10 @@ public class ConnectionTuneMethodHandler implements StateAwareMethodListener } protected ConnectionTuneMethodHandler() - { - } + { } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { _logger.debug("ConnectionTune frame received"); ConnectionTuneBody frame = (ConnectionTuneBody) evt.getMethod(); @@ -60,38 +62,36 @@ public class ConnectionTuneMethodHandler implements StateAwareMethodListener params = new ConnectionTuneParameters(); } - params.setFrameMax(frame.frameMax); + params.setFrameMax(frame.frameMax); params.setChannelMax(frame.channelMax); params.setHeartbeat(Integer.getInteger("amqj.heartbeat.delay", frame.heartbeat)); protocolSession.setConnectionTuneParameters(params); stateManager.changeState(AMQState.CONNECTION_NOT_OPENED); - protocolSession.writeFrame(createTuneOkFrame(evt.getChannelId(), params,frame.getMajor(), frame.getMinor())); + protocolSession.writeFrame(createTuneOkFrame(evt.getChannelId(), params, frame.getMajor(), frame.getMinor())); String host = protocolSession.getAMQConnection().getVirtualHost(); AMQShortString virtualHost = new AMQShortString("/" + host); - - protocolSession.writeFrame(createConnectionOpenFrame(evt.getChannelId(), virtualHost, null, true,frame.getMajor(), frame.getMinor())); + protocolSession.writeFrame(createConnectionOpenFrame(evt.getChannelId(), virtualHost, null, true, frame.getMajor(), + frame.getMinor())); } - protected AMQFrame createConnectionOpenFrame(int channel, AMQShortString path, AMQShortString capabilities, boolean insist, byte major, byte minor) + protected AMQFrame createConnectionOpenFrame(int channel, AMQShortString path, AMQShortString capabilities, + boolean insist, byte major, byte minor) { // Be aware of possible changes to parameter order as versions change. - return ConnectionOpenBody.createAMQFrame(channel, - major, minor, // AMQP version (major, minor) - capabilities, // capabilities - insist, // insist - path); // virtualHost + return ConnectionOpenBody.createAMQFrame(channel, major, minor, // AMQP version (major, minor) + capabilities, // capabilities + insist, // insist + path); // virtualHost } protected AMQFrame createTuneOkFrame(int channel, ConnectionTuneParameters params, byte major, byte minor) { // Be aware of possible changes to parameter order as versions change. - return ConnectionTuneOkBody.createAMQFrame(channel, - major, minor, - params.getChannelMax(), // channelMax - params.getFrameMax(), // frameMax - params.getHeartbeat()); // heartbeat + return ConnectionTuneOkBody.createAMQFrame(channel, major, minor, params.getChannelMax(), // channelMax + params.getFrameMax(), // frameMax + params.getHeartbeat()); // heartbeat } } diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java index 146c705c00..8f9a84a3a6 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java @@ -17,7 +17,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.client.state.AMQStateManager; @@ -25,32 +24,33 @@ import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.framing.ExchangeBoundOkBody; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author Apache Software Foundation */ public class ExchangeBoundOkMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(ExchangeBoundOkMethodHandler.class); - private static final ExchangeBoundOkMethodHandler _instance = new ExchangeBoundOkMethodHandler(); + private static final Logger _logger = LoggerFactory.getLogger(ExchangeBoundOkMethodHandler.class); + private static final ExchangeBoundOkMethodHandler _instance = new ExchangeBoundOkMethodHandler(); - public static ExchangeBoundOkMethodHandler getInstance() - { - return _instance; - } + public static ExchangeBoundOkMethodHandler getInstance() + { + return _instance; + } - private ExchangeBoundOkMethodHandler() - { - } + private ExchangeBoundOkMethodHandler() + { } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException - { - if (_logger.isDebugEnabled()) - { + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException + { + if (_logger.isDebugEnabled()) + { ExchangeBoundOkBody body = (ExchangeBoundOkBody) evt.getMethod(); - _logger.debug("Received Exchange.Bound-Ok message, response code: " + body.replyCode + " text: " + - body.replyText); - } - } + _logger.debug("Received Exchange.Bound-Ok message, response code: " + body.replyCode + " text: " + + body.replyText); + } + } } - - diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java index eaf4721445..81228b4cdc 100644 --- a/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java @@ -17,7 +17,6 @@ */ package org.apache.qpid.client.handler; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.client.state.AMQStateManager; @@ -25,31 +24,32 @@ import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.framing.QueueDeleteOkBody; import org.apache.qpid.protocol.AMQMethodEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author Apache Software Foundation */ public class QueueDeleteOkMethodHandler implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(QueueDeleteOkMethodHandler.class); - private static final QueueDeleteOkMethodHandler _instance = new QueueDeleteOkMethodHandler(); + private static final Logger _logger = LoggerFactory.getLogger(QueueDeleteOkMethodHandler.class); + private static final QueueDeleteOkMethodHandler _instance = new QueueDeleteOkMethodHandler(); - public static QueueDeleteOkMethodHandler getInstance() - { - return _instance; - } + public static QueueDeleteOkMethodHandler getInstance() + { + return _instance; + } - private QueueDeleteOkMethodHandler() - { - } + private QueueDeleteOkMethodHandler() + { } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException - { - if (_logger.isDebugEnabled()) - { + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException + { + if (_logger.isDebugEnabled()) + { QueueDeleteOkBody body = (QueueDeleteOkBody) evt.getMethod(); _logger.debug("Received Queue.Delete-Ok message, message count: " + body.messageCount); - } - } + } + } } - - 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 13f544516a..2dfeb19268 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java @@ -20,18 +20,10 @@ */ package org.apache.qpid.client.message; -import java.util.Collections; -import java.util.Enumeration; -import java.util.Map; -import java.util.UUID; - -import javax.jms.Destination; -import javax.jms.JMSException; -import javax.jms.MessageNotReadableException; -import javax.jms.MessageNotWriteableException; - import org.apache.commons.collections.map.ReferenceMap; + import org.apache.mina.common.ByteBuffer; + import org.apache.qpid.AMQException; import org.apache.qpid.client.*; import org.apache.qpid.framing.AMQShortString; @@ -41,6 +33,16 @@ import org.apache.qpid.url.AMQBindingURL; import org.apache.qpid.url.BindingURL; import org.apache.qpid.url.URLSyntaxException; +import javax.jms.Destination; +import javax.jms.JMSException; +import javax.jms.MessageNotReadableException; +import javax.jms.MessageNotWriteableException; + +import java.util.Collections; +import java.util.Enumeration; +import java.util.Map; +import java.util.UUID; + public abstract class AbstractJMSMessage extends AMQMessage implements org.apache.qpid.jms.Message { private static final Map _destinationCache = Collections.synchronizedMap(new ReferenceMap()); @@ -70,35 +72,32 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach _changedData = (data == null); _headerAdapter = new JMSHeaderAdapter(((BasicContentHeaderProperties) _contentHeaderProperties).getHeaders()); - _strictAMQP = Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP, AMQSession.STRICT_AMQP_DEFAULT)); + _strictAMQP = + Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP, AMQSession.STRICT_AMQP_DEFAULT)); } protected AbstractJMSMessage(long deliveryTag, BasicContentHeaderProperties contentHeader, AMQShortString exchange, - AMQShortString routingKey, ByteBuffer data) throws AMQException + AMQShortString routingKey, ByteBuffer data) throws AMQException { this(contentHeader, deliveryTag); Integer type = contentHeader.getHeaders().getInteger(CustomJMSXProperty.JMS_QPID_DESTTYPE.getShortStringName()); - int contentType = (type == null) ? AMQDestination.UNKNOWN_TYPE : type.intValue(); AMQDestination dest; - switch (contentType) + if (AMQDestination.QUEUE_TYPE.equals(type)) { - - case AMQDestination.QUEUE_TYPE: - dest = new AMQQueue(exchange, routingKey, routingKey); - break; - - case AMQDestination.TOPIC_TYPE: - dest = new AMQTopic(exchange, routingKey, null); - break; - - default: - dest = new AMQUndefinedDestination(exchange, routingKey, null); - break; + dest = new AMQQueue(exchange, routingKey, routingKey); + } + else if (AMQDestination.TOPIC_TYPE.equals(type)) + { + dest = new AMQTopic(exchange, routingKey, null); } - //Destination dest = AMQDestination.createDestination(url); + else + { + dest = new AMQUndefinedDestination(exchange, routingKey, null); + } + // Destination dest = AMQDestination.createDestination(url); setJMSDestination(dest); _data = data; @@ -202,7 +201,7 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach if (!(destination instanceof AMQDestination)) { throw new IllegalArgumentException( - "ReplyTo destination may only be an AMQDestination - passed argument was type " + destination.getClass()); + "ReplyTo destination may only be an AMQDestination - passed argument was type " + destination.getClass()); } final AMQDestination amqd = (AMQDestination) destination; @@ -614,7 +613,6 @@ public abstract class AbstractJMSMessage extends AMQMessage implements org.apach getContentHeaderProperties().setHeaders(messageProperties); } - public JMSHeaderAdapter getJmsHeaders() { return _headerAdapter; 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 5deaec4c17..87df7e1337 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 @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,51 +20,53 @@ */ package org.apache.qpid.client.message; -import java.util.Iterator; -import java.util.List; - -import javax.jms.JMSException; - -import org.apache.log4j.Logger; import org.apache.mina.common.ByteBuffer; + import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentBody; import org.apache.qpid.framing.ContentHeaderBody; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; + +import java.util.Iterator; +import java.util.List; + public abstract class AbstractJMSMessageFactory implements MessageFactory { - private static final Logger _logger = Logger.getLogger(AbstractJMSMessageFactory.class); - + private static final Logger _logger = LoggerFactory.getLogger(AbstractJMSMessageFactory.class); - protected abstract AbstractJMSMessage createMessage(long messageNbr, ByteBuffer data, - AMQShortString exchange, AMQShortString routingKey, - ContentHeaderBody contentHeader) throws AMQException; + protected abstract AbstractJMSMessage createMessage(long messageNbr, ByteBuffer data, AMQShortString exchange, + AMQShortString routingKey, ContentHeaderBody contentHeader) throws AMQException; - protected AbstractJMSMessage createMessageWithBody(long messageNbr, - ContentHeaderBody contentHeader, - AMQShortString exchange, AMQShortString routingKey, - List bodies) throws AMQException + protected AbstractJMSMessage createMessageWithBody(long messageNbr, ContentHeaderBody contentHeader, + AMQShortString exchange, AMQShortString routingKey, List bodies) throws AMQException { ByteBuffer data; final boolean debug = _logger.isDebugEnabled(); // we optimise the non-fragmented case to avoid copying - if (bodies != null && bodies.size() == 1) + if ((bodies != null) && (bodies.size() == 1)) { - if(debug) + if (debug) { - _logger.debug("Non-fragmented message body (bodySize=" + contentHeader.bodySize +")"); + _logger.debug("Non-fragmented message body (bodySize=" + contentHeader.bodySize + ")"); } - data = ((ContentBody)bodies.get(0)).payload; + + data = ((ContentBody) bodies.get(0)).payload; } else if (bodies != null) { - if(debug) + if (debug) { - _logger.debug("Fragmented message body (" + bodies.size() + " frames, bodySize=" + contentHeader.bodySize + ")"); + _logger.debug("Fragmented message body (" + bodies.size() + " frames, bodySize=" + contentHeader.bodySize + + ")"); } - data = ByteBuffer.allocate((int)contentHeader.bodySize); // XXX: Is cast a problem? + + data = ByteBuffer.allocate((int) contentHeader.bodySize); // XXX: Is cast a problem? final Iterator it = bodies.iterator(); while (it.hasNext()) { @@ -72,27 +74,29 @@ public abstract class AbstractJMSMessageFactory implements MessageFactory data.put(cb.payload); cb.payload.release(); } + data.flip(); } else // bodies == null { data = ByteBuffer.allocate(0); } - if(debug) + + if (debug) { - _logger.debug("Creating message from buffer with position=" + data.position() + " and remaining=" + data.remaining()); + _logger.debug("Creating message from buffer with position=" + data.position() + " and remaining=" + + data.remaining()); } return createMessage(messageNbr, data, exchange, routingKey, contentHeader); } - public AbstractJMSMessage createMessage(long messageNbr, boolean redelivered, - ContentHeaderBody contentHeader, - AMQShortString exchange, AMQShortString routingKey, - List bodies) throws JMSException, AMQException + public AbstractJMSMessage createMessage(long messageNbr, boolean redelivered, ContentHeaderBody contentHeader, + AMQShortString exchange, AMQShortString routingKey, List bodies) throws JMSException, AMQException { final AbstractJMSMessage msg = createMessageWithBody(messageNbr, contentHeader, exchange, routingKey, bodies); msg.setJMSRedelivered(redelivered); + return msg; } diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java index ae64ac987e..495f09e8fd 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java @@ -14,36 +14,38 @@ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations - * under the License. + * under the License. + * * - * */ package org.apache.qpid.client.message; +import org.apache.mina.common.ByteBuffer; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ContentHeaderBody; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.jms.MessageFormatException; + import java.nio.charset.CharacterCodingException; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; -import javax.jms.JMSException; -import javax.jms.MessageFormatException; - -import org.apache.log4j.Logger; -import org.apache.mina.common.ByteBuffer; -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ContentHeaderBody; - public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jms.MapMessage { - private static final Logger _logger = Logger.getLogger(JMSMapMessage.class); - + private static final Logger _logger = LoggerFactory.getLogger(JMSMapMessage.class); public static final String MIME_TYPE = "jms/map-message"; private static final AMQShortString MIME_TYPE_SHORT_STRING = new AMQShortString(MIME_TYPE); - private Map<String,Object> _map = new HashMap<String, Object>(); + private Map<String, Object> _map = new HashMap<String, Object>(); public JMSMapMessage() throws JMSException { @@ -56,24 +58,22 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm populateMapFromData(); } - - JMSMapMessage(long messageNbr, ContentHeaderBody contentHeader, AMQShortString exchange, - AMQShortString routingKey, ByteBuffer data) throws AMQException + JMSMapMessage(long messageNbr, ContentHeaderBody contentHeader, AMQShortString exchange, AMQShortString routingKey, + ByteBuffer data) throws AMQException { super(messageNbr, contentHeader, exchange, routingKey, data); try { populateMapFromData(); - } + } catch (JMSException je) { throw new AMQException(null, "Error populating MapMessage from ByteBuffer", je); - + } } - public String toBodyString() throws JMSException { return _map.toString(); @@ -84,16 +84,14 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm return MIME_TYPE_SHORT_STRING; } - public ByteBuffer getData() { - //What if _data is null? + // What if _data is null? writeMapToData(); + return super.getData(); } - - @Override public void clearBodyImpl() throws JMSException { @@ -105,18 +103,18 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm { Object value = _map.get(propName); - if(value instanceof Boolean) + if (value instanceof Boolean) { - return ((Boolean)value).booleanValue(); + return ((Boolean) value).booleanValue(); } - else if((value instanceof String) || (value == null)) + else if ((value instanceof String) || (value == null)) { - return Boolean.valueOf((String)value); + return Boolean.valueOf((String) value); } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to boolean."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to boolean."); } } @@ -125,18 +123,18 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm { Object value = _map.get(propName); - if(value instanceof Byte) + if (value instanceof Byte) { - return ((Byte)value).byteValue(); + return ((Byte) value).byteValue(); } - else if((value instanceof String) || (value==null)) + else if ((value instanceof String) || (value == null)) { - return Byte.valueOf((String)value).byteValue(); + return Byte.valueOf((String) value).byteValue(); } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to byte."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to byte."); } } @@ -144,51 +142,50 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm { Object value = _map.get(propName); - if(value instanceof Short) + if (value instanceof Short) { - return ((Short)value).shortValue(); + return ((Short) value).shortValue(); } - else if(value instanceof Byte) + else if (value instanceof Byte) { - return ((Byte)value).shortValue(); + return ((Byte) value).shortValue(); } - else if((value instanceof String) || (value==null)) + else if ((value instanceof String) || (value == null)) { - return Short.valueOf((String)value).shortValue(); + return Short.valueOf((String) value).shortValue(); } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to short."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to short."); } } - public int getInt(String propName) throws JMSException { Object value = _map.get(propName); - if(value instanceof Integer) + if (value instanceof Integer) { - return ((Integer)value).intValue(); + return ((Integer) value).intValue(); } - else if(value instanceof Short) + else if (value instanceof Short) { - return ((Short)value).intValue(); + return ((Short) value).intValue(); } - else if(value instanceof Byte) + else if (value instanceof Byte) { - return ((Byte)value).intValue(); + return ((Byte) value).intValue(); } - else if((value instanceof String) || (value==null)) + else if ((value instanceof String) || (value == null)) { - return Integer.valueOf((String)value).intValue(); + return Integer.valueOf((String) value).intValue(); } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to int."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to int."); } } @@ -197,30 +194,32 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm { Object value = _map.get(propName); - if(value instanceof Long) + if (value instanceof Long) { - return ((Long)value).longValue(); + return ((Long) value).longValue(); } - else if(value instanceof Integer) + else if (value instanceof Integer) { - return ((Integer)value).longValue(); + return ((Integer) value).longValue(); } - if(value instanceof Short) + + if (value instanceof Short) { - return ((Short)value).longValue(); + return ((Short) value).longValue(); } - if(value instanceof Byte) + + if (value instanceof Byte) { - return ((Byte)value).longValue(); + return ((Byte) value).longValue(); } - else if((value instanceof String) || (value==null)) + else if ((value instanceof String) || (value == null)) { - return Long.valueOf((String)value).longValue(); + return Long.valueOf((String) value).longValue(); } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to long."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to long."); } } @@ -229,45 +228,43 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm { Object value = _map.get(propName); - if(!_map.containsKey(propName)) + if (!_map.containsKey(propName)) { throw new MessageFormatException("Property " + propName + " not present"); } - else if(value instanceof Character) + else if (value instanceof Character) { - return ((Character)value).charValue(); + return ((Character) value).charValue(); } else if (value == null) { - throw new NullPointerException("Property " + propName + " has null value and therefore cannot " + - "be converted to char."); + throw new NullPointerException("Property " + propName + " has null value and therefore cannot " + + "be converted to char."); } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to boolan."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to boolan."); } } - - public float getFloat(String propName) throws JMSException { Object value = _map.get(propName); - if(value instanceof Float) + if (value instanceof Float) { - return ((Float)value).floatValue(); + return ((Float) value).floatValue(); } - else if((value instanceof String) || (value==null)) + else if ((value instanceof String) || (value == null)) { - return Float.valueOf((String)value).floatValue(); + return Float.valueOf((String) value).floatValue(); } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to float."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to float."); } } @@ -275,22 +272,22 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm { Object value = _map.get(propName); - if(value instanceof Double) + if (value instanceof Double) { - return ((Double)value).doubleValue(); + return ((Double) value).doubleValue(); } - else if(value instanceof Float) + else if (value instanceof Float) { - return ((Float)value).doubleValue(); + return ((Float) value).doubleValue(); } - else if((value instanceof String) || (value==null)) + else if ((value instanceof String) || (value == null)) { - return Double.valueOf((String)value).doubleValue(); + return Double.valueOf((String) value).doubleValue(); } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to double."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to double."); } } @@ -298,14 +295,13 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm { Object value = _map.get(propName); - if((value instanceof String) || (value == null)) + if ((value instanceof String) || (value == null)) { return (String) value; } - else if(value instanceof byte[]) + else if (value instanceof byte[]) { - throw new MessageFormatException("Property " + propName + " of type byte[] " + - "cannot be converted to String."); + throw new MessageFormatException("Property " + propName + " of type byte[] " + "cannot be converted to String."); } else { @@ -318,18 +314,18 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm { Object value = _map.get(propName); - if(!_map.containsKey(propName)) + if (!_map.containsKey(propName)) { - throw new MessageFormatException("Property " + propName + " not present"); + throw new MessageFormatException("Property " + propName + " not present"); } - else if((value instanceof byte[]) || (value == null)) + else if ((value instanceof byte[]) || (value == null)) { - return (byte[])value; + return (byte[]) value; } else { - throw new MessageFormatException("Property " + propName + " of type " + - value.getClass().getName() + " cannot be converted to byte[]."); + throw new MessageFormatException("Property " + propName + " of type " + value.getClass().getName() + + " cannot be converted to byte[]."); } } @@ -343,7 +339,6 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm return Collections.enumeration(_map.keySet()); } - public void setBoolean(String propName, boolean b) throws JMSException { checkWritable(); @@ -416,46 +411,38 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm public void setBytes(String propName, byte[] bytes, int offset, int length) throws JMSException { - if((offset == 0) && (length == bytes.length)) + if ((offset == 0) && (length == bytes.length)) { - setBytes(propName,bytes); + setBytes(propName, bytes); } else { byte[] newBytes = new byte[length]; - System.arraycopy(bytes,offset,newBytes,0,length); - setBytes(propName,newBytes); + System.arraycopy(bytes, offset, newBytes, 0, length); + setBytes(propName, newBytes); } } public void setObject(String propName, Object value) throws JMSException - { + { checkWritable(); checkPropertyName(propName); - 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) + 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(propName, value); } else { - throw new MessageFormatException("Cannot set property " + propName + " to value " + value + - "of type " + value.getClass().getName() + "."); + throw new MessageFormatException("Cannot set property " + propName + " to value " + value + "of type " + + value.getClass().getName() + "."); } } private void checkPropertyName(String propName) { - if(propName == null || propName.equals("")) + if ((propName == null) || propName.equals("")) { throw new IllegalArgumentException("Property name cannot be null, or the empty String."); } @@ -466,19 +453,18 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm return _map.containsKey(propName); } - private void populateMapFromData() throws JMSException { - if(_data != null) + if (_data != null) { _data.rewind(); final int entries = readIntImpl(); - for(int i = 0; i < entries; i++) + for (int i = 0; i < entries; i++) { String propName = readStringImpl(); Object value = readObject(); - _map.put(propName,value); + _map.put(propName, value); } } else @@ -492,7 +478,7 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm allocateInitialBuffer(); final int size = _map.size(); writeIntImpl(size); - for(Map.Entry<String, Object> entry : _map.entrySet()) + for (Map.Entry<String, Object> entry : _map.entrySet()) { try { @@ -500,10 +486,10 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm } catch (CharacterCodingException e) { - throw new IllegalArgumentException("Cannot encode property key name " + entry.getKey(),e); - + throw new IllegalArgumentException("Cannot encode property key name " + entry.getKey(), e); } + try { writeObject(entry.getValue()); @@ -511,14 +497,11 @@ public class JMSMapMessage extends AbstractBytesTypedMessage implements javax.jm catch (JMSException e) { Object value = entry.getValue(); - throw new IllegalArgumentException("Cannot encode property key name " + entry.getKey() + - " value : " + value + " (type: " + value.getClass().getName() + ").",e); + throw new IllegalArgumentException("Cannot encode property key name " + entry.getKey() + " value : " + value + + " (type: " + value.getClass().getName() + ").", e); } } } - - - } diff --git a/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java b/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java index 0afc8177fc..f6b11c6f6c 100644 --- a/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java +++ b/java/client/src/main/java/org/apache/qpid/client/message/MessageConverter.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,7 +20,8 @@ */ package org.apache.qpid.client.message; -import java.util.Enumeration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.BytesMessage; import javax.jms.JMSException; @@ -31,7 +32,7 @@ import javax.jms.ObjectMessage; import javax.jms.StreamMessage; import javax.jms.TextMessage; -import org.apache.log4j.Logger; +import java.util.Enumeration; public class MessageConverter { @@ -39,7 +40,7 @@ public class MessageConverter /** * Log4J logger */ - protected final Logger _logger = Logger.getLogger(getClass()); + protected final Logger _logger = LoggerFactory.getLogger(getClass()); /** * AbstractJMSMessage which will hold the converted message @@ -81,6 +82,7 @@ public class MessageConverter String name = (String) mapNames.nextElement(); nativeMessage.setObject(name, message.getObject(name)); } + _newMessage = (AbstractJMSMessage) nativeMessage; setMessageProperties(message); } @@ -121,15 +123,16 @@ public class MessageConverter } catch (MessageEOFException e) { - //we're at the end so don't mind the exception + // we're at the end so don't mind the exception } + _newMessage = (AbstractJMSMessage) nativeMessage; setMessageProperties(message); } public MessageConverter(Message message) throws JMSException { - //Send a message with just properties. + // Send a message with just properties. // Throwing away content BytesMessage nativeMessage = new JMSBytesMessage(); @@ -160,7 +163,7 @@ public class MessageConverter while (propertyNames.hasMoreElements()) { String propertyName = String.valueOf(propertyNames.nextElement()); - //TODO: Shouldn't need to check for JMS properties here as don't think getPropertyNames() should return them + // TODO: Shouldn't need to check for JMS properties here as don't think getPropertyNames() should return them if (!propertyName.startsWith("JMSX_")) { Object value = message.getObjectProperty(propertyName); @@ -190,6 +193,7 @@ public class MessageConverter { _newMessage.setJMSReplyTo(message.getJMSReplyTo()); } + _newMessage.setJMSType(message.getJMSType()); _newMessage.setJMSCorrelationID(message.getJMSCorrelationID()); diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java index 5687ad2658..d2d29039ea 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolHandler.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,10 +20,6 @@ */ package org.apache.qpid.client.protocol; -import java.util.Iterator; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.CountDownLatch; - import org.apache.log4j.Logger; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoHandlerAdapter; @@ -34,10 +30,10 @@ import org.apache.qpid.AMQConnectionClosedException; import org.apache.qpid.AMQDisconnectedException; import org.apache.qpid.AMQException; import org.apache.qpid.AMQTimeoutException; -import org.apache.qpid.AMQChannelClosedException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.SSLConfiguration; +import org.apache.qpid.client.failover.FailoverException; import org.apache.qpid.client.failover.FailoverHandler; import org.apache.qpid.client.failover.FailoverState; import org.apache.qpid.client.state.AMQState; @@ -60,9 +56,67 @@ import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; import org.apache.qpid.ssl.SSLContextFactory; +import java.util.Iterator; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.CountDownLatch; +/** + * AMQProtocolHandler is the client side protocol handler for AMQP, it handles all protocol events received from the + * network by MINA. The primary purpose of AMQProtocolHandler is to translate the generic event model of MINA into the + * specific event model of AMQP, by revealing the type of the received events (from decoded data), and passing the event + * on to more specific handlers for the type. In this sense, it channels the richer event model of AMQP, expressed in + * terms of methods and so on, through the cruder, general purpose event model of MINA, expressed in terms of "message + * received" and so on. + * + * <p/>There is a 1:1 mapping between an AMQProtocolHandler and an {@link AMQConnection}. The connection class is + * exposed to the end user of the AMQP client API, and also implements the JMS Connection API, so provides the public + * API calls through which an individual connection can be manipulated. This protocol handler talks to the network + * through MINA, in a behind the scenes role; it is not an exposed part of the client API. + * + * <p/>There is a 1:many mapping between an AMQProtocolHandler and a set of {@link AMQSession}s. At the MINA level, + * there is one session per connection. At the AMQP level there can be many channels which are also called sessions in + * JMS parlance. The {@link AMQSession}s are managed through an {@link AMQProtocolSession} instance. The protocol + * session is similar to the MINA per-connection session, except that it can span the lifecycle of multiple MINA + * sessions in the event of failover. See below for more information about this. + * + * <p/>Mina provides a session container that can be used to store/retrieve arbitrary objects as String named + * attributes. A more convenient, type-safe, container for session data is provided in the form of {@link + * AMQProtocolSession}. + * + * <p/>A common way to use MINA is to have a single instance of the event handler, and for MINA to pass in its session + * object with every event, and for per-connection data to be held in the MINA session (perhaps using a type-safe + * wrapper as described above). This event handler is different, because dealing with failover complicates things. To + * the end client of an AMQConnection, a failed over connection is still handled through the same connection instance, + * but behind the scenes a new transport connection, and MINA session will have been created. The MINA session object + * cannot be used to track the state of the fail-over process, because it is destroyed and a new one is created, as the + * old connection is shutdown and a new one created. For this reason, an AMQProtocolHandler is created per AMQConnection + * and the protocol session data is held outside of the MINA IOSession. + * + * <p/>This handler is responsibile for setting up the filter chain to filter all events for this handler through. The + * filter chain is set up as a stack of event handers that perform the following functions (working upwards from the + * network traffic at the bottom), handing off incoming events to an asynchronous thread pool to do the work, optionally + * handling secure sockets encoding/decoding, encoding/decoding the AMQP format itself. + * + * <p/><table id="crc"><caption>CRC Card</caption> <tr><th> Responsibilities <th> Collaborations <tr><td> Create the + * filter chain to filter this handlers events. <td> {@link ProtocolCodecFilter}, {@link SSLContextFactory}, {@link + * SSLFilter}, {@link ReadWriteThreadModel}. + * + * <tr><td> Maintain fail-over state. <tr><td> </table> + * + * @todo Explain the system property: amqj.shared_read_write_pool. How does putting the protocol codec filter before the + * async write filter make it a shared pool? The pooling filter uses the same thread pool for reading and writing + * anyway, see {@link org.apache.qpid.pool.PoolingFilter}, docs for comments. Will putting the protocol codec filter + * before it mean not doing the read/write asynchronously but in the main filter thread? + * @todo Use a single handler instance, by shifting everything to do with the 'protocol session' state, including + * failover state, into AMQProtocolSession, and tracking that from AMQConnection? The lifecycles of AMQProtocolSesssion + * and AMQConnection will be the same, so if there is high cohesion between them, they could be merged, although there + * is sense in keeping the session model seperate. Will clarify things by having data held per protocol handler, per + * protocol session, per network connection, per channel, in seperate classes, so that lifecycles of the fields match + * lifecycles of their containing objects. + */ public class AMQProtocolHandler extends IoHandlerAdapter { + /** Used for debugging. */ private static final Logger _logger = Logger.getLogger(AMQProtocolHandler.class); /** @@ -74,8 +128,10 @@ public class AMQProtocolHandler extends IoHandlerAdapter /** Our wrapper for a protocol session that provides access to session values in a typesafe manner. */ private volatile AMQProtocolSession _protocolSession; + /** Holds the state of the protocol session. */ private AMQStateManager _stateManager = new AMQStateManager(); + /** Holds the method listeners, */ private final CopyOnWriteArraySet _frameListeners = new CopyOnWriteArraySet(); /** @@ -91,15 +147,31 @@ public class AMQProtocolHandler extends IoHandlerAdapter */ private FailoverState _failoverState = FailoverState.NOT_STARTED; + /** Used to provide a condition to wait upon for operations that are required to wait for failover to complete. */ private CountDownLatch _failoverLatch; + /** Defines the default timeout to use for synchronous protocol commands. */ private final long DEFAULT_SYNC_TIMEOUT = 1000 * 30; + /** + * Creates a new protocol handler, associated with the specified client connection instance. + * + * @param con The client connection that this is the event handler for. + */ public AMQProtocolHandler(AMQConnection con) { _connection = con; } + /** + * Invoked by MINA when a MINA session for a new connection is created. This method sets up the filter chain on the + * session, which filters the events handled by this handler. The filter chain consists of, handing off events to an + * asynchronous thread pool, optionally encoding/decoding ssl, encoding/decoding AMQP. + * + * @param session The MINA session. + * + * @throws Exception Any underlying exceptions are allowed to fall through to MINA. + */ public void sessionCreated(IoSession session) throws Exception { _logger.debug("Protocol session created for session " + System.identityHashCode(session)); @@ -119,16 +191,15 @@ public class AMQProtocolHandler extends IoHandlerAdapter if (_connection.getSSLConfiguration() != null) { SSLConfiguration sslConfig = _connection.getSSLConfiguration(); - SSLContextFactory sslFactory = new SSLContextFactory(sslConfig.getKeystorePath(), sslConfig.getKeystorePassword(), sslConfig.getCertType()); + SSLContextFactory sslFactory = + new SSLContextFactory(sslConfig.getKeystorePath(), sslConfig.getKeystorePassword(), sslConfig.getCertType()); SSLFilter sslFilter = new SSLFilter(sslFactory.buildClientContext()); sslFilter.setUseClientMode(true); session.getFilterChain().addBefore("protocolFilter", "ssl", sslFilter); } - try { - ReadWriteThreadModel threadModel = ReadWriteThreadModel.getInstance(); threadModel.getAsynchronousReadFilter().createNewJobForSession(session); threadModel.getAsynchronousWriteFilter().createNewJobForSession(session); @@ -142,35 +213,38 @@ public class AMQProtocolHandler extends IoHandlerAdapter _protocolSession.init(); } - public void sessionOpened(IoSession session) throws Exception - { - //System.setProperty("foo", "bar"); - } - /** - * When the broker connection dies we can either get sessionClosed() called or exceptionCaught() followed by - * sessionClosed() depending on whether we were trying to send data at the time of failure. + * Called when the network connection is closed. This can happen, either because the client explicitly requested + * that the connection be closed, in which case nothing is done, or because the connection died. In the case where + * the connection died, an attempt to failover automatically to a new connection may be started. The failover + * process will be started, provided that it is the clients policy to allow failover, and provided that a failover + * has not already been started or failed. + * + * <p/>It is important to note that when the connection dies this method may be called or {@link #exceptionCaught} + * may be called first followed by this method. This depends on whether the client was trying to send data at the + * time of the failure. * - * @param session + * @param session The MINA session. * - * @throws Exception + * @todo Clarify: presumably exceptionCaught is called when the client is sending during a connection failure and + * not otherwise? The above comment doesn't make that clear. */ - public void sessionClosed(IoSession session) throws Exception + public void sessionClosed(IoSession session) { if (_connection.isClosed()) { - _logger.info("Session closed called by client"); + _logger.debug("Session closed called by client"); } else { - _logger.info("Session closed called with failover state currently " + _failoverState); + _logger.debug("Session closed called with failover state currently " + _failoverState); - //reconnetablility was introduced here so as not to disturb the client as they have made their intentions + // reconnetablility was introduced here so as not to disturb the client as they have made their intentions // known through the policy settings. if ((_failoverState != FailoverState.IN_PROGRESS) && _connection.failoverAllowed()) { - _logger.info("FAILOVER STARTING"); + _logger.debug("FAILOVER STARTING"); if (_failoverState == FailoverState.NOT_STARTED) { _failoverState = FailoverState.IN_PROGRESS; @@ -178,12 +252,12 @@ public class AMQProtocolHandler extends IoHandlerAdapter } else { - _logger.info("Not starting failover as state currently " + _failoverState); + _logger.debug("Not starting failover as state currently " + _failoverState); } } else { - _logger.info("Failover not allowed by policy."); + _logger.debug("Failover not allowed by policy."); // or already in progress? if (_logger.isDebugEnabled()) { @@ -199,12 +273,12 @@ public class AMQProtocolHandler extends IoHandlerAdapter } else { - _logger.info("sessionClose() failover in progress"); + _logger.debug("sessionClose() failover in progress"); } } } - _logger.info("Protocol Session [" + this + "] closed"); + _logger.debug("Protocol Session [" + this + "] closed"); } /** See {@link FailoverHandler} to see rationale for separate thread. */ @@ -223,25 +297,32 @@ public class AMQProtocolHandler extends IoHandlerAdapter _logger.debug("Protocol Session [" + this + ":" + session + "] idle: " + status); if (IdleStatus.WRITER_IDLE.equals(status)) { - //write heartbeat frame: + // write heartbeat frame: _logger.debug("Sent heartbeat"); session.write(HeartbeatBody.FRAME); HeartbeatDiagnostics.sent(); } else if (IdleStatus.READER_IDLE.equals(status)) { - //failover: + // failover: HeartbeatDiagnostics.timeout(); _logger.warn("Timed out while waiting for heartbeat from peer."); session.close(); } } - public void exceptionCaught(IoSession session, Throwable cause) throws Exception + /** + * Invoked when any exception is thrown by a user IoHandler implementation or by MINA. If the cause is an + * IOException, MINA will close the connection automatically. + * + * @param session The MINA session. + * @param cause The exception that triggered this event. + */ + public void exceptionCaught(IoSession session, Throwable cause) { if (_failoverState == FailoverState.NOT_STARTED) { - //if (!(cause instanceof AMQUndeliveredException) && (!(cause instanceof AMQAuthenticationException))) + // if (!(cause instanceof AMQUndeliveredException) && (!(cause instanceof AMQAuthenticationException))) if (cause instanceof AMQConnectionClosedException) { _logger.info("Exception caught therefore going to attempt failover: " + cause, cause); @@ -250,8 +331,8 @@ public class AMQProtocolHandler extends IoHandlerAdapter sessionClosed(session); } - //FIXME Need to correctly handle other exceptions. Things like ... -// if (cause instanceof AMQChannelClosedException) + // FIXME Need to correctly handle other exceptions. Things like ... + // if (cause instanceof AMQChannelClosedException) // which will cause the JMSSession to end due to a channel close and so that Session needs // to be removed from the map so we can correctly still call close without an exception when trying to close // the server closed session. See also CloseChannelMethodHandler as the sessionClose is never called on exception @@ -261,6 +342,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter else if (_failoverState == FailoverState.FAILED) { _logger.error("Exception caught by protocol handler: " + cause, cause); + // we notify the state manager of the error in case we have any clients waiting on a state // change. Those "waiters" will be interrupted and can handle the exception AMQException amqe = new AMQException(null, "Protocol handler error: " + cause, cause); @@ -297,7 +379,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter final boolean debug = _logger.isDebugEnabled(); final long msgNumber = ++_messageReceivedCount; - if (debug && (msgNumber % 1000 == 0)) + if (debug && ((msgNumber % 1000) == 0)) { _logger.debug("Received " + _messageReceivedCount + " protocol messages"); } @@ -317,7 +399,8 @@ public class AMQProtocolHandler extends IoHandlerAdapter _logger.debug("(" + System.identityHashCode(this) + ")Method frame received: " + frame); } - final AMQMethodEvent<AMQMethodBody> evt = new AMQMethodEvent<AMQMethodBody>(frame.getChannel(), (AMQMethodBody) bodyFrame); + final AMQMethodEvent<AMQMethodBody> evt = + new AMQMethodEvent<AMQMethodBody>(frame.getChannel(), (AMQMethodBody) bodyFrame); try { @@ -331,10 +414,16 @@ public class AMQProtocolHandler extends IoHandlerAdapter final AMQMethodListener listener = (AMQMethodListener) it.next(); wasAnyoneInterested = listener.methodReceived(evt) || wasAnyoneInterested; } + if (!wasAnyoneInterested) + { + throw new AMQException(null, "AMQMethodEvent " + evt + " was not processed by any listener. Listeners:" + _frameListeners, null); + } } + if (!wasAnyoneInterested) { - throw new AMQException(null, "AMQMethodEvent " + evt + " was not processed by any listener. Listeners:" + _frameListeners, null); + throw new AMQException(null, "AMQMethodEvent " + evt + " was not processed by any listener. Listeners:" + + _frameListeners, null); } } catch (AMQException e) @@ -349,20 +438,20 @@ public class AMQProtocolHandler extends IoHandlerAdapter listener.error(e); } } + exceptionCaught(session, e); } + break; case ContentHeaderBody.TYPE: - _protocolSession.messageContentHeaderReceived(frame.getChannel(), - (ContentHeaderBody) bodyFrame); + _protocolSession.messageContentHeaderReceived(frame.getChannel(), (ContentHeaderBody) bodyFrame); break; case ContentBody.TYPE: - _protocolSession.messageContentBodyReceived(frame.getChannel(), - (ContentBody) bodyFrame); + _protocolSession.messageContentBodyReceived(frame.getChannel(), (ContentBody) bodyFrame); break; case HeartbeatBody.TYPE: @@ -371,11 +460,13 @@ public class AMQProtocolHandler extends IoHandlerAdapter { _logger.debug("Received heartbeat"); } + break; default: } + _connection.bytesReceived(_protocolSession.getIoSession().getReadBytes()); } @@ -387,10 +478,11 @@ public class AMQProtocolHandler extends IoHandlerAdapter final boolean debug = _logger.isDebugEnabled(); - if (debug && (sentMessages % 1000 == 0)) + if (debug && ((sentMessages % 1000) == 0)) { _logger.debug("Sent " + _messagesOut + " protocol messages"); } + _connection.bytesSent(session.getWrittenBytes()); if (debug) { @@ -408,7 +500,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter { _frameListeners.remove(listener); } - */ + */ public void attainState(AMQState s) throws AMQException { getStateManager().attainState(s); @@ -437,9 +529,8 @@ public class AMQProtocolHandler extends IoHandlerAdapter * @param frame * @param listener the blocking listener. Note the calling thread will block. */ - public AMQMethodEvent writeCommandFrameAndWaitForReply(AMQFrame frame, - BlockingMethodFrameListener listener) - throws AMQException + public AMQMethodEvent writeCommandFrameAndWaitForReply(AMQFrame frame, BlockingMethodFrameListener listener) + throws AMQException, FailoverException { return writeCommandFrameAndWaitForReply(frame, listener, DEFAULT_SYNC_TIMEOUT); } @@ -451,9 +542,8 @@ public class AMQProtocolHandler extends IoHandlerAdapter * @param frame * @param listener the blocking listener. Note the calling thread will block. */ - public AMQMethodEvent writeCommandFrameAndWaitForReply(AMQFrame frame, - BlockingMethodFrameListener listener, long timeout) - throws AMQException + public AMQMethodEvent writeCommandFrameAndWaitForReply(AMQFrame frame, BlockingMethodFrameListener listener, + long timeout) throws AMQException, FailoverException { try { @@ -461,6 +551,7 @@ public class AMQProtocolHandler extends IoHandlerAdapter _protocolSession.writeFrame(frame); AMQMethodEvent e = listener.blockForFrame(timeout); + return e; // When control resumes before this line, a reply will have been received // that matches the criteria defined in the blocking listener @@ -478,25 +569,33 @@ public class AMQProtocolHandler extends IoHandlerAdapter } /** More convenient method to write a frame and wait for it's response. */ - public AMQMethodEvent syncWrite(AMQFrame frame, Class responseClass) throws AMQException + public AMQMethodEvent syncWrite(AMQFrame frame, Class responseClass) throws AMQException, FailoverException { return syncWrite(frame, responseClass, DEFAULT_SYNC_TIMEOUT); } /** More convenient method to write a frame and wait for it's response. */ - public AMQMethodEvent syncWrite(AMQFrame frame, Class responseClass, long timeout) throws AMQException + public AMQMethodEvent syncWrite(AMQFrame frame, Class responseClass, long timeout) throws AMQException, FailoverException { - return writeCommandFrameAndWaitForReply(frame, - new SpecificMethodFrameListener(frame.getChannel(), responseClass), timeout); + return writeCommandFrameAndWaitForReply(frame, new SpecificMethodFrameListener(frame.getChannel(), responseClass), + timeout); } - - public void closeSession(AMQSession session) throws AMQException { _protocolSession.closeSession(session); } + /** + * Closes the connection. + * + * <p/>If a failover exception occurs whilst closing the connection it is ignored, as the connection is closed + * anyway. + * + * @param timeout The timeout to wait for an acknowledgement to the close request. + * + * @throws AMQException If the close fails for any reason. + */ public void closeConnection(long timeout) throws AMQException { getStateManager().changeState(AMQState.CONNECTION_CLOSING); @@ -504,13 +603,13 @@ public class AMQProtocolHandler extends IoHandlerAdapter // AMQP version change: Hardwire the version to 0-8 (major=8, minor=0) // TODO: Connect this to the session version obtained from ProtocolInitiation for this session. // Be aware of possible changes to parameter order as versions change. - final AMQFrame frame = ConnectionCloseBody.createAMQFrame(0, - _protocolSession.getProtocolMajorVersion(), - _protocolSession.getProtocolMinorVersion(), // AMQP version (major, minor) - 0, // classId - 0, // methodId - AMQConstant.REPLY_SUCCESS.getCode(), // replyCode - new AMQShortString("JMS client is closing the connection.")); // replyText + final AMQFrame frame = + ConnectionCloseBody.createAMQFrame(0, _protocolSession.getProtocolMajorVersion(), + _protocolSession.getProtocolMinorVersion(), // AMQP version (major, minor) + 0, // classId + 0, // methodId + AMQConstant.REPLY_SUCCESS.getCode(), // replyCode + new AMQShortString("JMS client is closing the connection.")); // replyText try { @@ -521,8 +620,10 @@ public class AMQProtocolHandler extends IoHandlerAdapter { _protocolSession.closeProtocolSession(false); } - - + catch (FailoverException e) + { + _logger.debug("FailoverException interrupted connection close, ignoring as connection close anyway."); + } } /** @return the number of bytes read from this protocol session */ @@ -604,7 +705,6 @@ public class AMQProtocolHandler extends IoHandlerAdapter return _protocolSession.getProtocolMajorVersion(); } - public byte getProtocolMinorVersion() { return _protocolSession.getProtocolMinorVersion(); diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java index f691637cdc..dcab89e9bb 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/AMQProtocolSession.java @@ -20,16 +20,8 @@ */ package org.apache.qpid.client.protocol; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -import javax.jms.JMSException; -import javax.security.sasl.SaslClient; - import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; - import org.apache.mina.common.CloseFuture; import org.apache.mina.common.IdleStatus; import org.apache.mina.common.IoSession; @@ -53,16 +45,24 @@ import org.apache.qpid.framing.VersionSpecificRegistry; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.security.sasl.SaslClient; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + /** * Wrapper for protocol session that provides type-safe access to session attributes. <p/> The underlying protocol * session is still available but clients should not use it to obtain session attributes. */ public class AMQProtocolSession implements AMQVersionAwareProtocolSession { - protected static final int LAST_WRITE_FUTURE_JOIN_TIMEOUT = 1000 * 60 * 2; - protected static final Logger _logger = Logger.getLogger(AMQProtocolSession.class); + protected static final Logger _logger = LoggerFactory.getLogger(AMQProtocolSession.class); public static final String PROTOCOL_INITIATION_RECEIVED = "ProtocolInitiatiionReceived"; diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java b/java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java index 4691d48f29..0ab2e07340 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/BlockingMethodFrameListener.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -27,71 +27,137 @@ import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; +/** + * BlockingMethodFrameListener is a 'rendezvous' which acts as a {@link AMQMethodListener} that delegates handling of + * incoming methods to a method listener implemented as a sub-class of this and hands off the processed method or + * error to a consumer. The producer of the event does not have to wait for the consumer to take the event, so this + * differs from a 'rendezvous' in that sense. + * + * <p/>BlockingMethodFrameListeners are used to coordinate waiting for replies to method calls that expect a response. + * They are always used in a 'one-shot' manner, that is, to recieve just one response. Usually the caller has to register + * them as method listeners with an event dispatcher and remember to de-register them (in a finally block) once they + * have been completed. + * + * <p/>The {@link #processMethod} must return <tt>true</tt> on any incoming method that it handles. This indicates to + * this listeners that the method it is waiting for has arrived. Incoming methods are also filtered by channel prior to + * being passed to the {@link #processMethod} method, so responses are only received for a particular channel. The + * channel id must be passed to the constructor. + * + * <p/>Errors from the producer are rethrown to the consumer. + * + * <p/><table id="crc"><caption>CRC Card</caption> + * <tr><th> Responsibilities <th> Collaborations + * <tr><td> Accept notification of AMQP method events. <td> {@link AMQMethodEvent} + * <tr><td> Delegate handling of the method to another method listener. <td> {@link AMQMethodBody} + * <tr><td> Block until a method is handled by the delegated to handler. + * <tr><td> Propagate the most recent exception to the consumer. + * </table> + * + * @todo Might be neater if this method listener simply wrapped another that provided the method handling using a + * methodRecevied method. The processMethod takes an additional channelId, however none of the implementations + * seem to use it. So wrapping the listeners is possible. + * + * @todo What is to stop a blocking method listener, receiving a second method whilst it is registered as a listener, + * overwriting the first one before the caller of the block method has had a chance to examine it? If one-shot + * behaviour is to be intended it should be enforced, perhaps by always returning false once the blocked for + * method has been received. + * + * @todo Interuption is caught but not handled. This could be allowed to fall through. This might actually be usefull + * for fail-over where a thread is blocking when failure happens, it could be interrupted to abandon or retry + * when this happens. At the very least, restore the interrupted status flag. + * + * @todo If the retrotranslator can handle it, could use a SynchronousQueue to implement this rendezvous. Need to + * check that SynchronousQueue has a non-blocking put method available. + */ public abstract class BlockingMethodFrameListener implements AMQMethodListener { + /** This flag is used to indicate that the blocked for method has been received. */ private volatile boolean _ready = false; - public abstract boolean processMethod(int channelId, AMQMethodBody frame) throws AMQException; - + /** Used to protect the shared event and ready flag between the producer and consumer. */ private final Object _lock = new Object(); - /** - * This is set if there is an exception thrown from processCommandFrame and the - * exception is rethrown to the caller of blockForFrame() - */ + /** Used to hold the most recent exception that is passed to the {@link #error(Exception)} method. */ private volatile Exception _error; + /** Holds the channel id for the channel upon which this listener is waiting for a response. */ protected int _channelId; + /** Holds the incoming method. */ protected AMQMethodEvent _doneEvt = null; + /** + * Creates a new method listener, that filters incoming method to just those that match the specified channel id. + * + * @param channelId The channel id to filter incoming methods with. + */ public BlockingMethodFrameListener(int channelId) { _channelId = channelId; } /** - * This method is called by the MINA dispatching thread. Note that it could - * be called before blockForFrame() has been called. + * Delegates any additional handling of the incoming methods to another handler. * - * @param evt the frame event - * @return true if the listener has dealt with this frame - * @throws AMQException + * @param channelId The channel id of the incoming method. + * @param frame The method body. + * + * @return <tt>true</tt> if the method was handled, <tt>false</tt> otherwise. */ - public boolean methodReceived(AMQMethodEvent evt) throws AMQException + public abstract boolean processMethod(int channelId, AMQMethodBody frame); // throws AMQException; + + /** + * Informs this listener that an AMQP method has been received. + * + * @param evt The AMQP method. + * + * @return <tt>true</tt> if this listener has handled the method, <tt>false</tt> otherwise. + */ + public boolean methodReceived(AMQMethodEvent evt) // throws AMQException { AMQMethodBody method = evt.getMethod(); - try + /*try + {*/ + boolean ready = (evt.getChannelId() == _channelId) && processMethod(evt.getChannelId(), method); + + if (ready) { - boolean ready = (evt.getChannelId() == _channelId) && processMethod(evt.getChannelId(), method); - if (ready) + // we only update the flag from inside the synchronized block + // so that the blockForFrame method cannot "miss" an update - it + // will only ever read the flag from within the synchronized block + synchronized (_lock) { - // we only update the flag from inside the synchronized block - // so that the blockForFrame method cannot "miss" an update - it - // will only ever read the flag from within the synchronized block - synchronized (_lock) - { - _doneEvt = evt; - _ready = ready; - _lock.notify(); - } + _doneEvt = evt; + _ready = ready; + _lock.notify(); } - return ready; } + + return ready; + + /*} catch (AMQException e) { error(e); // we rethrow the error here, and the code in the frame dispatcher will go round // each listener informing them that an exception has been thrown throw e; - } + }*/ } /** - * This method is called by the thread that wants to wait for a frame. + * Blocks until a method is received that is handled by the delegated to method listener, or the specified timeout + * has passed. + * + * @param timeout The timeout in milliseconds. + * + * @return The AMQP method that was received. + * + * @throws AMQException + * @throws FailoverException */ - public AMQMethodEvent blockForFrame(long timeout) throws AMQException + public AMQMethodEvent blockForFrame(long timeout) throws AMQException, FailoverException { synchronized (_lock) { @@ -117,24 +183,25 @@ public abstract class BlockingMethodFrameListener implements AMQMethodListener catch (InterruptedException e) { // IGNORE -- //fixme this isn't ideal as being interrupted isn't equivellant to sucess -// if (!_ready && timeout != -1) -// { -// _error = new AMQException("Server did not respond timely"); -// _ready = true; -// } + // if (!_ready && timeout != -1) + // { + // _error = new AMQException("Server did not respond timely"); + // _ready = true; + // } } } } + if (_error != null) { if (_error instanceof AMQException) { - throw(AMQException) _error; + throw (AMQException) _error; } else if (_error instanceof FailoverException) { - // This should ensure that FailoverException is not wrapped and can be caught. - throw(FailoverException) _error; // needed to expose FailoverException. + // This should ensure that FailoverException is not wrapped and can be caught. + throw (FailoverException) _error; // needed to expose FailoverException. } else { @@ -156,6 +223,7 @@ public abstract class BlockingMethodFrameListener implements AMQMethodListener // set the error so that the thread that is blocking (against blockForFrame()) // can pick up the exception and rethrow to the caller _error = e; + synchronized (_lock) { _ready = true; diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/HeartbeatConfig.java b/java/client/src/main/java/org/apache/qpid/client/protocol/HeartbeatConfig.java index 6a7462cd0f..35ea44a331 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/HeartbeatConfig.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/HeartbeatConfig.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,11 +20,12 @@ */ package org.apache.qpid.client.protocol; -import org.apache.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; class HeartbeatConfig { - private static final Logger _logger = Logger.getLogger(HeartbeatConfig.class); + private static final Logger _logger = LoggerFactory.getLogger(HeartbeatConfig.class); static final HeartbeatConfig CONFIG = new HeartbeatConfig(); /** @@ -35,13 +36,13 @@ class HeartbeatConfig HeartbeatConfig() { String property = System.getProperty("amqj.heartbeat.timeoutFactor"); - if(property != null) + if (property != null) { try { timeoutFactor = Float.parseFloat(property); } - catch(NumberFormatException e) + catch (NumberFormatException e) { _logger.warn("Invalid timeout factor (amqj.heartbeat.timeoutFactor): " + property); } diff --git a/java/client/src/main/java/org/apache/qpid/client/protocol/ProtocolBufferMonitorFilter.java b/java/client/src/main/java/org/apache/qpid/client/protocol/ProtocolBufferMonitorFilter.java index 652468d45d..93cc5e7ec3 100644 --- a/java/client/src/main/java/org/apache/qpid/client/protocol/ProtocolBufferMonitorFilter.java +++ b/java/client/src/main/java/org/apache/qpid/client/protocol/ProtocolBufferMonitorFilter.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,10 +20,12 @@ */ package org.apache.qpid.client.protocol; -import org.apache.log4j.Logger; import org.apache.mina.common.IoFilterAdapter; import org.apache.mina.common.IoSession; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * A MINA filter that monitors the numbers of messages pending to be sent by MINA. It outputs a message * when a threshold has been exceeded, and has a frequency configuration so that messages are not output @@ -32,13 +34,13 @@ import org.apache.mina.common.IoSession; */ public class ProtocolBufferMonitorFilter extends IoFilterAdapter { - private static final Logger _logger = Logger.getLogger(ProtocolBufferMonitorFilter.class); + private static final Logger _logger = LoggerFactory.getLogger(ProtocolBufferMonitorFilter.class); public static long DEFAULT_FREQUENCY = 5000; public static int DEFAULT_THRESHOLD = 3000; - private int _bufferedMessages = 0; + private int _bufferedMessages = 0; private int _threshold; @@ -58,7 +60,7 @@ public class ProtocolBufferMonitorFilter extends IoFilterAdapter _outputFrequencyInMillis = frequency; } - public void messageReceived( NextFilter nextFilter, IoSession session, Object message ) throws Exception + public void messageReceived(NextFilter nextFilter, IoSession session, Object message) throws Exception { _bufferedMessages++; if (_bufferedMessages > _threshold) @@ -66,8 +68,8 @@ public class ProtocolBufferMonitorFilter extends IoFilterAdapter long now = System.currentTimeMillis(); if ((now - _lastMessageOutputTime) > _outputFrequencyInMillis) { - _logger.warn("Protocol message buffer exceeded threshold of " + _threshold + ". Current backlog: " + - _bufferedMessages); + _logger.warn("Protocol message buffer exceeded threshold of " + _threshold + ". Current backlog: " + + _bufferedMessages); _lastMessageOutputTime = now; } } @@ -75,7 +77,7 @@ public class ProtocolBufferMonitorFilter extends IoFilterAdapter nextFilter.messageReceived(session, message); } - public void messageSent( NextFilter nextFilter, IoSession session, Object message ) throws Exception + public void messageSent(NextFilter nextFilter, IoSession session, Object message) throws Exception { _bufferedMessages--; nextFilter.messageSent(session, message); diff --git a/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java b/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java index 5c0f1de5bb..140cbdeb75 100644 --- a/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java +++ b/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.java @@ -20,10 +20,11 @@ */ package org.apache.qpid.client.security; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; +import org.apache.qpid.util.FileUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.io.IOException; import java.io.InputStream; import java.util.Enumeration; @@ -31,10 +32,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Properties; -import org.apache.log4j.Logger; - -import org.apache.qpid.util.FileUtils; - /** * CallbackHandlerRegistry is a registry for call back handlers for user authentication and interaction during user * authentication. It is capable of reading its configuration from a properties file containing call back handler @@ -60,7 +57,7 @@ import org.apache.qpid.util.FileUtils; */ public class CallbackHandlerRegistry { - private static final Logger _logger = Logger.getLogger(CallbackHandlerRegistry.class); + private static final Logger _logger = LoggerFactory.getLogger(CallbackHandlerRegistry.class); /** The name of the system property that holds the name of the callback handler properties file. */ private static final String FILE_PROPERTY = "amq.callbackhandler.properties"; @@ -121,7 +118,7 @@ public class CallbackHandlerRegistry String filename = System.getProperty(FILE_PROPERTY); InputStream is = FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME, - CallbackHandlerRegistry.class.getClassLoader()); + CallbackHandlerRegistry.class.getClassLoader()); try { @@ -167,12 +164,12 @@ public class CallbackHandlerRegistry _logger.error("Unable to read from file " + filename + ": " + e, e); } } - + if (useDefault) { is = CallbackHandlerRegistry.class.getResourceAsStream(DEFAULT_RESOURCE_NAME); } - + return is; }*/ @@ -207,7 +204,7 @@ public class CallbackHandlerRegistry if (!AMQCallbackHandler.class.isAssignableFrom(clazz)) { _logger.warn("SASL provider " + clazz + " does not implement " + AMQCallbackHandler.class - + ". Skipping"); + + ". Skipping"); continue; } diff --git a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java index 04db8044de..803b34b7fa 100644 --- a/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java +++ b/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.java @@ -20,6 +20,13 @@ */ package org.apache.qpid.client.security; +import org.apache.qpid.util.FileUtils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.security.sasl.SaslClientFactory; + import java.io.IOException; import java.io.InputStream; import java.security.Security; @@ -28,13 +35,6 @@ import java.util.Map; import java.util.Properties; import java.util.TreeMap; -import javax.security.sasl.SaslClientFactory; - - -import org.apache.log4j.Logger; - -import org.apache.qpid.util.FileUtils; - /** * DynamicSaslRegistrar provides a collection of helper methods for reading a configuration file that contains a mapping * from SASL mechanism names to implementing client factory class names and registering a security provider with the @@ -55,7 +55,7 @@ import org.apache.qpid.util.FileUtils; */ public class DynamicSaslRegistrar { - private static final Logger _logger = Logger.getLogger(DynamicSaslRegistrar.class); + private static final Logger _logger = LoggerFactory.getLogger(DynamicSaslRegistrar.class); /** The name of the system property that holds the name of the SASL configuration properties. */ private static final String FILE_PROPERTY = "amq.dynamicsaslregistrar.properties"; @@ -71,8 +71,8 @@ public class DynamicSaslRegistrar // Open the SASL properties file, using the default name is one is not specified. String filename = System.getProperty(FILE_PROPERTY); InputStream is = - FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME, - DynamicSaslRegistrar.class.getClassLoader()); + FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME, + DynamicSaslRegistrar.class.getClassLoader()); try { @@ -169,7 +169,7 @@ public class DynamicSaslRegistrar Enumeration e = props.propertyNames(); TreeMap<String, Class<? extends SaslClientFactory>> factoriesToRegister = - new TreeMap<String, Class<? extends SaslClientFactory>>(); + new TreeMap<String, Class<? extends SaslClientFactory>>(); while (e.hasMoreElements()) { diff --git a/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java b/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java index 5bf120454e..5a2c5ac5c1 100644 --- a/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java +++ b/java/client/src/main/java/org/apache/qpid/client/security/JCAProvider.java @@ -20,13 +20,13 @@ */ package org.apache.qpid.client.security; -import java.security.Provider; -import java.security.Security; -import java.util.Map; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.security.sasl.SaslClientFactory; -import org.apache.log4j.Logger; +import java.security.Provider; +import java.util.Map; /** * JCAProvider is a security provider for SASL client factories that is configured from a map of SASL mechanism names @@ -40,7 +40,7 @@ import org.apache.log4j.Logger; */ public class JCAProvider extends Provider { - private static final Logger log = Logger.getLogger(JCAProvider.class); + private static final Logger log = LoggerFactory.getLogger(JCAProvider.class); /** * Creates the security provider with a map from SASL mechanisms to implementing factories. @@ -50,9 +50,9 @@ public class JCAProvider extends Provider public JCAProvider(Map<String, Class<? extends SaslClientFactory>> providerMap) { super("AMQSASLProvider", 1.0, "A JCA provider that registers all " - + "AMQ SASL providers that want to be registered"); + + "AMQ SASL providers that want to be registered"); register(providerMap); -// Security.addProvider(this); + // Security.addProvider(this); } /** diff --git a/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java b/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java index 46323e8c09..66176dac3c 100644 --- a/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java +++ b/java/client/src/main/java/org/apache/qpid/client/security/UsernameHashedPasswordCallbackHandler.java @@ -20,26 +20,24 @@ */ package org.apache.qpid.client.security; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; +import org.apache.qpid.client.protocol.AMQProtocolSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.security.auth.callback.Callback; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; -import javax.security.sasl.RealmCallback; - -import com.sun.crypto.provider.HmacMD5; -import org.apache.log4j.Logger; - -import org.apache.qpid.client.protocol.AMQProtocolSession; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler { - private static final Logger _logger = Logger.getLogger(UsernameHashedPasswordCallbackHandler.class); + private static final Logger _logger = LoggerFactory.getLogger(UsernameHashedPasswordCallbackHandler.class); private AMQProtocolSession _protocolSession; @@ -91,11 +89,11 @@ public class UsernameHashedPasswordCallbackHandler implements AMQCallbackHandler byte[] digest = md.digest(); - char[] hash = new char[digest.length ]; + char[] hash = new char[digest.length]; int index = 0; for (byte b : digest) - { + { hash[index++] = (char) b; } diff --git a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java index c995bf40da..bef3180041 100644 --- a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java +++ b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java @@ -20,12 +20,6 @@ */ package org.apache.qpid.client.state; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.concurrent.CopyOnWriteArraySet; - -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.client.handler.BasicCancelOkMethodHandler; import org.apache.qpid.client.handler.BasicDeliverMethodHandler; @@ -58,13 +52,22 @@ import org.apache.qpid.framing.QueueDeleteOkBody; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArraySet; + /** * The state manager is responsible for managing the state of the protocol session. <p/> For each AMQProtocolHandler * there is a separate state manager. */ public class AMQStateManager implements AMQMethodListener { - private static final Logger _logger = Logger.getLogger(AMQStateManager.class); + private static final Logger _logger = LoggerFactory.getLogger(AMQStateManager.class); + private AMQProtocolSession _protocolSession; /** The current state */ @@ -78,14 +81,13 @@ public class AMQStateManager implements AMQMethodListener private final CopyOnWriteArraySet _stateListeners = new CopyOnWriteArraySet(); private final Object _stateLock = new Object(); - private static final long MAXIMUM_STATE_WAIT_TIME = 30000l; + private static final long MAXIMUM_STATE_WAIT_TIME = 30000L; public AMQStateManager() { this(null); } - public AMQStateManager(AMQProtocolSession protocolSession) { this(AMQState.CONNECTION_NOT_STARTED, true, protocolSession); @@ -179,20 +181,22 @@ public class AMQStateManager implements AMQMethodListener if (handler != null) { handler.methodReceived(this, _protocolSession, evt); + return true; } + return false; } - protected StateAwareMethodListener findStateTransitionHandler(AMQState currentState, - AMQMethodBody frame) - // throws IllegalStateTransitionException + protected StateAwareMethodListener findStateTransitionHandler(AMQState currentState, AMQMethodBody frame) + // throws IllegalStateTransitionException { final Class clazz = frame.getClass(); if (_logger.isDebugEnabled()) { _logger.debug("Looking for state[" + currentState + "] transition handler for frame " + clazz); } + final Map classToHandlerMap = (Map) _state2HandlersMap.get(currentState); if (classToHandlerMap == null) @@ -201,12 +205,14 @@ public class AMQStateManager implements AMQMethodListener // handler registered for "all" states return findStateTransitionHandler(null, frame); } + final StateAwareMethodListener handler = (StateAwareMethodListener) classToHandlerMap.get(clazz); if (handler == null) { if (currentState == null) { _logger.debug("No state transition handler defined for receiving frame " + frame); + return null; } else @@ -222,7 +228,6 @@ public class AMQStateManager implements AMQMethodListener } } - public void attainState(final AMQState s) throws AMQException { synchronized (_stateLock) @@ -230,7 +235,7 @@ public class AMQStateManager implements AMQMethodListener final long waitUntilTime = System.currentTimeMillis() + MAXIMUM_STATE_WAIT_TIME; long waitTime = MAXIMUM_STATE_WAIT_TIME; - while (_currentState != s && waitTime > 0) + while ((_currentState != s) && (waitTime > 0)) { try { @@ -240,11 +245,13 @@ public class AMQStateManager implements AMQMethodListener { _logger.warn("Thread interrupted"); } + if (_currentState != s) { waitTime = waitUntilTime - System.currentTimeMillis(); } } + if (_currentState != s) { _logger.warn("State not achieved within permitted time. Current state " + _currentState + ", desired state: " + s); diff --git a/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java b/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java index 1fd657c5fb..8b8453a1b0 100644 --- a/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java +++ b/java/client/src/main/java/org/apache/qpid/client/state/StateWaiter.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,15 +20,17 @@ */ package org.apache.qpid.client.state; -import org.apache.log4j.Logger; import org.apache.qpid.AMQException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Waits for a particular state to be reached. */ public class StateWaiter implements StateListener { - private static final Logger _logger = Logger.getLogger(StateWaiter.class); + private static final Logger _logger = LoggerFactory.getLogger(StateWaiter.class); private final AMQState _state; @@ -52,13 +54,13 @@ public class StateWaiter implements StateListener // The guard is required in case we are woken up by a spurious // notify(). // - while (!_newStateAchieved && _throwable == null) + while (!_newStateAchieved && (_throwable == null)) { try { _logger.debug("State " + _state + " not achieved so waiting..."); _monitor.wait(TIME_OUT); - //fixme this won't cause the timeout to exit the loop. need to set _throwable + // fixme this won't cause the timeout to exit the loop. need to set _throwable } catch (InterruptedException e) { @@ -72,7 +74,7 @@ public class StateWaiter implements StateListener _logger.debug("Throwable reached state waiter: " + _throwable); if (_throwable instanceof AMQException) { - throw(AMQException) _throwable; + throw (AMQException) _throwable; } else { @@ -89,6 +91,7 @@ public class StateWaiter implements StateListener { _logger.debug("stateChanged called changing from :" + oldState + " to :" + newState); } + if (_state == newState) { _newStateAchieved = true; @@ -97,6 +100,7 @@ public class StateWaiter implements StateListener { _logger.debug("New state reached so notifying monitor"); } + _monitor.notifyAll(); } } diff --git a/java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java b/java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java index 1c70ded62a..623591e0b6 100644 --- a/java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java +++ b/java/client/src/main/java/org/apache/qpid/client/state/listener/SpecificMethodFrameListener.java @@ -34,7 +34,7 @@ public class SpecificMethodFrameListener extends BlockingMethodFrameListener _expectedClass = expectedClass; } - public boolean processMethod(int channelId, AMQMethodBody frame) throws AMQException + public boolean processMethod(int channelId, AMQMethodBody frame) //throws AMQException { return _expectedClass.isInstance(frame); } diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java b/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java index 04e7e40564..5482e48699 100644 --- a/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/transport/SocketTransportConnection.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,28 +20,32 @@ */ package org.apache.qpid.client.transport; -import java.io.IOException; -import java.net.InetSocketAddress; - -import org.apache.log4j.Logger; import org.apache.mina.common.ByteBuffer; import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IoConnector; import org.apache.mina.common.SimpleByteBufferAllocator; import org.apache.mina.transport.socket.nio.SocketConnectorConfig; import org.apache.mina.transport.socket.nio.SocketSessionConfig; + import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.pool.ReadWriteThreadModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.net.InetSocketAddress; + public class SocketTransportConnection implements ITransportConnection { - private static final Logger _logger = Logger.getLogger(SocketTransportConnection.class); + private static final Logger _logger = LoggerFactory.getLogger(SocketTransportConnection.class); private static final int DEFAULT_BUFFER_SIZE = 32 * 1024; private SocketConnectorFactory _socketConnectorFactory; - static interface SocketConnectorFactory { + static interface SocketConnectorFactory + { IoConnector newSocketConnector(); } @@ -50,8 +54,7 @@ public class SocketTransportConnection implements ITransportConnection _socketConnectorFactory = socketConnectorFactory; } - public void connect(AMQProtocolHandler protocolHandler, BrokerDetails brokerDetail) - throws IOException + public void connect(AMQProtocolHandler protocolHandler, BrokerDetails brokerDetail) throws IOException { ByteBuffer.setUseDirectBuffers(Boolean.getBoolean("amqj.enableDirectBuffers")); diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java b/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java index b9193ce14e..459579d920 100644 --- a/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/transport/TransportConnection.java @@ -20,13 +20,6 @@ */ package org.apache.qpid.client.transport; -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import org.apache.log4j.Logger; - import org.apache.mina.common.IoConnector; import org.apache.mina.common.IoHandlerAdapter; import org.apache.mina.common.IoServiceConfig; @@ -34,11 +27,18 @@ import org.apache.mina.transport.socket.nio.SocketConnector; import org.apache.mina.transport.vmpipe.VmPipeAcceptor; import org.apache.mina.transport.vmpipe.VmPipeAddress; -import org.apache.qpid.client.AMQBrokerDetails; import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.pool.ReadWriteThreadModel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + /** * The TransportConnection is a helper class responsible for connecting to an AMQ server. It sets up the underlying * connector, which currently always uses TCP/IP sockets. It creates the "protocol handler" which deals with MINA @@ -57,7 +57,7 @@ public class TransportConnection private static final int TCP = 0; private static final int VM = 1; - private static Logger _logger = Logger.getLogger(TransportConnection.class); + private static Logger _logger = LoggerFactory.getLogger(TransportConnection.class); private static final String DEFAULT_QPID_SERVER = "org.apache.qpid.server.protocol.AMQPFastProtocolHandler"; @@ -99,7 +99,7 @@ public class TransportConnection // FIXME - this needs to be sorted to use the new Mina MultiThread SA. if (Boolean.getBoolean("qpidnio")) { - _logger.fatal("Using Qpid NIO - sysproperty 'qpidnio' is set."); + _logger.error("Using Qpid NIO - sysproperty 'qpidnio' is set."); // result = new org.apache.qpid.nio.SocketConnector(); // non-blocking connector } // else @@ -193,7 +193,7 @@ public class TransportConnection } catch (IOException e) { - _logger.error(e); + _logger.error("Got IOException.", e); // Try and unbind provider try @@ -262,7 +262,6 @@ public class TransportConnection catch (Exception e) { _logger.info("Unable to create InVM Qpid.AMQP on port " + port + ". Because: " + e.getCause()); - _logger.error(e); String because; if (e.getCause() == null) { diff --git a/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java b/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java index 104c4b43d0..d9137dc8b1 100644 --- a/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/transport/VmPipeTransportConnection.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,21 +20,25 @@ */ package org.apache.qpid.client.transport; -import java.io.IOException; - -import org.apache.log4j.Logger; import org.apache.mina.common.ConnectFuture; import org.apache.mina.common.IoServiceConfig; import org.apache.mina.transport.vmpipe.VmPipeAddress; import org.apache.mina.transport.vmpipe.VmPipeConnector; + import org.apache.qpid.client.protocol.AMQProtocolHandler; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.pool.PoolingFilter; import org.apache.qpid.pool.ReferenceCountingExecutorService; +import org.apache.qpid.pool.ReadWriteThreadModel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; public class VmPipeTransportConnection implements ITransportConnection { - private static final Logger _logger = Logger.getLogger(VmPipeTransportConnection.class); + private static final Logger _logger = LoggerFactory.getLogger(VmPipeTransportConnection.class); private static int _port; @@ -47,14 +51,9 @@ public class VmPipeTransportConnection implements ITransportConnection { final VmPipeConnector ioConnector = new VmPipeConnector(); final IoServiceConfig cfg = ioConnector.getDefaultConfig(); - ReferenceCountingExecutorService executorService = ReferenceCountingExecutorService.getInstance(); - PoolingFilter asyncRead = PoolingFilter.createAynschReadPoolingFilter(executorService, - "AsynchronousReadFilter"); - cfg.getFilterChain().addFirst("AsynchronousReadFilter", asyncRead); - PoolingFilter asyncWrite = PoolingFilter.createAynschWritePoolingFilter(executorService, - "AsynchronousWriteFilter"); - cfg.getFilterChain().addLast("AsynchronousWriteFilter", asyncWrite); - + + cfg.setThreadModel(ReadWriteThreadModel.getInstance()); + final VmPipeAddress address = new VmPipeAddress(_port); _logger.info("Attempting connection to " + address); ConnectFuture future = ioConnector.connect(address, protocolHandler); diff --git a/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java b/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java index 642b928d81..0fc39a9318 100644 --- a/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java +++ b/java/client/src/main/java/org/apache/qpid/client/util/FlowControllingBlockingQueue.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,16 +20,17 @@ */ package org.apache.qpid.client.util; - +import java.util.Iterator; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import java.util.Iterator; /** * A blocking queue that emits events above a user specified threshold allowing the caller to take action (e.g. flow * control) to try to prevent the queue growing (much) further. The underlying queue itself is not bounded therefore the * caller is not obliged to react to the events. <p/> This implementation is <b>only</b> safe where we have a single * thread adding items and a single (different) thread removing items. + * + * @todo Make this implement java.util.Queue and hide the implementation. Then different queue types can be substituted. */ public class FlowControllingBlockingQueue { @@ -81,6 +82,7 @@ public class FlowControllingBlockingQueue } } } + return o; } @@ -104,4 +106,3 @@ public class FlowControllingBlockingQueue return _queue.iterator(); } } - diff --git a/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java b/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java index 6ad3fb4bae..6ec883ff0b 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java +++ b/java/client/src/main/java/org/apache/qpid/jms/FailoverPolicy.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,22 +20,23 @@ */ package org.apache.qpid.jms; -import org.apache.log4j.Logger; import org.apache.qpid.jms.failover.FailoverMethod; import org.apache.qpid.jms.failover.FailoverRoundRobinServers; import org.apache.qpid.jms.failover.FailoverSingleServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class FailoverPolicy { - private static final Logger _logger = Logger.getLogger(FailoverPolicy.class); + private static final Logger _logger = LoggerFactory.getLogger(FailoverPolicy.class); private static final long MINUTE = 60000L; private static final long DEFAULT_METHOD_TIMEOUT = 1 * MINUTE; private static final long DEFAULT_FAILOVER_TIMEOUT = 4 * MINUTE; - private FailoverMethod _methods[] = new FailoverMethod[1]; + private FailoverMethod[] _methods = new FailoverMethod[1]; private int _currentMethod; @@ -52,7 +53,7 @@ public class FailoverPolicy { FailoverMethod method; - //todo This should be integrated in to the connection url when it supports + // todo This should be integrated in to the connection url when it supports // multiple strategies. _methodsRetries = 0; @@ -72,12 +73,12 @@ public class FailoverPolicy { String failoverMethod = connectionDetails.getFailoverMethod(); -/* - if (failoverMethod.equals(FailoverMethod.RANDOM)) - { - //todo write a random connection Failover - } -*/ + /* + if (failoverMethod.equals(FailoverMethod.RANDOM)) + { + //todo write a random connection Failover + } + */ if (failoverMethod.equals(FailoverMethod.SINGLE_BROKER)) { method = new FailoverRoundRobinServers(connectionDetails); @@ -92,12 +93,12 @@ public class FailoverPolicy { try { - Class[] constructorSpec = {ConnectionURL.class}; - Object [] params = {connectionDetails}; + Class[] constructorSpec = { ConnectionURL.class }; + Object[] params = { connectionDetails }; - method = (FailoverMethod) ClassLoader.getSystemClassLoader(). - loadClass(failoverMethod). - getConstructor(constructorSpec).newInstance(params); + method = + (FailoverMethod) ClassLoader.getSystemClassLoader().loadClass(failoverMethod) + .getConstructor(constructorSpec).newInstance(params); } catch (Exception cnfe) { @@ -157,13 +158,13 @@ public class FailoverPolicy return false; } - } else { if ((now - _lastFailTime) >= DEFAULT_FAILOVER_TIMEOUT) { _logger.info("Failover timeout"); + return false; } else @@ -179,7 +180,6 @@ public class FailoverPolicy _lastFailTime = _lastMethodTime; } - if (_methods[_currentMethod].failoverAllowed()) { failoverAllowed = true; @@ -190,6 +190,7 @@ public class FailoverPolicy { nextMethod(); _logger.info("Changing method to " + _methods[_currentMethod].methodName()); + return failoverAllowed(); } else @@ -207,6 +208,7 @@ public class FailoverPolicy { _currentMethod++; _methods[_currentMethod].reset(); + return true; } else @@ -225,11 +227,13 @@ public class FailoverPolicy _logger.info("Retrying methods starting with " + _methods[_currentMethod].methodName()); _methods[_currentMethod].reset(); + return failoverAllowed(); } else { _logger.debug("All failover methods exhausted"); + return false; } } @@ -278,7 +282,7 @@ public class FailoverPolicy public FailoverMethod getCurrentMethod() { - if (_currentMethod >= 0 && _currentMethod < (_methods.length - 1)) + if ((_currentMethod >= 0) && (_currentMethod < (_methods.length - 1))) { return _methods[_currentMethod]; } @@ -311,6 +315,7 @@ public class FailoverPolicy { sb.append(">"); } + sb.append(_methods[i].toString()); } diff --git a/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverRoundRobinServers.java b/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverRoundRobinServers.java index f8325c35ef..4e0d0b79b5 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverRoundRobinServers.java +++ b/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverRoundRobinServers.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,13 +20,15 @@ */ package org.apache.qpid.jms.failover; -import org.apache.log4j.Logger; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionURL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class FailoverRoundRobinServers implements FailoverMethod { - private static final Logger _logger = Logger.getLogger(FailoverRoundRobinServers.class); + private static final Logger _logger = LoggerFactory.getLogger(FailoverRoundRobinServers.class); /** The default number of times to cycle through all servers */ public static final int DEFAULT_CYCLE_RETRIES = 0; @@ -72,7 +74,7 @@ public class FailoverRoundRobinServers implements FailoverMethod _connectionDetails = connectionDetails; - //There is no current broker at startup so set it to -1. + // There is no current broker at startup so set it to -1. _currentBrokerIndex = -1; String cycleRetries = _connectionDetails.getFailoverOption(ConnectionURL.OPTIONS_FAILOVER_CYCLE); @@ -104,9 +106,8 @@ public class FailoverRoundRobinServers implements FailoverMethod public boolean failoverAllowed() { - return ((_currentCycleRetries < _cycleRetries) - || (_currentServerRetry < _serverRetries) - || (_currentBrokerIndex < (_connectionDetails.getBrokerCount() - 1))); + return ((_currentCycleRetries < _cycleRetries) || (_currentServerRetry < _serverRetries) + || (_currentBrokerIndex < (_connectionDetails.getBrokerCount() - 1))); } public void attainedConnection() @@ -125,8 +126,6 @@ public class FailoverRoundRobinServers implements FailoverMethod return _connectionDetails.getBrokerDetails(_currentBrokerIndex); } - - public BrokerDetails getNextBrokerDetails() { if (_currentBrokerIndex == (_connectionDetails.getBrokerCount() - 1)) @@ -137,7 +136,7 @@ public class FailoverRoundRobinServers implements FailoverMethod { _currentBrokerIndex = 0; - setBroker(_connectionDetails.getBrokerDetails(_currentBrokerIndex )); + setBroker(_connectionDetails.getBrokerDetails(_currentBrokerIndex)); _logger.info("First run using " + _connectionDetails.getBrokerDetails(_currentBrokerIndex)); } @@ -151,15 +150,15 @@ public class FailoverRoundRobinServers implements FailoverMethod else { _currentCycleRetries++; - //failed to connect to first broker + // failed to connect to first broker _currentBrokerIndex = 0; - setBroker(_connectionDetails.getBrokerDetails(_currentBrokerIndex )); + setBroker(_connectionDetails.getBrokerDetails(_currentBrokerIndex)); // This is zero rather than -1 as we are already retrieving the details. _currentServerRetry = 0; } - //else - should force client to stop as max retries has been reached. + // else - should force client to stop as max retries has been reached. } else { @@ -169,7 +168,7 @@ public class FailoverRoundRobinServers implements FailoverMethod { _currentBrokerIndex = 0; - setBroker(_connectionDetails.getBrokerDetails(_currentBrokerIndex )); + setBroker(_connectionDetails.getBrokerDetails(_currentBrokerIndex)); _logger.info("First run using " + _connectionDetails.getBrokerDetails(_currentBrokerIndex)); } @@ -177,13 +176,14 @@ public class FailoverRoundRobinServers implements FailoverMethod { _logger.info("Retrying " + _connectionDetails.getBrokerDetails(_currentBrokerIndex)); } + _currentServerRetry++; } else { _currentBrokerIndex++; - setBroker(_connectionDetails.getBrokerDetails(_currentBrokerIndex )); + setBroker(_connectionDetails.getBrokerDetails(_currentBrokerIndex)); // This is zero rather than -1 as we are already retrieving the details. _currentServerRetry = 0; } @@ -192,7 +192,6 @@ public class FailoverRoundRobinServers implements FailoverMethod return _connectionDetails.getBrokerDetails(_currentBrokerIndex); } - public void setBroker(BrokerDetails broker) { @@ -246,12 +245,13 @@ public class FailoverRoundRobinServers implements FailoverMethod sb.append(_currentBrokerIndex); sb.append("\n"); - for(int i=0; i < _connectionDetails.getBrokerCount() ; i++) + for (int i = 0; i < _connectionDetails.getBrokerCount(); i++) { if (i == _currentBrokerIndex) { sb.append(">"); } + sb.append(_connectionDetails.getBrokerDetails(i)); sb.append("\n"); } diff --git a/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java b/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java index 4f6f1561b6..a46c7f3cd5 100644 --- a/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java +++ b/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,38 +20,40 @@ */ package org.apache.qpid.jndi; -import java.io.BufferedInputStream; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.ConcurrentHashMap; - -import javax.jms.ConnectionFactory; -import javax.jms.Destination; -import javax.jms.Queue; -import javax.jms.Topic; -import javax.naming.Context; -import javax.naming.NamingException; -import javax.naming.spi.InitialContextFactory; - -import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnectionFactory; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQHeadersExchange; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQTopic; +import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.url.AMQBindingURL; import org.apache.qpid.url.BindingURL; import org.apache.qpid.url.URLSyntaxException; -import org.apache.qpid.exchange.ExchangeDefaults; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.ConnectionFactory; +import javax.jms.Destination; +import javax.jms.Queue; +import javax.jms.Topic; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.naming.spi.InitialContextFactory; + +import java.io.BufferedInputStream; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.ConcurrentHashMap; public class PropertiesFileInitialContextFactory implements InitialContextFactory { - protected final Logger _logger = Logger.getLogger(PropertiesFileInitialContextFactory.class); + protected final Logger _logger = LoggerFactory.getLogger(PropertiesFileInitialContextFactory.class); private String CONNECTION_FACTORY_PREFIX = "connectionfactory."; private String DESTINATION_PREFIX = "destination."; @@ -78,7 +80,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor if (file != null) { _logger.info("Loading Properties from:" + file); - //Load the properties specified + // Load the properties specified Properties p = new Properties(); p.load(new BufferedInputStream(new FileInputStream(file))); @@ -93,8 +95,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor } catch (IOException ioe) { - _logger.warn("Unable to load property file specified in Provider_URL:" + - environment.get(Context.PROVIDER_URL)); + _logger.warn("Unable to load property file specified in Provider_URL:" + environment.get(Context.PROVIDER_URL)); } createConnectionFactories(data, environment); @@ -109,7 +110,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor } // Implementation methods - //------------------------------------------------------------------------- + // ------------------------------------------------------------------------- protected ReadOnlyContext createContext(Map data, Hashtable environment) { return new ReadOnlyContext(environment, data); @@ -200,6 +201,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor { _logger.warn("Unable to createFactories:" + urlse); } + return null; } @@ -216,6 +218,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor catch (URLSyntaxException urlse) { _logger.warn("Unable to destination:" + urlse); + return null; } @@ -226,6 +229,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor catch (IllegalArgumentException iaw) { _logger.warn("Binding: '" + binding + "' not supported"); + return null; } } @@ -235,17 +239,15 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor */ protected Queue createQueue(Object value) { - if(value instanceof AMQShortString) + if (value instanceof AMQShortString) { return new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, (AMQShortString) value); } else if (value instanceof String) - { return new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, new AMQShortString((String) value)); } else if (value instanceof BindingURL) - { return new AMQQueue((BindingURL) value); } @@ -258,16 +260,15 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor */ protected Topic createTopic(Object value) { - if(value instanceof AMQShortString) + if (value instanceof AMQShortString) { - return new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, (AMQShortString)value); + return new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, (AMQShortString) value); } else if (value instanceof String) { return new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, new AMQShortString((String) value)); } else if (value instanceof BindingURL) - { return new AMQTopic((BindingURL) value); } @@ -293,7 +294,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor } // Properties - //------------------------------------------------------------------------- + // ------------------------------------------------------------------------- public String getConnectionPrefix() { return CONNECTION_FACTORY_PREFIX; diff --git a/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java b/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java index 1d85ea47fd..7cca22de6c 100644 --- a/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java +++ b/java/client/src/test/java/org/apache/qpid/client/DispatcherTest.java @@ -20,9 +20,13 @@ */ package org.apache.qpid.client; -import java.util.Hashtable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import junit.framework.TestCase; + +import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.Connection; import javax.jms.ConnectionFactory; @@ -36,11 +40,9 @@ import javax.jms.Session; import javax.naming.Context; import javax.naming.spi.InitialContextFactory; -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; +import java.util.Hashtable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery queue @@ -56,7 +58,7 @@ import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; */ public class DispatcherTest extends TestCase { - private static final Logger _logger = Logger.getLogger(DispatcherTest.class); + private static final Logger _logger = LoggerFactory.getLogger(DispatcherTest.class); Context _context; @@ -68,8 +70,8 @@ public class DispatcherTest extends TestCase MessageProducer _producer; Session _clientSession, _producerSession; - private final CountDownLatch _allFirstMessagesSent = new CountDownLatch(1); //all messages Sent Lock - private final CountDownLatch _allSecondMessagesSent = new CountDownLatch(1); //all messages Sent Lock + private final CountDownLatch _allFirstMessagesSent = new CountDownLatch(1); // all messages Sent Lock + private final CountDownLatch _allSecondMessagesSent = new CountDownLatch(1); // all messages Sent Lock private volatile boolean _connectionStopped = false; @@ -89,14 +91,14 @@ public class DispatcherTest extends TestCase Queue queue = (Queue) _context.lookup("queue"); - //Create Client 1 + // Create Client 1 _clientConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection(); _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); _consumer = _clientSession.createConsumer(queue); - //Create Producer + // Create Producer _producerConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection(); _producerConnection.start(); @@ -109,7 +111,6 @@ public class DispatcherTest extends TestCase { _producer.send(_producerSession.createTextMessage("Message " + msg)); } - } protected void tearDown() throws Exception @@ -122,67 +123,63 @@ public class DispatcherTest extends TestCase TransportConnection.killAllVMBrokers(); } - public void testAsynchronousRecieve() { - _logger.info("Test Start"); - assertTrue(!((AMQConnection) _clientConnection).started()); - //Set default Message Listener + // Set default Message Listener try { _consumer.setMessageListener(new MessageListener() - { - public void onMessage(Message message) { - _logger.info("Client 1 ML 1 Received Message(" + _receivedCount + "):" + message); + public void onMessage(Message message) + { + _logger.info("Client 1 ML 1 Received Message(" + _receivedCount + "):" + message); - _receivedCount++; + _receivedCount++; - if (_receivedCount == MSG_COUNT) - { - _allFirstMessagesSent.countDown(); - } + if (_receivedCount == MSG_COUNT) + { + _allFirstMessagesSent.countDown(); + } - if (_connectionStopped) - { - _logger.info("Running with Message:" + _receivedCount); - } + if (_connectionStopped) + { + _logger.info("Running with Message:" + _receivedCount); + } - if (_connectionStopped && _allFirstMessagesSent.getCount() == 0) - { - _receivedCountWhileStopped++; - } + if (_connectionStopped && (_allFirstMessagesSent.getCount() == 0)) + { + _receivedCountWhileStopped++; + } - if (_allFirstMessagesSent.getCount() == 0) - { - if (_receivedCount == MSG_COUNT * 2) + if (_allFirstMessagesSent.getCount() == 0) { - _allSecondMessagesSent.countDown(); + if (_receivedCount == (MSG_COUNT * 2)) + { + _allSecondMessagesSent.countDown(); + } } } - } - }); - + }); + assertTrue("Connecion should not be started", !((AMQConnection) _clientConnection).started()); - _clientConnection.start(); + _clientConnection.start(); } catch (JMSException e) { _logger.error("Error Setting Default ML on consumer1"); } - try { _allFirstMessagesSent.await(1000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { - //do nothing + // do nothing } try @@ -196,7 +193,6 @@ public class DispatcherTest extends TestCase _logger.error("Error stopping connection"); } - try { _logger.error("Send additional messages"); @@ -211,14 +207,13 @@ public class DispatcherTest extends TestCase _logger.error("Unable to send additional messages", e); } - try { Thread.sleep(1000); } catch (InterruptedException e) { - //ignore + // ignore } try @@ -233,7 +228,6 @@ public class DispatcherTest extends TestCase _logger.error("Error Setting Better ML on consumer1", e); } - _logger.info("Waiting upto 2 seconds for messages"); try @@ -242,17 +236,15 @@ public class DispatcherTest extends TestCase } catch (InterruptedException e) { - //do nothing + // do nothing } assertEquals("Messages not received correctly", 0, _allFirstMessagesSent.getCount()); assertEquals("Messages not received correctly", 0, _allSecondMessagesSent.getCount()); assertEquals("Client didn't get all messages", MSG_COUNT * 2, _receivedCount); assertEquals("Messages received while stopped is not 0", 0, _receivedCountWhileStopped); - } - public static junit.framework.Test suite() { return new junit.framework.TestSuite(DispatcherTest.class); diff --git a/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java b/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java index 9e48914431..7461f6c200 100644 --- a/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java +++ b/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerImmediatePrefetch.java @@ -20,27 +20,6 @@ */ package org.apache.qpid.client; -import java.util.Hashtable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import javax.jms.Connection; -import javax.jms.ConnectionFactory; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Queue; -import javax.jms.Session; -import javax.naming.Context; -import javax.naming.spi.InitialContextFactory; - -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; - /** * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery * queue <p/> The message delivery process: Mina puts a message on _queue in AMQSession and the dispatcher thread @@ -52,17 +31,12 @@ import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; */ public class MessageListenerMultiConsumerImmediatePrefetch extends MessageListenerMultiConsumerTest { - - protected void setUp() throws Exception { - System.setProperty(AMQSession.IMMEDIATE_PREFETCH, "true"); super.setUp(); - } - public static junit.framework.Test suite() { return new junit.framework.TestSuite(MessageListenerMultiConsumerImmediatePrefetch.class); diff --git a/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java b/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java index c9407d8ff6..20632e245f 100644 --- a/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java +++ b/java/client/src/test/java/org/apache/qpid/client/MessageListenerMultiConsumerTest.java @@ -20,9 +20,13 @@ */ package org.apache.qpid.client; -import java.util.Hashtable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import junit.framework.TestCase; + +import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.Connection; import javax.jms.ConnectionFactory; @@ -35,11 +39,9 @@ import javax.jms.Session; import javax.naming.Context; import javax.naming.spi.InitialContextFactory; -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; +import java.util.Hashtable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery @@ -52,7 +54,7 @@ import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; */ public class MessageListenerMultiConsumerTest extends TestCase { - private static final Logger _logger = Logger.getLogger(MessageListenerMultiConsumerTest.class); + private static final Logger _logger = LoggerFactory.getLogger(MessageListenerMultiConsumerTest.class); Context _context; @@ -64,8 +66,7 @@ public class MessageListenerMultiConsumerTest extends TestCase private MessageConsumer _consumer2; private Session _clientSession1; private Queue _queue; - private final CountDownLatch _allMessagesSent = new CountDownLatch(2); //all messages Sent Lock - + private final CountDownLatch _allMessagesSent = new CountDownLatch(2); // all messages Sent Lock protected void setUp() throws Exception { @@ -77,13 +78,13 @@ public class MessageListenerMultiConsumerTest extends TestCase Hashtable<String, String> env = new Hashtable<String, String>(); env.put("connectionfactory.connection", "amqp://guest:guest@MLT_ID/test?brokerlist='vm://:1'"); - env.put("queue.queue", "direct://amq.direct//"+this.getClass().getName()); + env.put("queue.queue", "direct://amq.direct//" + this.getClass().getName()); _context = factory.getInitialContext(env); _queue = (Queue) _context.lookup("queue"); - //Create Client 1 + // Create Client 1 _clientConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection(); _clientConnection.start(); @@ -92,17 +93,16 @@ public class MessageListenerMultiConsumerTest extends TestCase _consumer1 = _clientSession1.createConsumer(_queue); - //Create Client 2 + // Create Client 2 Session clientSession2 = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); _consumer2 = clientSession2.createConsumer(_queue); - //Create Producer + // Create Producer Connection producerConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection(); producerConnection.start(); - Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); MessageProducer producer = producerSession.createProducer(_queue); @@ -124,18 +124,18 @@ public class MessageListenerMultiConsumerTest extends TestCase TransportConnection.killAllVMBrokers(); } - public void testRecieveInterleaved() throws Exception { int msg = 0; int MAX_LOOPS = MSG_COUNT * 2; - for (int loops = 0; msg < MSG_COUNT || loops < MAX_LOOPS; loops++) + for (int loops = 0; (msg < MSG_COUNT) || (loops < MAX_LOOPS); loops++) { if (_consumer1.receive(100) != null) { msg++; } + if (_consumer2.receive(100) != null) { msg++; @@ -145,39 +145,37 @@ public class MessageListenerMultiConsumerTest extends TestCase assertEquals("Not all messages received.", MSG_COUNT, msg); } - public void testAsynchronousRecieve() throws Exception { _consumer1.setMessageListener(new MessageListener() - { - public void onMessage(Message message) { - _logger.info("Client 1 Received Message(" + receivedCount1 + "):" + message); + public void onMessage(Message message) + { + _logger.info("Client 1 Received Message(" + receivedCount1 + "):" + message); - receivedCount1++; + receivedCount1++; - if (receivedCount1 == MSG_COUNT / 2) - { - _allMessagesSent.countDown(); - } + if (receivedCount1 == (MSG_COUNT / 2)) + { + _allMessagesSent.countDown(); + } - } - }); + } + }); _consumer2.setMessageListener(new MessageListener() - { - public void onMessage(Message message) { - _logger.info("Client 2 Received Message(" + receivedCount2 + "):" + message); - - receivedCount2++; - if (receivedCount2 == MSG_COUNT / 2) + public void onMessage(Message message) { - _allMessagesSent.countDown(); - } - } - }); + _logger.info("Client 2 Received Message(" + receivedCount2 + "):" + message); + receivedCount2++; + if (receivedCount2 == (MSG_COUNT / 2)) + { + _allMessagesSent.countDown(); + } + } + }); _logger.info("Waiting upto 2 seconds for messages"); @@ -187,7 +185,7 @@ public class MessageListenerMultiConsumerTest extends TestCase } catch (InterruptedException e) { - //do nothing + // do nothing } assertEquals(MSG_COUNT, receivedCount1 + receivedCount2); @@ -195,34 +193,37 @@ public class MessageListenerMultiConsumerTest extends TestCase public void testRecieveC2Only() throws Exception { - if (!Boolean.parseBoolean(System.getProperties(). - getProperty(AMQSession.IMMEDIATE_PREFETCH, AMQSession.IMMEDIATE_PREFETCH_DEFAULT))) + if ( + !Boolean.parseBoolean( + System.getProperties().getProperty(AMQSession.IMMEDIATE_PREFETCH, + AMQSession.IMMEDIATE_PREFETCH_DEFAULT))) { _logger.info("Performing Receive only on C2"); for (int msg = 0; msg < MSG_COUNT; msg++) { - assertTrue(MSG_COUNT + " msg should be received. Only received:" + msg, - _consumer2.receive(1000) != null); + assertTrue(MSG_COUNT + " msg should be received. Only received:" + msg, _consumer2.receive(1000) != null); } } } public void testRecieveBoth() throws Exception { - if (!Boolean.parseBoolean(System.getProperties(). - getProperty(AMQSession.IMMEDIATE_PREFETCH, AMQSession.IMMEDIATE_PREFETCH_DEFAULT))) + if ( + !Boolean.parseBoolean( + System.getProperties().getProperty(AMQSession.IMMEDIATE_PREFETCH, + AMQSession.IMMEDIATE_PREFETCH_DEFAULT))) { _logger.info("Performing Receive only with two consumers on one session "); MessageConsumer consumer2 = _clientSession1.createConsumer(_queue); - for (int msg = 0; msg < MSG_COUNT / 2; msg++) + for (int msg = 0; msg < (MSG_COUNT / 2); msg++) { assertTrue(_consumer1.receive() != null); } - for (int msg = 0; msg < MSG_COUNT / 2; msg++) + for (int msg = 0; msg < (MSG_COUNT / 2); msg++) { assertTrue(consumer2.receive() != null); } @@ -231,20 +232,19 @@ public class MessageListenerMultiConsumerTest extends TestCase { _logger.info("Performing Receive only on both C1 and C2"); - for (int msg = 0; msg < MSG_COUNT / 2; msg++) + for (int msg = 0; msg < (MSG_COUNT / 2); msg++) { assertTrue(_consumer1.receive() != null); } - for (int msg = 0; msg < MSG_COUNT / 2; msg++) + for (int msg = 0; msg < (MSG_COUNT / 2); msg++) { assertTrue(_consumer2.receive() != null); } } } - public static junit.framework.Test suite() { return new junit.framework.TestSuite(MessageListenerMultiConsumerTest.class); diff --git a/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java b/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java index b15742f3aa..87630fad5b 100644 --- a/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java +++ b/java/client/src/test/java/org/apache/qpid/client/MessageListenerTest.java @@ -14,15 +14,19 @@ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations - * under the License. + * under the License. + * * - * */ package org.apache.qpid.client; -import java.util.Hashtable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import junit.framework.TestCase; + +import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.Connection; import javax.jms.ConnectionFactory; @@ -35,13 +39,9 @@ import javax.jms.Session; import javax.naming.Context; import javax.naming.spi.InitialContextFactory; -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; -import org.apache.qpid.url.BindingURL; -import org.apache.qpid.url.AMQBindingURL; +import java.util.Hashtable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery @@ -54,7 +54,7 @@ import org.apache.qpid.url.AMQBindingURL; */ public class MessageListenerTest extends TestCase implements MessageListener { - private static final Logger _logger = Logger.getLogger(MessageListenerTest.class); + private static final Logger _logger = LoggerFactory.getLogger(MessageListenerTest.class); Context _context; @@ -73,6 +73,7 @@ public class MessageListenerTest extends TestCase implements MessageListener { TransportConnection.createVMBroker(1); } + InitialContextFactory factory = new PropertiesFileInitialContextFactory(); Hashtable<String, String> env = new Hashtable<String, String>(); @@ -84,7 +85,7 @@ public class MessageListenerTest extends TestCase implements MessageListener Queue queue = (Queue) _context.lookup("queue"); - //Create Client + // Create Client _clientConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection(); _clientConnection.start(); @@ -93,7 +94,7 @@ public class MessageListenerTest extends TestCase implements MessageListener _consumer = clientSession.createConsumer(queue); - //Create Producer + // Create Producer Connection producerConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection(); @@ -123,7 +124,6 @@ public class MessageListenerTest extends TestCase implements MessageListener } } - public void testSynchronousRecieve() throws Exception { for (int msg = 0; msg < MSG_COUNT; msg++) @@ -144,9 +144,9 @@ public class MessageListenerTest extends TestCase implements MessageListener } catch (InterruptedException e) { - //do nothing + // do nothing } - //Should have recieved all async messages + // Should have recieved all async messages assertEquals(MSG_COUNT, receivedCount); } @@ -156,11 +156,11 @@ public class MessageListenerTest extends TestCase implements MessageListener _logger.error("Test disabled as initial receive is not called first"); // Perform initial receive to start connection -// assertTrue(_consumer.receive(2000) != null); -// receivedCount++; + // assertTrue(_consumer.receive(2000) != null); + // receivedCount++; // Sleep to ensure remaining 4 msgs end up on _synchronousQueue -// Thread.sleep(1000); + // Thread.sleep(1000); // Set the message listener and wait for the messages to come in. _consumer.setMessageListener(this); @@ -173,14 +173,13 @@ public class MessageListenerTest extends TestCase implements MessageListener } catch (InterruptedException e) { - //do nothing + // do nothing } - //Should have recieved all async messages + // Should have recieved all async messages assertEquals(MSG_COUNT, receivedCount); } - public void onMessage(Message message) { _logger.info("Received Message(" + receivedCount + "):" + message); diff --git a/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java b/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java index 97fbf9876f..5f7ca69554 100644 --- a/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java +++ b/java/client/src/test/java/org/apache/qpid/client/ResetMessageListenerTest.java @@ -20,9 +20,13 @@ */ package org.apache.qpid.client; -import java.util.Hashtable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; +import junit.framework.TestCase; + +import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.Connection; import javax.jms.ConnectionFactory; @@ -36,11 +40,9 @@ import javax.jms.Session; import javax.naming.Context; import javax.naming.spi.InitialContextFactory; -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; +import java.util.Hashtable; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; /** * QPID-293 Setting MessageListener after connection has started can cause messages to be "lost" on a internal delivery @@ -53,7 +55,7 @@ import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; */ public class ResetMessageListenerTest extends TestCase { - private static final Logger _logger = Logger.getLogger(ResetMessageListenerTest.class); + private static final Logger _logger = LoggerFactory.getLogger(ResetMessageListenerTest.class); Context _context; @@ -67,8 +69,8 @@ public class ResetMessageListenerTest extends TestCase MessageProducer _producer; Session _clientSession, _producerSession; - private final CountDownLatch _allFirstMessagesSent = new CountDownLatch(2); //all messages Sent Lock - private final CountDownLatch _allSecondMessagesSent = new CountDownLatch(2); //all messages Sent Lock + private final CountDownLatch _allFirstMessagesSent = new CountDownLatch(2); // all messages Sent Lock + private final CountDownLatch _allSecondMessagesSent = new CountDownLatch(2); // all messages Sent Lock protected void setUp() throws Exception { @@ -88,17 +90,17 @@ public class ResetMessageListenerTest extends TestCase Queue queue = (Queue) _context.lookup("queue"); - //Create Client 1 + // Create Client 1 _clientConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection(); _clientSession = _clientConnection.createSession(false, Session.AUTO_ACKNOWLEDGE); _consumer1 = _clientSession.createConsumer(queue); - //Create Client 2 on same session + // Create Client 2 on same session _consumer2 = _clientSession.createConsumer(queue); - //Create Producer + // Create Producer _producerConnection = ((ConnectionFactory) _context.lookup("connection")).createConnection(); _producerConnection.start(); @@ -129,57 +131,55 @@ public class ResetMessageListenerTest extends TestCase TransportConnection.killAllVMBrokers(); } - public void testAsynchronousRecieve() { _logger.info("Test Start"); - //Set default Message Listener + // Set default Message Listener try { _consumer1.setMessageListener(new MessageListener() - { - public void onMessage(Message message) { - _logger.info("Client 1 ML 1 Received Message(" + receivedCount1ML1 + "):" + message); - - receivedCount1ML1++; - if (receivedCount1ML1 == MSG_COUNT / 2) + public void onMessage(Message message) { - _allFirstMessagesSent.countDown(); + _logger.info("Client 1 ML 1 Received Message(" + receivedCount1ML1 + "):" + message); + + receivedCount1ML1++; + if (receivedCount1ML1 == (MSG_COUNT / 2)) + { + _allFirstMessagesSent.countDown(); + } } - } - }); + }); } catch (JMSException e) { _logger.error("Error Setting Default ML on consumer1"); } - try { _consumer2.setMessageListener(new MessageListener() - { - public void onMessage(Message message) { - _logger.info("Client 2 Received Message(" + receivedCount2 + "):" + message); - - receivedCount2++; - if (receivedCount2 == MSG_COUNT / 2) + public void onMessage(Message message) { - _logger.info("Client 2 received all its messages1"); - _allFirstMessagesSent.countDown(); + _logger.info("Client 2 Received Message(" + receivedCount2 + "):" + message); + + receivedCount2++; + if (receivedCount2 == (MSG_COUNT / 2)) + { + _logger.info("Client 2 received all its messages1"); + _allFirstMessagesSent.countDown(); + } + + if (receivedCount2 == MSG_COUNT) + { + _logger.info("Client 2 received all its messages2"); + _allSecondMessagesSent.countDown(); + } } - - if (receivedCount2 == MSG_COUNT) - { - _logger.info("Client 2 received all its messages2"); - _allSecondMessagesSent.countDown(); - } - } - }); + }); _clientConnection.start(); } @@ -189,7 +189,6 @@ public class ResetMessageListenerTest extends TestCase } - try { _allFirstMessagesSent.await(1000, TimeUnit.MILLISECONDS); @@ -197,7 +196,7 @@ public class ResetMessageListenerTest extends TestCase } catch (InterruptedException e) { - //do nothing + // do nothing } try @@ -213,18 +212,18 @@ public class ResetMessageListenerTest extends TestCase try { _consumer1.setMessageListener(new MessageListener() - { - public void onMessage(Message message) { - _logger.info("Client 1 ML2 Received Message(" + receivedCount1ML1 + "):" + message); - - receivedCount1ML2++; - if (receivedCount1ML2 == MSG_COUNT / 2) + public void onMessage(Message message) { - _allSecondMessagesSent.countDown(); + _logger.info("Client 1 ML2 Received Message(" + receivedCount1ML1 + "):" + message); + + receivedCount1ML2++; + if (receivedCount1ML2 == (MSG_COUNT / 2)) + { + _allSecondMessagesSent.countDown(); + } } - } - }); + }); _clientConnection.start(); } @@ -260,11 +259,10 @@ public class ResetMessageListenerTest extends TestCase } catch (InterruptedException e) { - //do nothing + // do nothing } } - public static junit.framework.Test suite() { return new junit.framework.TestSuite(ResetMessageListenerTest.class); 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 4667a2b3fa..b6f46b4acc 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 @@ -19,32 +19,30 @@ */ package org.apache.qpid.test.unit.ack; -import java.util.concurrent.atomic.AtomicInteger; +import junit.framework.TestCase; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.jms.Session; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; - import javax.jms.TextMessage; -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.jms.Session; +import java.util.concurrent.atomic.AtomicInteger; public class RecoverTest extends TestCase { - private static final Logger _logger = Logger.getLogger(RecoverTest.class); + private static final Logger _logger = LoggerFactory.getLogger(RecoverTest.class); private Exception _error; private AtomicInteger count; @@ -64,16 +62,17 @@ public class RecoverTest extends TestCase count = null; } - public void testRecoverResendsMsgs() throws Exception { AMQConnection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "test"); Session consumerSession = con.createSession(false, Session.CLIENT_ACKNOWLEDGE); - Queue queue = new AMQQueue(consumerSession.getDefaultQueueExchangeName(),new AMQShortString("someQ"), new AMQShortString("someQ"), false, true); + Queue queue = + new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("someQ"), + new AMQShortString("someQ"), false, true); MessageConsumer consumer = consumerSession.createConsumer(queue); - //force synch to ensure the consumer has resulted in a bound queue - //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.DIRECT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS); + // force synch to ensure the consumer has resulted in a bound queue + // ((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.DIRECT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS); // This is the default now AMQConnection con2 = new AMQConnection("vm://:1", "guest", "guest", "producer1", "test"); @@ -122,16 +121,17 @@ public class RecoverTest extends TestCase con.close(); } - public void testRecoverResendsMsgsAckOnEarlier() throws Exception { AMQConnection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "test"); Session consumerSession = con.createSession(false, Session.CLIENT_ACKNOWLEDGE); - Queue queue = new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("someQ"), new AMQShortString("someQ"), false, true); + Queue queue = + new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("someQ"), + new AMQShortString("someQ"), false, true); MessageConsumer consumer = consumerSession.createConsumer(queue); - //force synch to ensure the consumer has resulted in a bound queue - //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.DIRECT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS); + // force synch to ensure the consumer has resulted in a bound queue + // ((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.DIRECT_EXCHANGE_NAME, ExchangeDefaults.DIRECT_EXCHANGE_CLASS); // This is the default now AMQConnection con2 = new AMQConnection("vm://:1", "guest", "guest", "producer1", "test"); @@ -164,7 +164,6 @@ public class RecoverTest extends TestCase TextMessage tm4 = (TextMessage) consumer.receive(3000); assertEquals("msg4", tm4.getText()); - _logger.info("Received redelivery of two messages. calling acknolwedgeThis() first of those message"); ((org.apache.qpid.jms.Message) tm3).acknowledgeThis(); @@ -180,7 +179,6 @@ public class RecoverTest extends TestCase // all acked so no messages to be delivered consumerSession.recover(); - tm = (TextMessage) consumer.receiveNoWait(); assertNull(tm); _logger.info("No messages redelivered as is expected"); @@ -193,8 +191,12 @@ public class RecoverTest extends TestCase AMQConnection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "test"); Session consumerSession = con.createSession(false, Session.CLIENT_ACKNOWLEDGE); - Queue queue = new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q1"), new AMQShortString("Q1"), false, true); - Queue queue2 = new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q2"), new AMQShortString("Q2"), false, true); + Queue queue = + new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q1"), new AMQShortString("Q1"), + false, true); + Queue queue2 = + new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q2"), new AMQShortString("Q2"), + false, true); MessageConsumer consumer = consumerSession.createConsumer(queue); MessageConsumer consumer2 = consumerSession.createConsumer(queue2); @@ -232,68 +234,72 @@ public class RecoverTest extends TestCase AMQConnection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "test"); final Session consumerSession = con.createSession(false, Session.AUTO_ACKNOWLEDGE); - Queue queue = new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q3"), new AMQShortString("Q3"), false, true); + Queue queue = + new AMQQueue(consumerSession.getDefaultQueueExchangeName(), new AMQShortString("Q3"), new AMQShortString("Q3"), + false, true); MessageConsumer consumer = consumerSession.createConsumer(queue); MessageProducer producer = consumerSession.createProducer(queue); producer.send(consumerSession.createTextMessage("hello")); - final Object lock = new Object(); consumer.setMessageListener(new MessageListener() - { - - - - public void onMessage(Message message) { - try + + public void onMessage(Message message) { - count.incrementAndGet(); - if (count.get() == 1) + try { - if(message.getJMSRedelivered()) + count.incrementAndGet(); + if (count.get() == 1) { - setError(new Exception("Message marked as redilvered on what should be first delivery attempt")); + if (message.getJMSRedelivered()) + { + setError( + new Exception("Message marked as redilvered on what should be first delivery attempt")); + } + + consumerSession.recover(); } - consumerSession.recover(); - } - else if (count.get() == 2) - { - if(!message.getJMSRedelivered()) + else if (count.get() == 2) { - setError(new Exception("Message not marked as redilvered on what should be second delivery attempt")); + if (!message.getJMSRedelivered()) + { + setError( + new Exception( + "Message not marked as redilvered on what should be second delivery attempt")); + } + } + else + { + System.err.println(message); + fail("Message delivered too many times!: " + count); } } - else + catch (JMSException e) { - System.err.println(message); - fail("Message delivered too many times!: " + count); + _logger.error("Error recovering session: " + e, e); + setError(e); + } + + synchronized (lock) + { + lock.notify(); } } - catch (JMSException e) - { - _logger.error("Error recovering session: " + e, e); - setError(e); - } - synchronized(lock) - { - lock.notify(); - } - } - }); + }); con.start(); long waitTime = 300000L; long waitUntilTime = System.currentTimeMillis() + waitTime; - synchronized(lock) + synchronized (lock) { - while((count.get() <= 1) && (waitTime > 0)) + while ((count.get() <= 1) && (waitTime > 0)) { lock.wait(waitTime); - if(count.get() <= 1) + if (count.get() <= 1) { waitTime = waitUntilTime - System.currentTimeMillis(); } @@ -302,15 +308,16 @@ public class RecoverTest extends TestCase Thread.sleep(1000); - if(count.get() != 2) + if (count.get() != 2) { System.err.println("Count != 2 : " + count); } - assertTrue(count.get() == 2); + + assertTrue(count.get() == 2); con.close(); - if(_error != null) + if (_error != null) { throw _error; } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java index a350330c71..da1b46ee2c 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/BytesMessageTest.java @@ -6,9 +6,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -19,9 +19,20 @@ */ package org.apache.qpid.test.unit.basic; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.mina.common.ByteBuffer; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.message.JMSBytesMessage; +import org.apache.qpid.testutil.VMBrokerSetup; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.BytesMessage; import javax.jms.Connection; @@ -34,21 +45,13 @@ import javax.jms.MessageNotWriteableException; import javax.jms.MessageProducer; import javax.jms.Session; -import junit.framework.Assert; -import junit.framework.TestCase; - -import org.apache.mina.common.ByteBuffer; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.message.JMSBytesMessage; -import org.apache.qpid.testutil.VMBrokerSetup; -import org.apache.log4j.Logger; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; public class BytesMessageTest extends TestCase implements MessageListener { - private static final Logger _logger = Logger.getLogger(BytesMessageTest.class); + private static final Logger _logger = LoggerFactory.getLogger(BytesMessageTest.class); private Connection _connection; private Destination _destination; @@ -102,7 +105,7 @@ public class BytesMessageTest extends TestCase implements MessageListener void send(int count) throws JMSException { - //create a publisher + // create a publisher MessageProducer producer = _session.createProducer(_destination); for (int i = 0; i < count; i++) { @@ -115,7 +118,7 @@ public class BytesMessageTest extends TestCase implements MessageListener } catch (MessageNotReadableException mnwe) { - //normal execution + // normal execution } byte[] data = ("Message " + i).getBytes(); @@ -127,7 +130,7 @@ public class BytesMessageTest extends TestCase implements MessageListener void waitFor(int count) throws InterruptedException { - synchronized(received) + synchronized (received) { while (received.size() < count) { @@ -146,8 +149,7 @@ public class BytesMessageTest extends TestCase implements MessageListener buffer.get(data); actual.add(data); - - //Check Body Write Status + // Check Body Write Status try { m.writeBoolean(true); @@ -155,7 +157,7 @@ public class BytesMessageTest extends TestCase implements MessageListener } catch (MessageNotWriteableException mnwe) { - //normal execution + // normal execution } m.clearBody(); @@ -169,8 +171,7 @@ public class BytesMessageTest extends TestCase implements MessageListener Assert.fail("Message should be writeable"); } - - //Check property write status + // Check property write status try { m.setStringProperty("test", "test"); @@ -178,7 +179,7 @@ public class BytesMessageTest extends TestCase implements MessageListener } catch (MessageNotWriteableException mnwe) { - //normal execution + // normal execution } m.clearProperties(); @@ -219,6 +220,7 @@ public class BytesMessageTest extends TestCase implements MessageListener { errors.add("Found " + actual.next() + " but no more expected values."); } + if (!errors.isEmpty()) { throw new RuntimeException(errors.toString()); @@ -231,6 +233,7 @@ public class BytesMessageTest extends TestCase implements MessageListener { throw new RuntimeException("Expected length " + expected.length + " got " + actual.length); } + for (int i = 0; i < expected.length; i++) { if (expected[i] != actual[i]) @@ -242,7 +245,7 @@ public class BytesMessageTest extends TestCase implements MessageListener public void onMessage(Message message) { - synchronized(received) + synchronized (received) { received.add((JMSBytesMessage) message); received.notify(); diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java index 9e2918770a..aff496becf 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,19 +20,10 @@ */ package org.apache.qpid.test.unit.basic; -import java.io.IOException; -import java.util.ArrayList; - -import javax.jms.BytesMessage; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; - import junit.framework.TestCase; -import org.apache.log4j.Logger; import org.apache.mina.common.ByteBuffer; + import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQQueue; @@ -43,10 +34,21 @@ import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.FieldTableFactory; import org.apache.qpid.testutil.VMBrokerSetup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.BytesMessage; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; + +import java.io.IOException; +import java.util.ArrayList; + public class FieldTableMessageTest extends TestCase implements MessageListener { - - private static final Logger _logger = Logger.getLogger(FieldTableMessageTest.class); + private static final Logger _logger = LoggerFactory.getLogger(FieldTableMessageTest.class); private AMQConnection _connection; private AMQDestination _destination; @@ -67,10 +69,9 @@ public class FieldTableMessageTest extends TestCase implements MessageListener super.tearDown(); } - private void init(AMQConnection connection) throws Exception { - init(connection, new AMQQueue(connection,randomize("FieldTableMessageTest"), true)); + init(connection, new AMQQueue(connection, randomize("FieldTableMessageTest"), true)); } private void init(AMQConnection connection, AMQDestination destination) throws Exception @@ -79,11 +80,11 @@ public class FieldTableMessageTest extends TestCase implements MessageListener _destination = destination; _session = (AMQSession) connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); - //set up a slow consumer + // set up a slow consumer _session.createConsumer(destination).setMessageListener(this); connection.start(); - //_expected = new FieldTableTest().load("FieldTableTest2.properties"); + // _expected = new FieldTableTest().load("FieldTableTest2.properties"); _expected = load(); } @@ -111,7 +112,7 @@ public class FieldTableMessageTest extends TestCase implements MessageListener void send(int count) throws JMSException, IOException { - //create a publisher + // create a publisher MessageProducer producer = _session.createProducer(_destination); for (int i = 0; i < count; i++) { @@ -123,7 +124,7 @@ public class FieldTableMessageTest extends TestCase implements MessageListener void waitFor(int count) throws InterruptedException { - synchronized(received) + synchronized (received) { while (received.size() < count) { @@ -139,7 +140,7 @@ public class FieldTableMessageTest extends TestCase implements MessageListener ByteBuffer buffer = ((JMSBytesMessage) m).getData(); FieldTable actual = FieldTableFactory.newFieldTable(buffer, buffer.remaining()); for (String key : _expected.keys()) - { + { assertEquals("Values for " + key + " did not match", _expected.getObject(key), actual.getObject(key)); } } @@ -147,7 +148,7 @@ public class FieldTableMessageTest extends TestCase implements MessageListener public void onMessage(Message message) { - synchronized(received) + synchronized (received) { received.add((JMSBytesMessage) message); received.notify(); @@ -162,9 +163,9 @@ public class FieldTableMessageTest extends TestCase implements MessageListener public static void main(String[] argv) throws Exception { FieldTableMessageTest test = new FieldTableMessageTest(); - test._connectionString = argv.length == 0 ? "vm://:1" : argv[0]; + test._connectionString = (argv.length == 0) ? "vm://:1" : argv[0]; test.setUp(); - test._count = argv.length > 1 ? Integer.parseInt(argv[1]) : 5; + test._count = (argv.length > 1) ? Integer.parseInt(argv[1]) : 5; test.test(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java index 3830d61701..ffc7be82f0 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/LargeMessageTest.java @@ -14,32 +14,36 @@ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations - * under the License. + * under the License. + * * - * */ package org.apache.qpid.test.unit.basic; import junit.framework.TestCase; -import org.apache.log4j.Logger; + import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.message.JMSTextMessage; +import org.apache.qpid.client.transport.TransportConnection; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.Destination; -import javax.jms.Session; -import javax.jms.MessageConsumer; import javax.jms.JMSException; +import javax.jms.MessageConsumer; import javax.jms.MessageProducer; +import javax.jms.Session; import javax.jms.TextMessage; -import java.util.List; + import java.util.ArrayList; +import java.util.List; public class LargeMessageTest extends TestCase { - private static final Logger _logger = Logger.getLogger(LargeMessageTest.class); + private static final Logger _logger = LoggerFactory.getLogger(LargeMessageTest.class); private AMQConnection _connection; private Destination _destination; @@ -68,7 +72,7 @@ public class LargeMessageTest extends TestCase private void init(AMQConnection connection) throws Exception { - Destination destination = new AMQQueue(connection,"LargeMessageTest", true); + Destination destination = new AMQQueue(connection, "LargeMessageTest", true); init(connection, destination); } @@ -84,7 +88,7 @@ public class LargeMessageTest extends TestCase // Test boundary of 1 packet to 2 packets public void test64kminus1() { - checkLargeMessage(64 * 1024 - 1); + checkLargeMessage((64 * 1024) - 1); } public void test64k() @@ -94,13 +98,13 @@ public class LargeMessageTest extends TestCase public void test64kplus1() { - checkLargeMessage(64 * 1024 + 1); + checkLargeMessage((64 * 1024) + 1); } - //Test packet boundary of 3 packtes + // Test packet boundary of 3 packtes public void test128kminus1() { - checkLargeMessage(128 * 1024 - 1); + checkLargeMessage((128 * 1024) - 1); } public void test128k() @@ -110,7 +114,7 @@ public class LargeMessageTest extends TestCase public void test128kplus1() { - checkLargeMessage(128 * 1024 + 1); + checkLargeMessage((128 * 1024) + 1); } // Testing larger messages @@ -167,10 +171,10 @@ public class LargeMessageTest extends TestCase { builder.append(ch); - if (i % 1000 == 0) + if ((i % 1000) == 0) { ch++; - if (ch == 'z' + 1) + if (ch == ('z' + 1)) { ch = 'a'; } @@ -180,7 +184,6 @@ public class LargeMessageTest extends TestCase return builder.toString(); } - public static junit.framework.Test suite() { return new junit.framework.TestSuite(LargeMessageTest.class); diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java index 75eb3a8d5e..6708fefa86 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java @@ -20,9 +20,17 @@ */ package org.apache.qpid.test.unit.basic; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.message.JMSMapMessage; +import org.apache.qpid.client.transport.TransportConnection; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.Destination; import javax.jms.JMSException; @@ -34,20 +42,13 @@ import javax.jms.MessageNotWriteableException; import javax.jms.MessageProducer; import javax.jms.Session; -import junit.framework.Assert; -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.message.JMSMapMessage; -import org.apache.qpid.client.transport.TransportConnection; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; public class MapMessageTest extends TestCase implements MessageListener { - - private static final Logger _logger = Logger.getLogger(MapMessageTest.class); + private static final Logger _logger = LoggerFactory.getLogger(MapMessageTest.class); private AMQConnection _connection; private Destination _destination; @@ -57,7 +58,7 @@ public class MapMessageTest extends TestCase implements MessageListener private static final String MESSAGE = "Message "; private int _count = 100; public String _connectionString = "vm://:1"; - private byte[] _bytes = {99, 98, 97, 96, 95}; + private byte[] _bytes = { 99, 98, 97, 96, 95 }; private static final float _smallfloat = 100.0f; protected void setUp() throws Exception @@ -83,7 +84,7 @@ public class MapMessageTest extends TestCase implements MessageListener private void init(AMQConnection connection) throws Exception { - Destination destination = new AMQQueue(connection,randomize("MapMessageTest"), true); + Destination destination = new AMQQueue(connection, randomize("MapMessageTest"), true); init(connection, destination); } @@ -93,7 +94,7 @@ public class MapMessageTest extends TestCase implements MessageListener _destination = destination; _session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - //set up a slow consumer + // set up a slow consumer _session.createConsumer(destination).setMessageListener(this); connection.start(); } @@ -109,7 +110,7 @@ public class MapMessageTest extends TestCase implements MessageListener void send(int count) throws JMSException { - //create a publisher + // create a publisher MessageProducer producer = _session.createProducer(_destination); for (int i = 0; i < count; i++) { @@ -123,7 +124,7 @@ public class MapMessageTest extends TestCase implements MessageListener private void setMapValues(MapMessage message, int i) throws JMSException { - message.setBoolean("odd", i / 2 == 0); + message.setBoolean("odd", (i / 2) == 0); message.setByte("byte", (byte) Byte.MAX_VALUE); message.setBytes("bytes", _bytes); message.setChar("char", (char) 'c'); @@ -136,7 +137,7 @@ public class MapMessageTest extends TestCase implements MessageListener message.setShort("short", (short) Short.MAX_VALUE); message.setString("message", MESSAGE + i); - //Test Setting Object Values + // Test Setting Object Values message.setObject("object-bool", true); message.setObject("object-byte", Byte.MAX_VALUE); message.setObject("object-bytes", _bytes); @@ -147,7 +148,7 @@ public class MapMessageTest extends TestCase implements MessageListener message.setObject("object-long", Long.MAX_VALUE); message.setObject("object-short", Short.MAX_VALUE); - //Set a null String value + // Set a null String value message.setString("nullString", null); // Highlight protocol problem message.setString("emptyString", ""); @@ -159,10 +160,9 @@ public class MapMessageTest extends TestCase implements MessageListener long waitTime = 30000L; long waitUntilTime = System.currentTimeMillis() + 30000L; - - synchronized(received) + synchronized (received) { - while(received.size() < count && waitTime>0) + while ((received.size() < count) && (waitTime > 0)) { if (received.size() < count) { @@ -174,6 +174,7 @@ public class MapMessageTest extends TestCase implements MessageListener waitTime = waitUntilTime - System.currentTimeMillis(); } } + if (received.size() < count) { throw new Exception("Timed-out. Waiting for " + count + " only got " + received.size()); @@ -236,7 +237,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (NumberFormatException nfe) { - //normal execution + // normal execution } try @@ -246,10 +247,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (NumberFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getChar("message"); @@ -257,7 +258,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } try @@ -267,8 +268,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (NumberFormatException nfe) { - //normal execution + // normal execution } + try { m.getLong("message"); @@ -276,10 +278,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (NumberFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getFloat("message"); @@ -287,9 +289,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (NumberFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getDouble("message"); @@ -297,9 +299,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (NumberFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getBytes("message"); @@ -307,7 +309,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals(MESSAGE + m.getInt("messageNumber"), m.getString("message")); @@ -316,7 +318,7 @@ public class MapMessageTest extends TestCase implements MessageListener private void testShort(JMSMapMessage m) throws JMSException { - //Try bad reads + // Try bad reads try { m.getBoolean("short"); @@ -324,7 +326,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -334,12 +336,12 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals(Short.MAX_VALUE, m.getShort("short")); - //Try bad reads + // Try bad reads try { m.getChar("short"); @@ -347,14 +349,14 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } Assert.assertEquals(Short.MAX_VALUE, m.getInt("short")); Assert.assertEquals(Short.MAX_VALUE, m.getLong("short")); - //Try bad reads + // Try bad reads try { m.getFloat("short"); @@ -362,9 +364,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getDouble("short"); @@ -372,9 +374,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getBytes("short"); @@ -382,7 +384,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals("" + Short.MAX_VALUE, m.getString("short")); @@ -391,7 +393,7 @@ public class MapMessageTest extends TestCase implements MessageListener private void testLong(JMSMapMessage m) throws JMSException { - //Try bad reads + // Try bad reads try { m.getBoolean("long"); @@ -399,7 +401,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -409,7 +411,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -419,10 +421,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getChar("long"); @@ -430,7 +432,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } try @@ -440,12 +442,12 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals(Long.MAX_VALUE, m.getLong("long")); - //Try bad reads + // Try bad reads try { m.getFloat("long"); @@ -453,9 +455,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getDouble("long"); @@ -463,9 +465,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getBytes("long"); @@ -473,7 +475,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals("" + Long.MAX_VALUE, m.getString("long")); @@ -482,7 +484,7 @@ public class MapMessageTest extends TestCase implements MessageListener private void testDouble(JMSMapMessage m) throws JMSException { - //Try bad reads + // Try bad reads try { m.getBoolean("double"); @@ -490,7 +492,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -500,7 +502,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -510,10 +512,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getChar("double"); @@ -521,7 +523,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } try @@ -531,8 +533,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } + try { m.getLong("double"); @@ -540,10 +543,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getFloat("double"); @@ -551,13 +554,12 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - Assert.assertEquals(Double.MAX_VALUE, m.getDouble("double")); - //Try bad reads + // Try bad reads try { m.getBytes("double"); @@ -565,17 +567,16 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals("" + Double.MAX_VALUE, m.getString("double")); } - private void testFloat(JMSMapMessage m) throws JMSException { - //Try bad reads + // Try bad reads try { m.getBoolean("float"); @@ -583,7 +584,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -593,7 +594,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -603,10 +604,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getChar("float"); @@ -614,7 +615,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } try @@ -624,8 +625,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } + try { m.getLong("float"); @@ -633,15 +635,14 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - Assert.assertEquals(Float.MAX_VALUE, m.getFloat("float")); Assert.assertEquals(_smallfloat, (float) m.getDouble("smallfloat")); - //Try bad reads + // Try bad reads try { m.getBytes("float"); @@ -649,17 +650,16 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals("" + Float.MAX_VALUE, m.getString("float")); } - private void testInt(JMSMapMessage m) throws JMSException { - //Try bad reads + // Try bad reads try { m.getBoolean("int"); @@ -667,7 +667,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -677,7 +677,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -687,10 +687,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getChar("int"); @@ -698,14 +698,14 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } Assert.assertEquals(Integer.MAX_VALUE, m.getInt("int")); Assert.assertEquals(Integer.MAX_VALUE, (int) m.getLong("int")); - //Try bad reads + // Try bad reads try { m.getFloat("int"); @@ -713,9 +713,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getDouble("int"); @@ -723,9 +723,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getBytes("int"); @@ -733,17 +733,16 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals("" + Integer.MAX_VALUE, m.getString("int")); } - private void testChar(JMSMapMessage m) throws JMSException { - //Try bad reads + // Try bad reads try { m.getBoolean("char"); @@ -751,7 +750,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -761,7 +760,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -771,7 +770,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals('c', m.getChar("char")); @@ -783,8 +782,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } + try { m.getLong("char"); @@ -792,10 +792,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getFloat("char"); @@ -803,9 +803,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getDouble("char"); @@ -813,9 +813,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getBytes("char"); @@ -823,7 +823,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals("" + 'c', m.getString("char")); @@ -831,7 +831,7 @@ public class MapMessageTest extends TestCase implements MessageListener private void testBytes(JMSMapMessage m) throws JMSException { - //Try bad reads + // Try bad reads try { m.getBoolean("bytes"); @@ -839,7 +839,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -849,7 +849,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -859,10 +859,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getChar("bytes"); @@ -870,7 +870,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } try @@ -880,7 +880,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } try @@ -890,10 +890,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getFloat("bytes"); @@ -901,9 +901,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getDouble("bytes"); @@ -911,10 +911,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - assertBytesEqual(_bytes, m.getBytes("bytes")); try @@ -924,15 +923,14 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - } private void testByte(JMSMapMessage m) throws JMSException { - //Try bad reads + // Try bad reads try { m.getBoolean("byte"); @@ -940,14 +938,14 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals(Byte.MAX_VALUE, m.getByte("byte")); Assert.assertEquals((short) Byte.MAX_VALUE, m.getShort("byte")); - //Try bad reads + // Try bad reads try { m.getChar("byte"); @@ -955,15 +953,15 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } - //Reading a byte as an int is ok + // Reading a byte as an int is ok Assert.assertEquals((short) Byte.MAX_VALUE, m.getInt("byte")); Assert.assertEquals((short) Byte.MAX_VALUE, m.getLong("byte")); - //Try bad reads + // Try bad reads try { m.getFloat("byte"); @@ -971,9 +969,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getDouble("byte"); @@ -981,9 +979,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getBytes("byte"); @@ -991,7 +989,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals("" + Byte.MAX_VALUE, m.getString("byte")); @@ -1003,7 +1001,7 @@ public class MapMessageTest extends TestCase implements MessageListener Assert.assertEquals((m.getInt("messageNumber") / 2) == 0, m.getBoolean("odd")); - //Try bad reads + // Try bad reads try { m.getByte("odd"); @@ -1011,10 +1009,10 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getShort("odd"); @@ -1022,9 +1020,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getChar("odd"); @@ -1032,9 +1030,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException npe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getInt("odd"); @@ -1042,9 +1040,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getLong("odd"); @@ -1052,9 +1050,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getFloat("odd"); @@ -1062,9 +1060,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getDouble("odd"); @@ -1072,9 +1070,9 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } - //Try bad reads + // Try bad reads try { m.getBytes("odd"); @@ -1082,16 +1080,15 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageFormatException nfe) { - //normal execution + // normal execution } Assert.assertEquals("" + ((m.getInt("messageNumber") / 2) == 0), m.getString("odd")); } - private void testPropertyWriteStatus(JMSMapMessage m) throws JMSException { - //Check property write status + // Check property write status try { m.setStringProperty("test", "test"); @@ -1099,7 +1096,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageNotWriteableException mnwe) { - //normal execution + // normal execution } m.clearProperties(); @@ -1123,7 +1120,7 @@ public class MapMessageTest extends TestCase implements MessageListener } catch (MessageNotWriteableException mnwe) { - //normal execution + // normal execution } m.clearBody(); @@ -1138,54 +1135,51 @@ public class MapMessageTest extends TestCase implements MessageListener } } - - - private void testMapValues(JMSMapMessage m, int count) throws JMSException { - //Test get<Primiative> + // Test get<Primiative> - //Boolean - assertEqual(count / 2 == 0, m.getBoolean("odd")); - assertEqual("" + (count / 2 == 0), m.getString("odd")); + // Boolean + assertEqual((count / 2) == 0, m.getBoolean("odd")); + assertEqual("" + ((count / 2) == 0), m.getString("odd")); - //Byte + // Byte assertEqual(Byte.MAX_VALUE, m.getByte("byte")); assertEqual("" + Byte.MAX_VALUE, m.getString("byte")); - //Bytes + // Bytes assertBytesEqual(_bytes, m.getBytes("bytes")); - //Char + // Char assertEqual('c', m.getChar("char")); - //Double + // Double assertEqual(Double.MAX_VALUE, m.getDouble("double")); assertEqual("" + Double.MAX_VALUE, m.getString("double")); - //Float + // Float assertEqual(Float.MAX_VALUE, m.getFloat("float")); assertEqual(_smallfloat, (float) m.getDouble("smallfloat")); assertEqual("" + Float.MAX_VALUE, m.getString("float")); - //Integer + // Integer assertEqual(Integer.MAX_VALUE, m.getInt("int")); assertEqual("" + Integer.MAX_VALUE, m.getString("int")); assertEqual(count, m.getInt("messageNumber")); - //long + // long assertEqual(Long.MAX_VALUE, m.getLong("long")); assertEqual("" + Long.MAX_VALUE, m.getString("long")); - //Short + // Short assertEqual(Short.MAX_VALUE, m.getShort("short")); assertEqual("" + Short.MAX_VALUE, m.getString("short")); assertEqual((int) Short.MAX_VALUE, m.getInt("short")); - //String + // String assertEqual(MESSAGE + count, m.getString("message")); - //Test getObjects + // Test getObjects assertEqual(true, m.getObject("object-bool")); assertEqual(Byte.MAX_VALUE, m.getObject("object-byte")); assertBytesEqual(_bytes, (byte[]) m.getObject("object-bytes")); @@ -1196,7 +1190,7 @@ public class MapMessageTest extends TestCase implements MessageListener assertEqual(Long.MAX_VALUE, m.getObject("object-long")); assertEqual(Short.MAX_VALUE, m.getObject("object-short")); - //Check Special values + // Check Special values assertTrue(m.getString("nullString") == null); assertEqual("", m.getString("emptyString")); } @@ -1211,7 +1205,6 @@ public class MapMessageTest extends TestCase implements MessageListener } } - private static void assertEqual(Iterator expected, Iterator actual) { List<String> errors = new ArrayList<String>(); @@ -1234,6 +1227,7 @@ public class MapMessageTest extends TestCase implements MessageListener { errors.add("Found " + actual.next() + " but no more expected values."); } + if (!errors.isEmpty()) { throw new RuntimeException(errors.toString()); @@ -1250,7 +1244,7 @@ public class MapMessageTest extends TestCase implements MessageListener public void onMessage(Message message) { - synchronized(received) + synchronized (received) { _logger.info("****************** Recevied Messgage:" + (JMSMapMessage) message); received.add((JMSMapMessage) message); @@ -1266,12 +1260,13 @@ public class MapMessageTest extends TestCase implements MessageListener public static void main(String[] argv) throws Exception { MapMessageTest test = new MapMessageTest(); - test._connectionString = argv.length == 0 ? "vm://:1" : argv[0]; + test._connectionString = (argv.length == 0) ? "vm://:1" : argv[0]; test.setUp(); if (argv.length > 1) { test._count = Integer.parseInt(argv[1]); } + test.test(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java index ddb21ed3e5..65b3d60ad9 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java @@ -19,12 +19,6 @@ */ package org.apache.qpid.test.unit.basic; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Session; - import junit.framework.TestCase; import org.apache.qpid.client.AMQConnection; @@ -33,11 +27,19 @@ import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQTopic; import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.log4j.Logger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Session; public class MultipleConnectionTest extends TestCase { - private static final Logger _logger = Logger.getLogger(MultipleConnectionTest.class); + private static final Logger _logger = LoggerFactory.getLogger(MultipleConnectionTest.class); public static final String _defaultBroker = "vm://:1"; public String _connectionString = _defaultBroker; @@ -64,6 +66,7 @@ public class MultipleConnectionTest extends TestCase _counters[i] = new MessageCounter(_sessions[i].toString()); _sessions[i].createConsumer(dest).setMessageListener(_counters[i]); } + _connection.start(); } @@ -128,8 +131,10 @@ public class MultipleConnectionTest extends TestCase { break; } + wait(timeLeft); } + return expected <= _count; } @@ -144,7 +149,6 @@ public class MultipleConnectionTest extends TestCase } } - protected void setUp() throws Exception { super.setUp(); @@ -183,7 +187,7 @@ public class MultipleConnectionTest extends TestCase public static void main(String[] argv) throws Exception { - String broker = argv.length > 0 ? argv[0] : _defaultBroker; + String broker = (argv.length > 0) ? argv[0] : _defaultBroker; MultipleConnectionTest test = new MultipleConnectionTest(); test._connectionString = broker; @@ -195,12 +199,9 @@ public class MultipleConnectionTest extends TestCase String broker = _connectionString; int messages = 10; - AMQTopic topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME,"amq.topic"); + AMQTopic topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, "amq.topic"); - Receiver[] receivers = new Receiver[]{ - new Receiver(broker, topic, 2), - new Receiver(broker, topic, 14) - }; + Receiver[] receivers = new Receiver[] { new Receiver(broker, topic, 2), new Receiver(broker, topic, 14) }; Publisher publisher = new Publisher(broker, topic); for (int i = 0; i < messages; i++) diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java index aee9002354..9237555734 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/ObjectMessageTest.java @@ -19,17 +19,6 @@ */ package org.apache.qpid.test.unit.basic; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.MessageNotWriteableException; -import javax.jms.MessageProducer; - import junit.framework.Assert; import junit.framework.TestCase; @@ -39,11 +28,24 @@ import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.message.JMSObjectMessage; import org.apache.qpid.client.transport.TransportConnection; -import org.apache.log4j.Logger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.MessageNotWriteableException; +import javax.jms.MessageProducer; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; public class ObjectMessageTest extends TestCase implements MessageListener { - private static final Logger _logger = Logger.getLogger(ObjectMessageTest.class); + private static final Logger _logger = LoggerFactory.getLogger(ObjectMessageTest.class); private AMQConnection _connection; private AMQDestination _destination; @@ -75,7 +77,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener private void init(AMQConnection connection) throws Exception { - init(connection, new AMQQueue(connection,randomize("ObjectMessageTest"), true)); + init(connection, new AMQQueue(connection, randomize("ObjectMessageTest"), true)); } private void init(AMQConnection connection, AMQDestination destination) throws Exception @@ -84,7 +86,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener _destination = destination; _session = (AMQSession) connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); - //set up a slow consumer + // set up a slow consumer _session.createConsumer(destination).setMessageListener(this); connection.start(); } @@ -101,7 +103,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener void send(int count) throws JMSException { - //create a publisher + // create a publisher MessageProducer producer = _session.createProducer(_destination); for (int i = 0; i < count; i++) { @@ -113,7 +115,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener void waitFor(int count) throws InterruptedException { - synchronized(received) + synchronized (received) { while (received.size() < count) { @@ -136,7 +138,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener } catch (MessageNotWriteableException mnwe) { - //normal execution + // normal execution } m.clearBody(); @@ -150,7 +152,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener Assert.fail("Message should be writeable"); } - //Check property write status + // Check property write status try { m.setStringProperty("test", "test"); @@ -158,7 +160,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener } catch (MessageNotWriteableException mnwe) { - //normal execution + // normal execution } m.clearProperties(); @@ -200,6 +202,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener { errors.add("Found " + actual.next() + " but no more expected values."); } + if (!errors.isEmpty()) { throw new RuntimeException(errors.toString()); @@ -216,7 +219,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener public void onMessage(Message message) { - synchronized(received) + synchronized (received) { received.add((JMSObjectMessage) message); received.notify(); @@ -244,7 +247,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener public boolean equals(Object o) { - return o instanceof Payload && ((Payload) o).data.equals(data); + return (o instanceof Payload) && ((Payload) o).data.equals(data); } public String toString() @@ -256,12 +259,13 @@ public class ObjectMessageTest extends TestCase implements MessageListener public static void main(String[] argv) throws Exception { ObjectMessageTest test = new ObjectMessageTest(); - test._connectionString = argv.length == 0 ? "vm://:1" : argv[0]; + test._connectionString = (argv.length == 0) ? "vm://:1" : argv[0]; test.setUp(); if (argv.length > 1) { test._count = Integer.parseInt(argv[1]); } + test.test(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java index 90784b0772..dce9667ff2 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java @@ -20,10 +20,19 @@ */ package org.apache.qpid.test.unit.basic; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.math.BigDecimal; +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.message.AMQMessage; +import org.apache.qpid.client.message.JMSTextMessage; +import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.framing.AMQShortString; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.Destination; import javax.jms.JMSException; @@ -33,22 +42,14 @@ import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; -import junit.framework.Assert; -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.client.message.JMSTextMessage; -import org.apache.qpid.client.message.AMQMessage; -import org.apache.qpid.framing.AMQShortString; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; public class PropertyValueTest extends TestCase implements MessageListener { - - private static final Logger _logger = Logger.getLogger(PropertyValueTest.class); + private static final Logger _logger = LoggerFactory.getLogger(PropertyValueTest.class); private int count = 0; private AMQConnection _connection; @@ -83,7 +84,7 @@ public class PropertyValueTest extends TestCase implements MessageListener _destination = destination; _session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - //set up a slow consumer + // set up a slow consumer _session.createConsumer(destination).setMessageListener(this); connection.start(); } @@ -136,7 +137,7 @@ public class PropertyValueTest extends TestCase implements MessageListener void send(int count) throws JMSException { - //create a publisher + // create a publisher MessageProducer producer = _session.createProducer(_destination); for (int i = 0; i < count; i++) { @@ -152,14 +153,14 @@ public class PropertyValueTest extends TestCase implements MessageListener m.setIntProperty("Int", (int) Integer.MAX_VALUE); m.setJMSCorrelationID("Correlation"); - //fixme the m.setJMSMessage has no effect + // fixme the m.setJMSMessage has no effect producer.setPriority(8); m.setJMSPriority(3); - // Queue + // Queue Queue q; - if (i / 2 == 0) + if ((i / 2) == 0) { q = _session.createTemporaryQueue(); } @@ -173,8 +174,8 @@ public class PropertyValueTest extends TestCase implements MessageListener _logger.trace("Message:" + m); - Assert.assertEquals("Check temp queue has been set correctly", - m.getJMSReplyTo().toString(), m.getStringProperty("TempQueue")); + Assert.assertEquals("Check temp queue has been set correctly", m.getJMSReplyTo().toString(), + m.getStringProperty("TempQueue")); m.setJMSType("Test"); m.setLongProperty("UnsignedInt", (long) 4294967295L); @@ -183,18 +184,17 @@ public class PropertyValueTest extends TestCase implements MessageListener m.setShortProperty("Short", (short) Short.MAX_VALUE); m.setStringProperty("String", "Test"); - //AMQP Specific values + // AMQP Specific values // Timestamp long nano = System.nanoTime(); m.setStringProperty("time-str", String.valueOf(nano)); ((AMQMessage) m).setTimestampProperty(new AMQShortString("time"), nano); - //Decimal + // Decimal BigDecimal bd = new BigDecimal(Integer.MAX_VALUE); ((AMQMessage) m).setDecimalProperty(new AMQShortString("decimal"), bd.setScale(Byte.MAX_VALUE)); - bd = new BigDecimal((long) Integer.MAX_VALUE + 1L); try @@ -207,10 +207,10 @@ public class PropertyValueTest extends TestCase implements MessageListener // normal path. } - try { - ((AMQMessage) m).setDecimalProperty(new AMQShortString("decimal-bad-scale"), bd.setScale(Byte.MAX_VALUE + 1)); + ((AMQMessage) m).setDecimalProperty(new AMQShortString("decimal-bad-scale"), + bd.setScale(Byte.MAX_VALUE + 1)); fail("UnsupportedOperationException should be thrown as scale can't be correctly transmitted"); } catch (UnsupportedOperationException uoe) @@ -218,7 +218,7 @@ public class PropertyValueTest extends TestCase implements MessageListener // normal path. } - //Void + // Void ((AMQMessage) m).setVoidProperty(new AMQShortString("void")); _logger.debug("Sending Msg:" + m); @@ -244,58 +244,53 @@ public class PropertyValueTest extends TestCase implements MessageListener { actual.add(m.getText()); - //Check Properties - - Assert.assertEquals("Check Boolean properties are correctly transported", - true, m.getBooleanProperty("Bool")); - Assert.assertEquals("Check Byte properties are correctly transported", - (byte) Byte.MAX_VALUE, m.getByteProperty("Byte")); - Assert.assertEquals("Check Double properties are correctly transported", - (double) Double.MAX_VALUE, m.getDoubleProperty("Double")); - Assert.assertEquals("Check Float properties are correctly transported", - (float) Float.MAX_VALUE, m.getFloatProperty("Float")); - Assert.assertEquals("Check Int properties are correctly transported", - (int) Integer.MAX_VALUE, m.getIntProperty("Int")); - Assert.assertEquals("Check CorrelationID properties are correctly transported", - "Correlation", m.getJMSCorrelationID()); - Assert.assertEquals("Check Priority properties are correctly transported", - 8, m.getJMSPriority()); + // Check Properties + + Assert.assertEquals("Check Boolean properties are correctly transported", true, m.getBooleanProperty("Bool")); + Assert.assertEquals("Check Byte properties are correctly transported", (byte) Byte.MAX_VALUE, + m.getByteProperty("Byte")); + Assert.assertEquals("Check Double properties are correctly transported", (double) Double.MAX_VALUE, + m.getDoubleProperty("Double")); + Assert.assertEquals("Check Float properties are correctly transported", (float) Float.MAX_VALUE, + m.getFloatProperty("Float")); + Assert.assertEquals("Check Int properties are correctly transported", (int) Integer.MAX_VALUE, + m.getIntProperty("Int")); + Assert.assertEquals("Check CorrelationID properties are correctly transported", "Correlation", + m.getJMSCorrelationID()); + Assert.assertEquals("Check Priority properties are correctly transported", 8, m.getJMSPriority()); // Queue - Assert.assertEquals("Check ReplyTo properties are correctly transported", - m.getStringProperty("TempQueue"), m.getJMSReplyTo().toString()); + Assert.assertEquals("Check ReplyTo properties are correctly transported", m.getStringProperty("TempQueue"), + m.getJMSReplyTo().toString()); - Assert.assertEquals("Check Type properties are correctly transported", - "Test", m.getJMSType()); + Assert.assertEquals("Check Type properties are correctly transported", "Test", m.getJMSType()); - Assert.assertEquals("Check Short properties are correctly transported", - (short) Short.MAX_VALUE, m.getShortProperty("Short")); - Assert.assertEquals("Check UnsignedInt properties are correctly transported", - (long) 4294967295L, m.getLongProperty("UnsignedInt")); - Assert.assertEquals("Check Long properties are correctly transported", - (long) Long.MAX_VALUE, m.getLongProperty("Long")); - Assert.assertEquals("Check String properties are correctly transported", - "Test", m.getStringProperty("String")); + Assert.assertEquals("Check Short properties are correctly transported", (short) Short.MAX_VALUE, + m.getShortProperty("Short")); + Assert.assertEquals("Check UnsignedInt properties are correctly transported", (long) 4294967295L, + m.getLongProperty("UnsignedInt")); + Assert.assertEquals("Check Long properties are correctly transported", (long) Long.MAX_VALUE, + m.getLongProperty("Long")); + Assert.assertEquals("Check String properties are correctly transported", "Test", m.getStringProperty("String")); // AMQP Tests Specific values - Assert.assertEquals("Check Timestamp properties are correctly transported", - m.getStringProperty("time-str"), - ((AMQMessage) m).getTimestampProperty(new AMQShortString("time")).toString()); + Assert.assertEquals("Check Timestamp properties are correctly transported", m.getStringProperty("time-str"), + ((AMQMessage) m).getTimestampProperty(new AMQShortString("time")).toString()); - //Decimal + // Decimal BigDecimal bd = new BigDecimal(Integer.MAX_VALUE); - Assert.assertEquals("Check decimal properties are correctly transported", - bd.setScale(Byte.MAX_VALUE), - ((AMQMessage) m).getDecimalProperty(new AMQShortString("decimal"))); + Assert.assertEquals("Check decimal properties are correctly transported", bd.setScale(Byte.MAX_VALUE), + ((AMQMessage) m).getDecimalProperty(new AMQShortString("decimal"))); - //Void + // Void ((AMQMessage) m).setVoidProperty(new AMQShortString("void")); Assert.assertTrue("Check void properties are correctly transported", - ((AMQMessage) m).getPropertyHeaders().containsKey("void")); + ((AMQMessage) m).getPropertyHeaders().containsKey("void")); } + received.clear(); assertEqual(messages.iterator(), actual.iterator()); @@ -325,6 +320,7 @@ public class PropertyValueTest extends TestCase implements MessageListener { errors.add("Found " + actual.next() + " but no more expected values."); } + if (!errors.isEmpty()) { throw new RuntimeException(errors.toString()); @@ -356,12 +352,13 @@ public class PropertyValueTest extends TestCase implements MessageListener public static void main(String[] argv) throws Exception { PropertyValueTest test = new PropertyValueTest(); - test._connectionString = argv.length == 0 ? "vm://:1" : argv[0]; + test._connectionString = (argv.length == 0) ? "vm://:1" : argv[0]; test.setUp(); if (argv.length > 1) { test._count = Integer.parseInt(argv[1]); } + test.testOnce(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SelectorTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/SelectorTest.java index cc4bb441a4..40c712c1c9 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SelectorTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/SelectorTest.java @@ -20,14 +20,8 @@ */ package org.apache.qpid.test.unit.basic; -import javax.jms.DeliveryMode; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; - import junit.framework.TestCase; -import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQQueue; @@ -35,10 +29,17 @@ import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.BasicMessageProducer; import org.apache.qpid.client.transport.TransportConnection; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.DeliveryMode; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; + public class SelectorTest extends TestCase implements MessageListener { - - private final static Logger _logger = org.apache.log4j.Logger.getLogger(SelectorTest.class); + private static final Logger _logger = LoggerFactory.getLogger(SelectorTest.class); private AMQConnection _connection; private AMQDestination _destination; @@ -70,13 +71,12 @@ public class SelectorTest extends TestCase implements MessageListener _destination = destination; connection.start(); - String selector = null; -// selector = "Cost = 2 AND JMSDeliveryMode=" + DeliveryMode.NON_PERSISTENT; -// selector = "JMSType = Special AND Cost = 2 AND AMQMessageID > 0 AND JMSDeliveryMode=" + DeliveryMode.NON_PERSISTENT; + // selector = "Cost = 2 AND JMSDeliveryMode=" + DeliveryMode.NON_PERSISTENT; + // selector = "JMSType = Special AND Cost = 2 AND AMQMessageID > 0 AND JMSDeliveryMode=" + DeliveryMode.NON_PERSISTENT; _session = (AMQSession) connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); - //_session.createConsumer(destination).setMessageListener(this); + // _session.createConsumer(destination).setMessageListener(this); _session.createConsumer(destination, selector).setMessageListener(this); } @@ -103,7 +103,7 @@ public class SelectorTest extends TestCase implements MessageListener if (count == 0) { fail("Did not get message!"); - //throw new RuntimeException("Did not get message!"); + // throw new RuntimeException("Did not get message!"); } } finally @@ -128,7 +128,7 @@ public class SelectorTest extends TestCase implements MessageListener public static void main(String[] argv) throws Exception { SelectorTest test = new SelectorTest(); - test._connectionString = argv.length == 0 ? "localhost:5672" : argv[0]; + test._connectionString = (argv.length == 0) ? "localhost:5672" : argv[0]; test.setUp(); test.test(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java index 8e2d59475a..cc18169a5b 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,23 +20,25 @@ */ package org.apache.qpid.test.unit.basic; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; - import junit.framework.TestCase; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; -import org.apache.qpid.testutil.VMBrokerSetup; import org.apache.qpid.framing.AMQShortString; -import org.apache.log4j.Logger; +import org.apache.qpid.testutil.VMBrokerSetup; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; public class SessionStartTest extends TestCase implements MessageListener { - private static final Logger _logger = Logger.getLogger(SessionStartTest.class); + private static final Logger _logger = LoggerFactory.getLogger(SessionStartTest.class); private AMQConnection _connection; private AMQDestination _destination; @@ -57,7 +59,8 @@ public class SessionStartTest extends TestCase implements MessageListener private void init(AMQConnection connection) throws Exception { - init(connection, new AMQQueue(connection.getDefaultQueueExchangeName(), new AMQShortString(randomize("SessionStartTest")), true)); + init(connection, + new AMQQueue(connection.getDefaultQueueExchangeName(), new AMQShortString(randomize("SessionStartTest")), true)); } private void init(AMQConnection connection, AMQDestination destination) throws Exception @@ -107,7 +110,7 @@ public class SessionStartTest extends TestCase implements MessageListener public static void main(String[] argv) throws Exception { SessionStartTest test = new SessionStartTest(); - test._connectionString = argv.length == 0 ? "localhost:5672" : argv[0]; + test._connectionString = (argv.length == 0) ? "localhost:5672" : argv[0]; test.setUp(); test.test(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java index f24355552a..000fb9ab88 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,9 +20,18 @@ */ package org.apache.qpid.test.unit.basic; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import junit.framework.Assert; +import junit.framework.TestCase; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.client.message.JMSTextMessage; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.testutil.VMBrokerSetup; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.Destination; import javax.jms.JMSException; @@ -32,20 +41,13 @@ import javax.jms.MessageNotWriteableException; import javax.jms.MessageProducer; import javax.jms.Session; -import junit.framework.Assert; -import junit.framework.TestCase; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.client.message.JMSTextMessage; -import org.apache.qpid.testutil.VMBrokerSetup; -import org.apache.qpid.framing.AMQShortString; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; public class TextMessageTest extends TestCase implements MessageListener { - private static final Logger _logger = Logger.getLogger(TextMessageTest.class); + private static final Logger _logger = LoggerFactory.getLogger(TextMessageTest.class); private AMQConnection _connection; private Destination _destination; @@ -75,7 +77,8 @@ public class TextMessageTest extends TestCase implements MessageListener private void init(AMQConnection connection) throws Exception { - Destination destination = new AMQQueue(connection.getDefaultQueueExchangeName(), new AMQShortString(randomize("TextMessageTest")), true); + Destination destination = + new AMQQueue(connection.getDefaultQueueExchangeName(), new AMQShortString(randomize("TextMessageTest")), true); init(connection, destination); } @@ -85,7 +88,7 @@ public class TextMessageTest extends TestCase implements MessageListener _destination = destination; _session = (AMQSession) connection.createSession(false, Session.AUTO_ACKNOWLEDGE); - //set up a slow consumer + // set up a slow consumer _session.createConsumer(destination).setMessageListener(this); connection.start(); } @@ -102,7 +105,7 @@ public class TextMessageTest extends TestCase implements MessageListener void send(int count) throws JMSException { - //create a publisher + // create a publisher MessageProducer producer = _session.createProducer(_destination); for (int i = 0; i < count; i++) { @@ -118,7 +121,7 @@ public class TextMessageTest extends TestCase implements MessageListener void waitFor(int count) throws InterruptedException { - synchronized(received) + synchronized (received) { while (received.size() < count) { @@ -134,7 +137,7 @@ public class TextMessageTest extends TestCase implements MessageListener { actual.add(m.getText()); - //Check body write status + // Check body write status try { m.setText("Test text"); @@ -142,7 +145,7 @@ public class TextMessageTest extends TestCase implements MessageListener } catch (MessageNotWriteableException mnwe) { - //normal execution + // normal execution } m.clearBody(); @@ -156,7 +159,7 @@ public class TextMessageTest extends TestCase implements MessageListener Assert.fail("Message should be writeable"); } - //Check property write status + // Check property write status try { m.setStringProperty("test", "test"); @@ -164,7 +167,7 @@ public class TextMessageTest extends TestCase implements MessageListener } catch (MessageNotWriteableException mnwe) { - //normal execution + // normal execution } m.clearProperties(); @@ -205,6 +208,7 @@ public class TextMessageTest extends TestCase implements MessageListener { errors.add("Found " + actual.next() + " but no more expected values."); } + if (!errors.isEmpty()) { throw new RuntimeException(errors.toString()); @@ -221,7 +225,7 @@ public class TextMessageTest extends TestCase implements MessageListener public void onMessage(Message message) { - synchronized(received) + synchronized (received) { received.add((JMSTextMessage) message); received.notify(); @@ -236,12 +240,13 @@ public class TextMessageTest extends TestCase implements MessageListener public static void main(String[] argv) throws Exception { TextMessageTest test = new TextMessageTest(); - test._connectionString = argv.length == 0 ? "vm://:1" : argv[0]; + test._connectionString = (argv.length == 0) ? "vm://:1" : argv[0]; test.setUp(); if (argv.length > 1) { test._count = Integer.parseInt(argv[1]); } + test.test(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/close/CloseTests.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/close/CloseTests.java index 505af361bc..690ba7f01b 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/close/CloseTests.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/close/CloseTests.java @@ -14,35 +14,35 @@ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations - * under the License. + * under the License. + * * - * */ package org.apache.qpid.test.unit.basic.close; import junit.framework.TestCase; -import org.apache.qpid.client.transport.TransportConnection; + +import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.AMQException; -import org.apache.qpid.url.URLSyntaxException; +import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.url.AMQBindingURL; -import org.apache.log4j.Logger; +import org.apache.qpid.url.URLSyntaxException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import javax.jms.Session; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; +import javax.jms.Session; public class CloseTests extends TestCase { - - private static final Logger _logger = Logger.getLogger(CloseTests.class); - + private static final Logger _logger = LoggerFactory.getLogger(CloseTests.class); private static final String BROKER = "vm://:1"; - protected void setUp() throws Exception { super.setUp(); @@ -57,12 +57,11 @@ public class CloseTests extends TestCase TransportConnection.killVMBroker(1); } - public void testCloseQueueReceiver() throws AMQException, URLSyntaxException, JMSException { AMQConnection connection = new AMQConnection(BROKER, "guest", "guest", this.getName(), "test"); - Session session = connection.createQueueSession(false,Session.AUTO_ACKNOWLEDGE); + Session session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); AMQQueue queue = new AMQQueue(new AMQBindingURL("test-queue")); MessageConsumer consumer = session.createConsumer(queue); @@ -76,6 +75,6 @@ public class CloseTests extends TestCase consumer.close(); _logger.info("Closed Consumer"); - + } } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java index 4a114321aa..85fcf6d95a 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseMethodHandlerNoCloseOk.java @@ -14,30 +14,32 @@ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations - * under the License. + * under the License. + * * - * */ package org.apache.qpid.test.unit.client.channelclose; -import org.apache.log4j.Logger; -import org.apache.qpid.client.state.AMQStateManager; -import org.apache.qpid.client.state.StateAwareMethodListener; -import org.apache.qpid.client.protocol.AMQProtocolSession; -import org.apache.qpid.client.AMQNoConsumersException; -import org.apache.qpid.client.AMQNoRouteException; -import org.apache.qpid.protocol.AMQMethodEvent; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQInvalidRoutingKeyException; import org.apache.qpid.AMQChannelClosedException; +import org.apache.qpid.AMQException; import org.apache.qpid.AMQInvalidArgumentException; -import org.apache.qpid.framing.ChannelCloseBody; +import org.apache.qpid.AMQInvalidRoutingKeyException; +import org.apache.qpid.client.AMQNoConsumersException; +import org.apache.qpid.client.AMQNoRouteException; +import org.apache.qpid.client.protocol.AMQProtocolSession; +import org.apache.qpid.client.state.AMQStateManager; +import org.apache.qpid.client.state.StateAwareMethodListener; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ChannelCloseBody; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.protocol.AMQMethodEvent; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ChannelCloseMethodHandlerNoCloseOk implements StateAwareMethodListener { - private static final Logger _logger = Logger.getLogger(ChannelCloseMethodHandlerNoCloseOk.class); + private static final Logger _logger = LoggerFactory.getLogger(ChannelCloseMethodHandlerNoCloseOk.class); private static ChannelCloseMethodHandlerNoCloseOk _handler = new ChannelCloseMethodHandlerNoCloseOk(); @@ -46,7 +48,8 @@ public class ChannelCloseMethodHandlerNoCloseOk implements StateAwareMethodListe return _handler; } - public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) throws AMQException + public void methodReceived(AMQStateManager stateManager, AMQProtocolSession protocolSession, AMQMethodEvent evt) + throws AMQException { _logger.debug("ChannelClose method received"); ChannelCloseBody method = (ChannelCloseBody) evt.getMethod(); @@ -59,9 +62,9 @@ public class ChannelCloseMethodHandlerNoCloseOk implements StateAwareMethodListe } // For this test Method Handler .. don't send Close-OK -// // TODO: Be aware of possible changes to parameter order as versions change. -// AMQFrame frame = ChannelCloseOkBody.createAMQFrame(evt.getChannelId(), method.getMajor(), method.getMinor()); -// protocolSession.writeFrame(frame); + // // TODO: Be aware of possible changes to parameter order as versions change. + // AMQFrame frame = ChannelCloseOkBody.createAMQFrame(evt.getChannelId(), method.getMajor(), method.getMinor()); + // protocolSession.writeFrame(frame); if (errorCode != AMQConstant.REPLY_SUCCESS) { _logger.error("Channel close received with errorCode " + errorCode + ", and reason " + reason); @@ -91,6 +94,7 @@ public class ChannelCloseMethodHandlerNoCloseOk implements StateAwareMethodListe } } + protocolSession.channelClosed(evt.getChannelId(), errorCode, String.valueOf(reason)); } -}
\ No newline at end of file +} diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java index c7f1bb3065..6753ed48e4 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseOkTest.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,10 +20,17 @@ */ package org.apache.qpid.test.unit.client.channelclose; -import java.util.ArrayList; -import java.util.List; +import junit.framework.TestCase; + +import junit.textui.TestRunner; + +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.transport.TransportConnection; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import javax.jms.Connection; import javax.jms.Destination; import javax.jms.ExceptionListener; import javax.jms.JMSException; @@ -33,14 +40,8 @@ import javax.jms.MessageProducer; import javax.jms.Session; import javax.jms.TextMessage; -import junit.framework.TestCase; -import junit.textui.TestRunner; - -import org.apache.log4j.Logger; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQQueue; -import org.apache.qpid.client.transport.TransportConnection; - +import java.util.ArrayList; +import java.util.List; /** * Due to bizarre exception handling all sessions are closed if you get @@ -66,10 +67,9 @@ public class ChannelCloseOkTest extends TestCase private final List<Message> _received1 = new ArrayList<Message>(); private final List<Message> _received2 = new ArrayList<Message>(); - private final static Logger _log = Logger.getLogger(ChannelCloseOkTest.class); + private static final Logger _log = LoggerFactory.getLogger(ChannelCloseOkTest.class); public String _connectionString = "vm://:1"; - protected void setUp() throws Exception { super.setUp(); @@ -77,34 +77,34 @@ public class ChannelCloseOkTest extends TestCase TransportConnection.createVMBroker(1); _connection = new AMQConnection(_connectionString, "guest", "guest", randomize("Client"), "test"); - _destination1 = new AMQQueue(_connection,"q1", true); + _destination1 = new AMQQueue(_connection, "q1", true); _destination2 = new AMQQueue(_connection, "q2", true); _session1 = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); _session1.createConsumer(_destination1).setMessageListener(new MessageListener() - { - public void onMessage(Message message) { - _log.debug("consumer 1 got message [" + getTextMessage(message) + "]"); - synchronized(_received1) + public void onMessage(Message message) { - _received1.add(message); - _received1.notify(); + _log.debug("consumer 1 got message [" + getTextMessage(message) + "]"); + synchronized (_received1) + { + _received1.add(message); + _received1.notify(); + } } - } - }); + }); _session2 = _connection.createSession(false, Session.AUTO_ACKNOWLEDGE); _session2.createConsumer(_destination2).setMessageListener(new MessageListener() - { - public void onMessage(Message message) { - _log.debug("consumer 2 got message [" + getTextMessage(message) + "]"); - synchronized(_received2) + public void onMessage(Message message) { - _received2.add(message); - _received2.notify(); + _log.debug("consumer 2 got message [" + getTextMessage(message) + "]"); + synchronized (_received2) + { + _received2.add(message); + _received2.notify(); + } } - } - }); + }); _connection.start(); } @@ -145,12 +145,12 @@ public class ChannelCloseOkTest extends TestCase public void testWithExceptionListener() throws Exception { _connection.setExceptionListener(new ExceptionListener() - { - public void onException(JMSException jmsException) { - _log.warn("onException - "+jmsException.getMessage()); - } - }); + public void onException(JMSException jmsException) + { + _log.warn("onException - " + jmsException.getMessage()); + } + }); doTest(); } @@ -175,6 +175,7 @@ public class ChannelCloseOkTest extends TestCase send(_session1, _destination1, "" + i); send(_session2, _destination2, "" + i); } + waitFor(_received1, num + 1); waitFor(_received2, num + 1); @@ -184,7 +185,7 @@ public class ChannelCloseOkTest extends TestCase } private void sendAndWait(Session session, Destination destination, String message, List<Message> received, int count) - throws JMSException, InterruptedException + throws JMSException, InterruptedException { send(session, destination, message); waitFor(received, count); @@ -199,7 +200,7 @@ public class ChannelCloseOkTest extends TestCase private void waitFor(List<Message> received, int count) throws InterruptedException { - synchronized(received) + synchronized (received) { while (received.size() < count) { diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java index 51bbe7d0e6..87984e8c49 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/channelclose/ChannelCloseTest.java @@ -14,46 +14,48 @@ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations - * under the License. + * under the License. + * * - * */ package org.apache.qpid.test.unit.client.channelclose; import junit.framework.TestCase; -import javax.jms.Connection; -import javax.jms.Session; - -import javax.jms.JMSException; -import javax.jms.ExceptionListener; -import javax.jms.MessageProducer; -import javax.jms.MessageConsumer; -import javax.jms.Message; -import javax.jms.TextMessage; -import javax.jms.Queue; - -import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQTimeoutException; import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.failover.FailoverException; import org.apache.qpid.client.protocol.AMQProtocolSession; import org.apache.qpid.client.state.AMQStateManager; +import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.ChannelCloseOkBody; import org.apache.qpid.framing.ChannelOpenBody; import org.apache.qpid.framing.ChannelOpenOkBody; -import org.apache.qpid.framing.AMQFrame; import org.apache.qpid.framing.ExchangeDeclareBody; import org.apache.qpid.framing.ExchangeDeclareOkBody; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.AMQException; -import org.apache.qpid.AMQTimeoutException; -import org.apache.qpid.url.URLSyntaxException; -import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.jms.ConnectionListener; -import org.apache.log4j.Logger; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.url.URLSyntaxException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.Connection; +import javax.jms.ExceptionListener; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; +import javax.jms.TextMessage; public class ChannelCloseTest extends TestCase implements ExceptionListener, ConnectionListener { - private static final Logger _logger = Logger.getLogger(ChannelCloseTest.class); + private static final Logger _logger = LoggerFactory.getLogger(ChannelCloseTest.class); Connection _connection; private String _brokerlist = "vm://:1"; @@ -73,15 +75,14 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con TransportConnection.killAllVMBrokers(); } - /* close channel, use chanel with same id ensure error. - */ - public void testReusingChannelAfterFullClosure() + */ + public void testReusingChannelAfterFullClosure() throws Exception { _connection = newConnection(); - //Create Producer + // Create Producer try { _connection.start(); @@ -113,6 +114,7 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con { _logger.info("Exception occured was:" + e.getErrorCode()); } + assertEquals("Connection should be closed", AMQConstant.CHANNEL_ERROR, e.getErrorCode()); _connection = newConnection(); @@ -134,29 +136,27 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con /* close channel and send guff then send ok no errors */ - public void testSendingMethodsAfterClose() + public void testSendingMethodsAfterClose() throws Exception { try { - _connection = new AMQConnection("amqp://guest:guest@CCTTest/test?brokerlist='" - + _brokerlist + "'"); + _connection = new AMQConnection("amqp://guest:guest@CCTTest/test?brokerlist='" + _brokerlist + "'"); ((AMQConnection) _connection).setConnectionListener(this); - _connection.setExceptionListener(this); - //Change the StateManager for one that doesn't respond with Close-OKs + // Change the StateManager for one that doesn't respond with Close-OKs AMQStateManager oldStateManager = ((AMQConnection) _connection).getProtocolHandler().getStateManager(); _session = _connection.createSession(false, Session.CLIENT_ACKNOWLEDGE); _connection.start(); - //Test connection + // Test connection checkSendingMessage(); - //Set StateManager to manager that ignores Close-oks + // Set StateManager to manager that ignores Close-oks AMQProtocolSession protocolSession = ((AMQConnection) _connection).getProtocolHandler().getProtocolSession(); AMQStateManager newStateManager = new NoCloseOKStateManager(protocolSession); newStateManager.changeState(oldStateManager.getCurrentState()); @@ -214,7 +214,7 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con createChannelAndTest(TEST_CHANNEL); - //Test connection is still ok + // Test connection is still ok checkSendingMessage(); @@ -248,9 +248,9 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con } } - private void createChannelAndTest(int channel) + private void createChannelAndTest(int channel) throws FailoverException { - //Create A channel + // Create A channel try { createChannel(channel); @@ -274,14 +274,14 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con private void sendClose(int channel) { - AMQFrame frame = ChannelCloseOkBody.createAMQFrame(channel, - ((AMQConnection) _connection).getProtocolHandler().getProtocolMajorVersion(), - ((AMQConnection) _connection).getProtocolHandler().getProtocolMinorVersion()); + AMQFrame frame = + ChannelCloseOkBody.createAMQFrame(channel, + ((AMQConnection) _connection).getProtocolHandler().getProtocolMajorVersion(), + ((AMQConnection) _connection).getProtocolHandler().getProtocolMinorVersion()); ((AMQConnection) _connection).getProtocolHandler().writeFrame(frame); } - private void checkSendingMessage() throws JMSException { TEST++; @@ -307,8 +307,7 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con AMQConnection connection = null; try { - connection = new AMQConnection("amqp://guest:guest@CCTTest/test?brokerlist='" - + _brokerlist + "'"); + connection = new AMQConnection("amqp://guest:guest@CCTTest/test?brokerlist='" + _brokerlist + "'"); connection.setConnectionListener(this); @@ -330,24 +329,24 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con fail("Creating new connection when:" + e.getMessage()); } - return connection; } - private void declareExchange(int channelId, String _type, String _name, boolean nowait) throws AMQException + private void declareExchange(int channelId, String _type, String _name, boolean nowait) + throws AMQException, FailoverException { - AMQFrame exchangeDeclare = ExchangeDeclareBody.createAMQFrame(channelId, - ((AMQConnection) _connection).getProtocolHandler().getProtocolMajorVersion(), - ((AMQConnection) _connection).getProtocolHandler().getProtocolMinorVersion(), - null, // arguments - false, // autoDelete - false, // durable - new AMQShortString(_name), // exchange - false, // internal - nowait, // nowait - true, // passive - 0, // ticket - new AMQShortString(_type)); // type + AMQFrame exchangeDeclare = + ExchangeDeclareBody.createAMQFrame(channelId, + ((AMQConnection) _connection).getProtocolHandler().getProtocolMajorVersion(), + ((AMQConnection) _connection).getProtocolHandler().getProtocolMinorVersion(), null, // arguments + false, // autoDelete + false, // durable + new AMQShortString(_name), // exchange + false, // internal + nowait, // nowait + true, // passive + 0, // ticket + new AMQShortString(_type)); // type if (nowait) { @@ -355,36 +354,31 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con } else { - ((AMQConnection) _connection).getProtocolHandler().syncWrite(exchangeDeclare, ExchangeDeclareOkBody.class, SYNC_TIMEOUT); + ((AMQConnection) _connection).getProtocolHandler().syncWrite(exchangeDeclare, ExchangeDeclareOkBody.class, + SYNC_TIMEOUT); } } - private void createChannel(int channelId) throws AMQException + private void createChannel(int channelId) throws AMQException, FailoverException { - ((AMQConnection) _connection).getProtocolHandler().syncWrite( - ChannelOpenBody.createAMQFrame(channelId, - ((AMQConnection) _connection).getProtocolHandler().getProtocolMajorVersion(), - ((AMQConnection) _connection).getProtocolHandler().getProtocolMinorVersion(), - null), // outOfBand - ChannelOpenOkBody.class); + ((AMQConnection) _connection).getProtocolHandler().syncWrite(ChannelOpenBody.createAMQFrame(channelId, + ((AMQConnection) _connection).getProtocolHandler().getProtocolMajorVersion(), + ((AMQConnection) _connection).getProtocolHandler().getProtocolMinorVersion(), null), // outOfBand + ChannelOpenOkBody.class); } - public void onException(JMSException jmsException) { - //_logger.info("CCT" + jmsException); + // _logger.info("CCT" + jmsException); fail(jmsException.getMessage()); } public void bytesSent(long count) - { - } + { } public void bytesReceived(long count) - { - - } + { } public boolean preFailover(boolean redirect) { @@ -397,6 +391,5 @@ public class ChannelCloseTest extends TestCase implements ExceptionListener, Con } public void failoverComplete() - { - } + { } } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Client.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Client.java index e077bddd8d..19ef612bcc 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Client.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/Client.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,14 +20,16 @@ */ package org.apache.qpid.test.unit.client.forwardall; -import javax.jms.Message; -import javax.jms.MessageListener; - import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.framing.AMQShortString; -import org.apache.log4j.Logger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.Message; +import javax.jms.MessageListener; /** * Declare a private temporary response queue, @@ -37,8 +39,7 @@ import org.apache.log4j.Logger; */ public class Client implements MessageListener { - - private static final Logger _logger = Logger.getLogger(Client.class); + private static final Logger _logger = LoggerFactory.getLogger(Client.class); private final AMQConnection _connection; private final AMQSession _session; @@ -55,10 +56,11 @@ public class Client implements MessageListener _connection = connection; _expected = expected; _session = (AMQSession) _connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); - AMQQueue response = new AMQQueue(_connection.getDefaultQueueExchangeName(), new AMQShortString("ResponseQueue"), true); + AMQQueue response = + new AMQQueue(_connection.getDefaultQueueExchangeName(), new AMQShortString("ResponseQueue"), true); _session.createConsumer(response).setMessageListener(this); _connection.start(); - AMQQueue service = new SpecialQueue(_connection,"ServiceQueue"); + AMQQueue service = new SpecialQueue(_connection, "ServiceQueue"); Message request = _session.createTextMessage("Request!"); request.setJMSReplyTo(response); _session.createProducer(service).send(request); @@ -72,27 +74,27 @@ public class Client implements MessageListener public synchronized void onMessage(Message response) { - - _logger.info("Received " + (++_count) + " of " + _expected + " responses."); - if(_count == _expected) + + _logger.info("Received " + (++_count) + " of " + _expected + " responses."); + if (_count == _expected) { notifyAll(); } - } synchronized void waitUntilComplete() throws Exception { - if(_count < _expected) + if (_count < _expected) { wait(10000L); } - if(_count < _expected) + + if (_count < _expected) { - throw new Exception("Didn't receive all messages... got " + _count + " expected " + _expected); + throw new Exception("Didn't receive all messages... got " + _count + " expected " + _expected); } } @@ -105,7 +107,8 @@ public class Client implements MessageListener { final String connectionString; final int expected; - if (argv.length == 0) { + if (argv.length == 0) + { connectionString = "localhost:5672"; expected = 100; } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java index 69c5fc3aa9..9c354ee260 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/CombinedTest.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -23,7 +23,9 @@ package org.apache.qpid.test.unit.client.forwardall; import junit.framework.TestCase; import org.apache.qpid.testutil.VMBrokerSetup; -import org.apache.log4j.Logger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Runs the Service's and Client parts of the test in the same process @@ -31,7 +33,7 @@ import org.apache.log4j.Logger; */ public class CombinedTest extends TestCase { - private static final Logger _logger = Logger.getLogger(CombinedTest.class); + private static final Logger _logger = LoggerFactory.getLogger(CombinedTest.class); protected void setUp() throws Exception { diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java index 8482227961..be16f6b7ae 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/forwardall/ServiceCreator.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,14 +20,14 @@ */ package org.apache.qpid.test.unit.client.forwardall; -import org.apache.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import javax.jms.JMSException; public class ServiceCreator implements Runnable { - private static final Logger _logger = Logger.getLogger(ServiceCreator.class); - + private static final Logger _logger = LoggerFactory.getLogger(ServiceCreator.class); private static Thread[] threads; private static ServiceCreator[] _services; @@ -67,7 +67,7 @@ public class ServiceCreator implements Runnable } catch (JMSException e) { - //ignore + // ignore } } } @@ -77,7 +77,7 @@ public class ServiceCreator implements Runnable threads = new Thread[services]; _services = new ServiceCreator[services]; ServiceCreator runner = new ServiceCreator(broker); - //start services + // start services _logger.info("Starting " + services + " services..."); for (int i = 0; i < services; i++) { @@ -106,6 +106,7 @@ public class ServiceCreator implements Runnable connectionString = argv[0]; services = Integer.parseInt(argv[1]); } + start(connectionString, services); } } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java index 11a6b4b5c5..cd03b523d1 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,17 +20,6 @@ */ package org.apache.qpid.test.unit.client.message; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; - -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.ObjectMessage; - import junit.framework.TestCase; import org.apache.qpid.client.AMQConnection; @@ -38,11 +27,24 @@ import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.testutil.VMBrokerSetup; -import org.apache.log4j.Logger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.ObjectMessage; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; public class ObjectMessageTest extends TestCase implements MessageListener { - private static final Logger _logger = Logger.getLogger(ObjectMessageTest.class); + private static final Logger _logger = LoggerFactory.getLogger(ObjectMessageTest.class); private AMQConnection connection; private AMQDestination destination; @@ -59,15 +61,15 @@ public class ObjectMessageTest extends TestCase implements MessageListener { super.setUp(); connection = new AMQConnection(_broker, "guest", "guest", randomize("Client"), "test"); - destination = new AMQQueue(connection,randomize("LatencyTest"), true); + destination = new AMQQueue(connection, randomize("LatencyTest"), true); session = (AMQSession) connection.createSession(false, AMQSession.NO_ACKNOWLEDGE); - //set up a consumer + // set up a consumer session.createConsumer(destination).setMessageListener(this); connection.start(); - //create a publisher - producer = session.createProducer(destination, false, false, true); + // create a publisher + producer = session.createProducer(destination, false, false, true); A a1 = new A(1, "A"); A a2 = new A(2, "a"); B b = new B(1, "B"); @@ -77,7 +79,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener c.put("B", b); c.put("String", "String"); - data = new Serializable[]{a1, a2, b, c, "Hello World!", new Integer(1001)}; + data = new Serializable[] { a1, a2, b, c, "Hello World!", new Integer(1001) }; } protected void tearDown() throws Exception @@ -86,8 +88,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener } public ObjectMessageTest() - { - } + { } ObjectMessageTest(String broker) throws Exception { @@ -118,60 +119,60 @@ public class ObjectMessageTest extends TestCase implements MessageListener { String testStringProperty = "TestStringProperty"; ObjectMessage msg = session.createObjectMessage(data[0]); - msg.setObjectProperty("TestStringProperty",testStringProperty); + msg.setObjectProperty("TestStringProperty", testStringProperty); assertEquals(testStringProperty, msg.getObjectProperty("TestStringProperty")); } public void testSetObjectPropertyForBoolean() throws Exception { ObjectMessage msg = session.createObjectMessage(data[0]); - msg.setObjectProperty("TestBooleanProperty",Boolean.TRUE); + msg.setObjectProperty("TestBooleanProperty", Boolean.TRUE); assertEquals(Boolean.TRUE, msg.getObjectProperty("TestBooleanProperty")); } public void testSetObjectPropertyForByte() throws Exception { ObjectMessage msg = session.createObjectMessage(data[0]); - msg.setObjectProperty("TestByteProperty",Byte.MAX_VALUE); + msg.setObjectProperty("TestByteProperty", Byte.MAX_VALUE); assertEquals(Byte.MAX_VALUE, msg.getObjectProperty("TestByteProperty")); } public void testSetObjectPropertyForShort() throws Exception { ObjectMessage msg = session.createObjectMessage(data[0]); - msg.setObjectProperty("TestShortProperty",Short.MAX_VALUE); + msg.setObjectProperty("TestShortProperty", Short.MAX_VALUE); assertEquals(Short.MAX_VALUE, msg.getObjectProperty("TestShortProperty")); } + public void testSetObjectPropertyForInteger() throws Exception { ObjectMessage msg = session.createObjectMessage(data[0]); - msg.setObjectProperty("TestIntegerProperty",Integer.MAX_VALUE); + msg.setObjectProperty("TestIntegerProperty", Integer.MAX_VALUE); assertEquals(Integer.MAX_VALUE, msg.getObjectProperty("TestIntegerProperty")); } public void testSetObjectPropertyForDouble() throws Exception { ObjectMessage msg = session.createObjectMessage(data[0]); - msg.setObjectProperty("TestDoubleProperty",Double.MAX_VALUE); + msg.setObjectProperty("TestDoubleProperty", Double.MAX_VALUE); assertEquals(Double.MAX_VALUE, msg.getObjectProperty("TestDoubleProperty")); } public void testSetObjectPropertyForFloat() throws Exception { ObjectMessage msg = session.createObjectMessage(data[0]); - msg.setObjectProperty("TestFloatProperty",Float.MAX_VALUE); + msg.setObjectProperty("TestFloatProperty", Float.MAX_VALUE); assertEquals(Float.MAX_VALUE, msg.getObjectProperty("TestFloatProperty")); } public void testSetObjectPropertyForByteArray() throws Exception { - byte[] array = {1,2,3,4,5}; + byte[] array = { 1, 2, 3, 4, 5 }; ObjectMessage msg = session.createObjectMessage(data[0]); - msg.setObjectProperty("TestByteArrayProperty",array); - assertTrue(Arrays.equals(array,(byte[])msg.getObjectProperty("TestByteArrayProperty"))); + msg.setObjectProperty("TestByteArrayProperty", array); + assertTrue(Arrays.equals(array, (byte[]) msg.getObjectProperty("TestByteArrayProperty"))); } - public void testSetObjectForNull() throws Exception { ObjectMessage msg = session.createObjectMessage(); @@ -179,13 +180,12 @@ public class ObjectMessageTest extends TestCase implements MessageListener assertNull(msg.getObject()); } - private void send() throws Exception { for (int i = 0; i < data.length; i++) { ObjectMessage msg; - if (i % 2 == 0) + if ((i % 2) == 0) { msg = session.createObjectMessage(data[i]); } @@ -194,6 +194,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener msg = session.createObjectMessage(); msg.setObject(data[i]); } + producer.send(msg); } } @@ -205,16 +206,19 @@ public class ObjectMessageTest extends TestCase implements MessageListener { throw new Exception("Expected " + data.length + " objects, got " + actual.length); } + for (int i = 0; i < data.length; i++) { if (actual[i] instanceof Exception) { throw new Exception("Error on receive of " + data[i], ((Exception) actual[i])); } + if (actual[i] == null) { throw new Exception("Expected " + data[i] + " got null"); } + if (!data[i].equals(actual[i])) { throw new Exception("Expected " + data[i] + " got " + actual[i]); @@ -222,7 +226,6 @@ public class ObjectMessageTest extends TestCase implements MessageListener } } - private void close() throws Exception { session.close(); @@ -236,6 +239,7 @@ public class ObjectMessageTest extends TestCase implements MessageListener { wait(); } + waiting = false; } @@ -260,21 +264,21 @@ public class ObjectMessageTest extends TestCase implements MessageListener items.add(e); } - synchronized(this) - { - received++; - notify(); - } + synchronized (this) + { + received++; + notify(); + } } - public static void main(String[] argv) throws Exception { - String broker = argv.length > 0 ? argv[0] : "vm://:1"; + String broker = (argv.length > 0) ? argv[0] : "vm://:1"; if ("-help".equals(broker)) { System.out.println("Usage: <broker>"); } + new ObjectMessageTest(broker).testSendAndReceive(); } @@ -296,12 +300,12 @@ public class ObjectMessageTest extends TestCase implements MessageListener public boolean equals(Object o) { - return o instanceof A && equals((A) o); + return (o instanceof A) && equals((A) o); } protected boolean equals(A a) { - return areEqual(a.sValue, sValue) && a.iValue == iValue; + return areEqual(a.sValue, sValue) && (a.iValue == iValue); } } @@ -317,17 +321,16 @@ public class ObjectMessageTest extends TestCase implements MessageListener protected boolean equals(A a) { - return super.equals(a) && a instanceof B && time == ((B) a).time; + return super.equals(a) && (a instanceof B) && (time == ((B) a).time); } } private static class C extends HashMap implements Serializable - { - } + { } private static boolean areEqual(Object a, Object b) { - return a == null ? b == null : a.equals(b); + return (a == null) ? (b == null) : a.equals(b); } private static String randomize(String in) diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java index 117696196e..5a61480f6a 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/close/CloseBeforeAckTest.java @@ -20,22 +20,23 @@ */
package org.apache.qpid.test.unit.close;
-import javax.jms.Connection;
-import javax.jms.Message;
-import javax.jms.MessageListener;
-import javax.jms.Session;
-
import junit.framework.Assert;
import junit.framework.TestCase;
-import org.apache.log4j.Logger;
-
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.transport.TransportConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import uk.co.thebadgerset.junit.concurrency.TestRunnable;
import uk.co.thebadgerset.junit.concurrency.ThreadTestCoordinator;
+import javax.jms.Connection;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.Session;
+
/**
* This test forces the situation where a session is closed whilst a message consumer is still in its onMessage method.
* Running in AUTO_ACK mode, the close call ought to wait until the onMessage method completes, and the ack is sent
@@ -46,7 +47,7 @@ import uk.co.thebadgerset.junit.concurrency.ThreadTestCoordinator; */
public class CloseBeforeAckTest extends TestCase
{
- private static final Logger log = Logger.getLogger(CloseBeforeAckTest.class);
+ private static final Logger log = LoggerFactory.getLogger(CloseBeforeAckTest.class);
Connection connection;
Session session;
@@ -64,34 +65,34 @@ public class CloseBeforeAckTest extends TestCase public void onMessage(Message message)
{
// Give thread 2 permission to close the session.
- allow(new int[]{1});
+ allow(new int[] { 1 });
// Wait until thread 2 has closed the connection, or is blocked waiting for this to complete.
- waitFor(new int[]{1}, true);
+ waitFor(new int[] { 1 }, true);
}
}
TestThread1 testThread1 = new TestThread1();
TestRunnable testThread2 =
- new TestRunnable()
+ new TestRunnable()
+ {
+ public void runWithExceptions() throws Exception
{
- public void runWithExceptions() throws Exception
- {
- // Send a message to be picked up by thread 1.
- session.createProducer(null).send(session.createQueue(TEST_QUEUE_NAME),
- session.createTextMessage("Hi there thread 1!"));
-
- // Wait for thread 1 to pick up the message and give permission to continue.
- waitFor(new int[]{0}, false);
-
- // Close the connection.
- session.close();
-
- // Allow thread 1 to continue to completion, if it is erronously still waiting.
- allow(new int[]{1});
- }
- };
+ // Send a message to be picked up by thread 1.
+ session.createProducer(null).send(session.createQueue(TEST_QUEUE_NAME),
+ session.createTextMessage("Hi there thread 1!"));
+
+ // Wait for thread 1 to pick up the message and give permission to continue.
+ waitFor(new int[] { 0 }, false);
+
+ // Close the connection.
+ session.close();
+
+ // Allow thread 1 to continue to completion, if it is erronously still waiting.
+ allow(new int[] { 1 });
+ }
+ };
public void testCloseBeforeAutoAck_QPID_397() throws Exception
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java index d52707d965..a297011acd 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/close/MessageRequeueTest.java @@ -22,34 +22,28 @@ package org.apache.qpid.test.unit.close; import junit.framework.TestCase; -import java.util.concurrent.atomic.AtomicInteger; +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.message.AbstractJMSMessage; +import org.apache.qpid.client.transport.TransportConnection; +import org.apache.qpid.testutil.QpidClientConnection; +import org.apache.qpid.url.URLSyntaxException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import javax.jms.ExceptionListener; -import javax.jms.Session; import javax.jms.Connection; import javax.jms.JMSException; -import javax.jms.Queue; -import javax.jms.MessageProducer; import javax.jms.Message; -import javax.jms.TextMessage; import javax.jms.MessageConsumer; +import javax.jms.Queue; +import javax.jms.Session; -import org.apache.qpid.client.AMQConnectionFactory; -import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.message.AbstractJMSMessage; -import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.url.URLSyntaxException; -import org.apache.qpid.AMQException; -import org.apache.qpid.testutil.QpidClientConnection; -import org.apache.log4j.Logger; -import org.apache.log4j.Level; +import java.util.concurrent.atomic.AtomicInteger; public class MessageRequeueTest extends TestCase { - - private static final Logger _logger = Logger.getLogger(MessageRequeueTest.class); + private static final Logger _logger = LoggerFactory.getLogger(MessageRequeueTest.class); protected static AtomicInteger consumerIds = new AtomicInteger(0); protected final Integer numTestMessages = 150; @@ -86,7 +80,7 @@ public class MessageRequeueTest extends TestCase { super.tearDown(); - if (!passed) // clean up + if (!passed) // clean up { QpidClientConnection conn = new QpidClientConnection(BROKER); @@ -96,6 +90,7 @@ public class MessageRequeueTest extends TestCase conn.disconnect(); } + TransportConnection.killVMBroker(1); } @@ -117,7 +112,7 @@ public class MessageRequeueTest extends TestCase final MessageConsumer consumer = conn.getSession().createConsumer(q); int messagesReceived = 0; - long messageLog[] = new long[numTestMessages + 1]; + long[] messageLog = new long[numTestMessages + 1]; _logger.info("consuming..."); Message msg = consumer.receive(1000); @@ -130,15 +125,13 @@ public class MessageRequeueTest extends TestCase int msgindex = msg.getIntProperty("index"); if (messageLog[msgindex] != 0) { - _logger.error("Received Message(" + msgindex + ":" + ((AbstractJMSMessage) msg).getDeliveryTag() + - ") more than once."); + _logger.error("Received Message(" + msgindex + ":" + ((AbstractJMSMessage) msg).getDeliveryTag() + + ") more than once."); } if (_logger.isInfoEnabled()) { - _logger.info("Received Message(" + System.identityHashCode(msgindex) + ") " + - "DT:" + dt + - "IN:" + msgindex); + _logger.info("Received Message(" + System.identityHashCode(msgindex) + ") " + "DT:" + dt + "IN:" + msgindex); } if (dt == 0) @@ -148,7 +141,7 @@ public class MessageRequeueTest extends TestCase messageLog[msgindex] = dt; - //get Next message + // get Next message msg = consumer.receive(1000); } @@ -163,7 +156,7 @@ public class MessageRequeueTest extends TestCase for (long b : messageLog) { - if (b == 0 && index != 0) //delivery tag of zero shouldn't exist + if ((b == 0) && (index != 0)) // delivery tag of zero shouldn't exist { _logger.error("Index: " + index + " was not received."); list.append(" "); @@ -175,6 +168,7 @@ public class MessageRequeueTest extends TestCase index++; } + assertEquals(list.toString(), 0, failed); _logger.info("consumed: " + messagesReceived); conn.disconnect(); @@ -199,7 +193,7 @@ public class MessageRequeueTest extends TestCase t1.start(); t2.start(); t3.start(); -// t4.start(); + // t4.start(); try { @@ -228,7 +222,7 @@ public class MessageRequeueTest extends TestCase for (long b : receieved) { - if (b == 0 && index != 0) //delivery tag of zero shouldn't exist (and we don't have msg 0) + if ((b == 0) && (index != 0)) // delivery tag of zero shouldn't exist (and we don't have msg 0) { _logger.error("Index: " + index + " was not received."); list.append(" "); @@ -237,8 +231,10 @@ public class MessageRequeueTest extends TestCase list.append(b); failed++; } + index++; } + assertEquals(list.toString() + "-" + numTestMessages + "-" + totalConsumed, 0, failed); assertEquals("number of consumed messages does not match initial data", numTestMessages, totalConsumed); passed = true; @@ -278,15 +274,14 @@ public class MessageRequeueTest extends TestCase int msgindex = result.getIntProperty("index"); if (receieved[msgindex] != 0) { - _logger.error("Received Message(" + msgindex + ":" + ((AbstractJMSMessage) result).getDeliveryTag() + - ") more than once."); + _logger.error("Received Message(" + msgindex + ":" + + ((AbstractJMSMessage) result).getDeliveryTag() + ") more than once."); } if (_logger.isInfoEnabled()) { - _logger.info("Received Message(" + System.identityHashCode(msgindex) + ") " + - "DT:" + dt + - "IN:" + msgindex); + _logger.info("Received Message(" + System.identityHashCode(msgindex) + ") " + "DT:" + dt + + "IN:" + msgindex); } if (dt == 0) @@ -297,9 +292,8 @@ public class MessageRequeueTest extends TestCase receieved[msgindex] = dt; } - count++; - if (count % 100 == 0) + if ((count % 100) == 0) { _logger.info("consumer-" + id + ": got " + result + ", new count is " + count); } @@ -328,11 +322,10 @@ public class MessageRequeueTest extends TestCase } } - public void testRequeue() throws JMSException, AMQException, URLSyntaxException { int run = 0; -// while (run < 10) + // while (run < 10) { run++; @@ -359,7 +352,6 @@ public class MessageRequeueTest extends TestCase assertNotNull("Message should not be null", msg); - // As we have not ack'd message will be requeued. _logger.debug("Close Consumer"); consumer.close(); @@ -369,4 +361,4 @@ public class MessageRequeueTest extends TestCase } } -}
\ No newline at end of file +} diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java index a2cd2e4da3..66e0cad1a9 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSDestinationTest.java @@ -1,28 +1,29 @@ package org.apache.qpid.test.unit.message;
-import javax.jms.Connection;
-import javax.jms.MessageConsumer;
-import javax.jms.MessageProducer;
-import javax.jms.Queue;
-import javax.jms.Session;
-import javax.jms.TextMessage;
-
import junit.framework.TestCase;
-import org.apache.log4j.Logger;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.framing.AMQShortString;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.jms.Connection;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
/**
* @author Apache Software Foundation
*/
public class JMSDestinationTest extends TestCase
{
-
- private static final Logger _logger = Logger.getLogger(JMSDestinationTest.class);
+ private static final Logger _logger = LoggerFactory.getLogger(JMSDestinationTest.class);
public String _connectionString = "vm://:1";
@@ -32,7 +33,6 @@ public class JMSDestinationTest extends TestCase TransportConnection.createVMBroker(1);
}
-
protected void tearDown() throws Exception
{
super.tearDown();
@@ -43,7 +43,9 @@ public class JMSDestinationTest extends TestCase {
AMQConnection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "test");
AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
- Queue queue = new AMQQueue(con.getDefaultQueueExchangeName(), new AMQShortString("someQ"), new AMQShortString("someQ"), false, true);
+ Queue queue =
+ new AMQQueue(con.getDefaultQueueExchangeName(), new AMQShortString("someQ"), new AMQShortString("someQ"), false,
+ true);
MessageConsumer consumer = consumerSession.createConsumer(queue);
Connection con2 = new AMQConnection("vm://:1", "guest", "guest", "producer1", "test");
@@ -64,7 +66,7 @@ public class JMSDestinationTest extends TestCase TextMessage rm = (TextMessage) consumer.receive();
assertNotNull(rm);
- assertEquals(rm.getJMSDestination(),queue);
+ assertEquals(rm.getJMSDestination(), queue);
con.close();
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java index dad1666299..3012909daa 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/JMSPropertiesTest.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,17 +20,8 @@ */ package org.apache.qpid.test.unit.message; -import javax.jms.Connection; -import javax.jms.Destination; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.ObjectMessage; -import javax.jms.Queue; -import javax.jms.Session; - import junit.framework.TestCase; -import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; @@ -38,13 +29,23 @@ import org.apache.qpid.client.message.NonQpidObjectMessage; import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.framing.AMQShortString; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.Destination; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.ObjectMessage; +import javax.jms.Queue; +import javax.jms.Session; + /** * @author Apache Software Foundation */ public class JMSPropertiesTest extends TestCase { - private static final Logger _logger = Logger.getLogger(JMSPropertiesTest.class); + private static final Logger _logger = LoggerFactory.getLogger(JMSPropertiesTest.class); public String _connectionString = "vm://:1"; @@ -52,14 +53,12 @@ public class JMSPropertiesTest extends TestCase public static final int JMS_DELIV_MODE = 1; public static final String JMS_TYPE = "test.jms.type"; - protected void setUp() throws Exception { super.setUp(); TransportConnection.createVMBroker(1); } - protected void tearDown() throws Exception { super.tearDown(); @@ -70,36 +69,38 @@ public class JMSPropertiesTest extends TestCase { AMQConnection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "test"); AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE); - Queue queue = new AMQQueue(con.getDefaultQueueExchangeName(),new AMQShortString("someQ"), new AMQShortString("someQ"), false, true); + Queue queue = + new AMQQueue(con.getDefaultQueueExchangeName(), new AMQShortString("someQ"), new AMQShortString("someQ"), false, + true); MessageConsumer consumer = consumerSession.createConsumer(queue); AMQConnection con2 = new AMQConnection("vm://:1", "guest", "guest", "producer1", "test"); Session producerSession = con2.createSession(false, Session.CLIENT_ACKNOWLEDGE); MessageProducer producer = producerSession.createProducer(queue); - Destination JMS_REPLY_TO = new AMQQueue(con2,"my.replyto"); - //create a test message to send + Destination JMS_REPLY_TO = new AMQQueue(con2, "my.replyto"); + // create a test message to send ObjectMessage sentMsg = new NonQpidObjectMessage(); sentMsg.setJMSCorrelationID(JMS_CORR_ID); sentMsg.setJMSDeliveryMode(JMS_DELIV_MODE); sentMsg.setJMSType(JMS_TYPE); sentMsg.setJMSReplyTo(JMS_REPLY_TO); - //send it + // send it producer.send(sentMsg); con2.close(); con.start(); - //get message and check JMS properties + // get message and check JMS properties ObjectMessage rm = (ObjectMessage) consumer.receive(); assertNotNull(rm); - assertEquals("JMS Correlation ID mismatch",sentMsg.getJMSCorrelationID(),rm.getJMSCorrelationID()); - //TODO: Commented out as always overwritten by send delivery mode value - prob should not set in conversion - //assertEquals("JMS Delivery Mode mismatch",sentMsg.getJMSDeliveryMode(),rm.getJMSDeliveryMode()); - assertEquals("JMS Type mismatch",sentMsg.getJMSType(),rm.getJMSType()); - assertEquals("JMS Reply To mismatch",sentMsg.getJMSReplyTo(),rm.getJMSReplyTo()); + assertEquals("JMS Correlation ID mismatch", sentMsg.getJMSCorrelationID(), rm.getJMSCorrelationID()); + // TODO: Commented out as always overwritten by send delivery mode value - prob should not set in conversion + // assertEquals("JMS Delivery Mode mismatch",sentMsg.getJMSDeliveryMode(),rm.getJMSDeliveryMode()); + assertEquals("JMS Type mismatch", sentMsg.getJMSType(), rm.getJMSType()); + assertEquals("JMS Reply To mismatch", sentMsg.getJMSReplyTo(), rm.getJMSReplyTo()); con.close(); } diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java index fb5ea58174..9c4f2af107 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java @@ -20,37 +20,39 @@ */ package org.apache.qpid.test.unit.message; -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageEOFException; -import javax.jms.MessageListener; -import javax.jms.MessageProducer; -import javax.jms.Session; -import javax.jms.StreamMessage; - import junit.framework.TestCase; -import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQHeadersExchange; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; import org.apache.qpid.url.AMQBindingURL; import org.apache.qpid.url.BindingURL; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageEOFException; +import javax.jms.MessageListener; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.StreamMessage; + /** * @author Apache Software Foundation */ public class StreamMessageTest extends TestCase { - private static final Logger _logger = Logger.getLogger(StreamMessageTest.class); + private static final Logger _logger = LoggerFactory.getLogger(StreamMessageTest.class); public String _connectionString = "vm://:1"; @@ -60,7 +62,6 @@ public class StreamMessageTest extends TestCase TransportConnection.createVMBroker(1); } - protected void tearDown() throws Exception { super.tearDown(); @@ -72,15 +73,18 @@ public class StreamMessageTest extends TestCase Connection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "test"); AMQSession consumerSession = (AMQSession) con.createSession(false, Session.CLIENT_ACKNOWLEDGE); - - AMQHeadersExchange queue = new AMQHeadersExchange(new AMQBindingURL(ExchangeDefaults.HEADERS_EXCHANGE_CLASS+"://"+ExchangeDefaults.HEADERS_EXCHANGE_NAME+"/test/queue1?"+ BindingURL.OPTION_ROUTING_KEY+"='F0000=1'")); + AMQHeadersExchange queue = + new AMQHeadersExchange(new AMQBindingURL( + ExchangeDefaults.HEADERS_EXCHANGE_CLASS + "://" + ExchangeDefaults.HEADERS_EXCHANGE_NAME + + "/test/queue1?" + BindingURL.OPTION_ROUTING_KEY + "='F0000=1'")); FieldTable ft = new FieldTable(); - ft.setString("F1000","1"); - MessageConsumer consumer = consumerSession.createConsumer(queue, AMQSession.DEFAULT_PREFETCH_LOW_MARK, AMQSession.DEFAULT_PREFETCH_HIGH_MARK, false, false, (String)null, ft); + ft.setString("F1000", "1"); + MessageConsumer consumer = + consumerSession.createConsumer(queue, AMQSession.DEFAULT_PREFETCH_LOW_MARK, + AMQSession.DEFAULT_PREFETCH_HIGH_MARK, false, false, (String) null, ft); - - //force synch to ensure the consumer has resulted in a bound queue - //((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS); + // force synch to ensure the consumer has resulted in a bound queue + // ((AMQSession) consumerSession).declareExchangeSynch(ExchangeDefaults.HEADERS_EXCHANGE_NAME, ExchangeDefaults.HEADERS_EXCHANGE_CLASS); // This is the default now Connection con2 = new AMQConnection("vm://:1", "guest", "guest", "producer1", "test"); @@ -91,21 +95,18 @@ public class StreamMessageTest extends TestCase _logger.info("Starting producer connection"); con2.start(); - MessageProducer mandatoryProducer = producerSession.createProducer(queue); // Third test - should be routed _logger.info("Sending isBound message"); - StreamMessage msg = producerSession.createStreamMessage(); + StreamMessage msg = producerSession.createStreamMessage(); - msg.setStringProperty("F1000","1"); + msg.setStringProperty("F1000", "1"); - msg.writeByte((byte)42); + msg.writeByte((byte) 42); mandatoryProducer.send(msg); - - _logger.info("Starting consumer connection"); con.start(); @@ -129,23 +130,24 @@ public class StreamMessageTest extends TestCase AMQQueue queue = new AMQQueue(con.getDefaultQueueExchangeName(), new AMQShortString("testQ")); MessageConsumer consumer = consumerSession.createConsumer(queue); consumer.setMessageListener(new MessageListener() - { - - public void onMessage(Message message) { - StreamMessage sm = (StreamMessage) message; - try - { - sm.clearBody(); - sm.writeString("dfgjshfslfjshflsjfdlsjfhdsljkfhdsljkfhsd"); - } - catch (JMSException e) + + public void onMessage(Message message) { - _logger.error("Error when writing large string to received msg: " + e, e); - fail("Error when writing large string to received msg" + e); + StreamMessage sm = (StreamMessage) message; + try + { + sm.clearBody(); + sm.writeString("dfgjshfslfjshflsjfdlsjfhdsljkfhdsljkfhsd"); + } + catch (JMSException e) + { + _logger.error("Error when writing large string to received msg: " + e, e); + fail("Error when writing large string to received msg" + e); + } } - } - }); + }); + Connection con2 = new AMQConnection("vm://:1", "guest", "guest", "producer1", "test"); AMQSession producerSession = (AMQSession) con2.createSession(false, Session.CLIENT_ACKNOWLEDGE); MessageProducer mandatoryProducer = producerSession.createProducer(queue); diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java index 15cb9678e4..c8d43a47a5 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/topic/DurableSubscriptionTest.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,14 +20,6 @@ */ package org.apache.qpid.test.unit.topic; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.Session; -import javax.jms.TextMessage; -import javax.jms.TopicSubscriber; - import junit.framework.TestCase; import org.apache.qpid.AMQException; @@ -36,11 +28,21 @@ import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQTopic; import org.apache.qpid.client.transport.TransportConnection; import org.apache.qpid.url.URLSyntaxException; -import org.apache.log4j.Logger; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Session; +import javax.jms.TextMessage; +import javax.jms.TopicSubscriber; public class DurableSubscriptionTest extends TestCase { - private static final Logger _logger = Logger.getLogger(DurableSubscriptionTest.class); + private static final Logger _logger = LoggerFactory.getLogger(DurableSubscriptionTest.class); protected void setUp() throws Exception { @@ -84,7 +86,6 @@ public class DurableSubscriptionTest extends TestCase msg = consumer1.receive(1000); assertEquals(null, msg); - _logger.info("Receive message on consumer 1:expecting A"); msg = consumer2.receive(); assertEquals("A", ((TextMessage) msg).getText()); 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 0e718da19b..df2a38d0fc 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 @@ -21,18 +21,21 @@ package org.apache.qpid.test.unit.transacted; import junit.framework.TestCase; + +import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.AMQException; import org.apache.qpid.url.URLSyntaxException; -import org.apache.log4j.Logger; -import javax.jms.Session; -import javax.jms.MessageProducer; -import javax.jms.MessageConsumer; -import javax.jms.Queue; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import javax.jms.JMSException; import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; import javax.jms.TextMessage; /** @@ -52,7 +55,7 @@ public class CommitRollbackTest extends TestCase private MessageConsumer _consumer; Queue _jmsQueue; - private static final Logger _logger = Logger.getLogger(CommitRollbackTest.class); + private static final Logger _logger = LoggerFactory.getLogger(CommitRollbackTest.class); private static final String BROKER = "vm://:1"; protected void setUp() throws Exception @@ -62,10 +65,10 @@ public class CommitRollbackTest extends TestCase { TransportConnection.createVMBroker(1); } + testMethod++; queue += testMethod; - newConnection(); } @@ -106,7 +109,6 @@ public class CommitRollbackTest extends TestCase assertTrue("session is not transacted", _session.getTransacted()); assertTrue("session is not transacted", _pubSession.getTransacted()); - _logger.info("sending test message"); String MESSAGE_TEXT = "testPutThenDisconnect"; _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT)); @@ -119,7 +121,7 @@ public class CommitRollbackTest extends TestCase _logger.info("receiving result"); Message result = _consumer.receive(1000); - //commit to ensure message is removed from queue + // commit to ensure message is removed from queue _session.commit(); assertNull("test message was put and disconnected before commit, but is still present", result); @@ -135,7 +137,6 @@ public class CommitRollbackTest extends TestCase assertTrue("session is not transacted", _session.getTransacted()); assertTrue("session is not transacted", _pubSession.getTransacted()); - _logger.info("sending test message"); String MESSAGE_TEXT = "testPutThenDisconnect"; _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT)); @@ -151,7 +152,7 @@ public class CommitRollbackTest extends TestCase _logger.info("receiving result"); Message result = _consumer.receive(1000); - //commit to ensure message is removed from queue + // commit to ensure message is removed from queue _session.commit(); assertNull("test message was put and disconnected before commit, but is still present", result); @@ -168,7 +169,6 @@ public class CommitRollbackTest extends TestCase assertTrue("session is not transacted", _session.getTransacted()); assertTrue("session is not transacted", _pubSession.getTransacted()); - _logger.info("sending test message"); String MESSAGE_TEXT = "testPutThenRollback"; _publisher.send(_pubSession.createTextMessage(MESSAGE_TEXT)); @@ -335,13 +335,12 @@ public class CommitRollbackTest extends TestCase assertTrue("Messasge is not marked as redelivered", result.getJMSRedelivered()); } - /** * Test that rolling back a session purges the dispatcher queue, and the messages arrive in the correct order * * @throws Exception On error */ - public void testSend2ThenRollback() throws Exception + /*public void testSend2ThenRollback() throws Exception { assertTrue("session is not transacted", _session.getTransacted()); assertTrue("session is not transacted", _pubSession.getTransacted()); @@ -391,7 +390,7 @@ public class CommitRollbackTest extends TestCase } assertNull("test message should be null", result); - } + }*/ public void testSend2ThenCloseAfter1andTryAgain() throws Exception { @@ -428,7 +427,7 @@ public class CommitRollbackTest extends TestCase { assertTrue("Messasge is not marked as redelivered" + result, result.getJMSRedelivered()); } - else // or it will be msg 2 arriving the first time due to latency. + 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()); @@ -445,7 +444,6 @@ public class CommitRollbackTest extends TestCase } - public void testPutThenRollbackThenGet() throws Exception { assertTrue("session is not transacted", _session.getTransacted()); 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 d994d4c141..929621c496 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 @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,24 +20,24 @@ */ package org.apache.qpid.test.unit.transacted; -import javax.jms.Connection; -import javax.jms.JMSException; -import javax.jms.Message; -import javax.jms.MessageConsumer; -import javax.jms.MessageProducer; -import javax.jms.TextMessage; - import junit.framework.TestCase; -import org.apache.log4j.Logger; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.transport.TransportConnection; -import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.jms.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.TextMessage; + public class TransactedTest extends TestCase { private AMQQueue queue1; @@ -56,7 +56,7 @@ public class TransactedTest extends TestCase private Session testSession; private MessageConsumer testConsumer1; private MessageConsumer testConsumer2; - private static final Logger _logger = Logger.getLogger(TransactedTest.class); + private static final Logger _logger = LoggerFactory.getLogger(TransactedTest.class); protected void setUp() throws Exception { @@ -68,13 +68,15 @@ public class TransactedTest extends TestCase _logger.info("Create Session"); session = con.createSession(true, Session.SESSION_TRANSACTED); _logger.info("Create Q1"); - queue1 = new AMQQueue(session.getDefaultQueueExchangeName(), new AMQShortString("Q1"), new AMQShortString("Q1"), false, true); + queue1 = + new AMQQueue(session.getDefaultQueueExchangeName(), new AMQShortString("Q1"), new AMQShortString("Q1"), false, + true); _logger.info("Create Q2"); queue2 = new AMQQueue(session.getDefaultQueueExchangeName(), new AMQShortString("Q2"), false); _logger.info("Create Consumer of Q1"); consumer1 = session.createConsumer(queue1); - //Dummy just to create the queue. + // Dummy just to create the queue. _logger.info("Create Consumer of Q2"); MessageConsumer consumer2 = session.createConsumer(queue2); _logger.info("Close Consumer of Q2"); @@ -98,7 +100,6 @@ public class TransactedTest extends TestCase _logger.info("Create prep connection start"); prepCon.start(); - _logger.info("Create test connection"); testCon = new AMQConnection("vm://:1", "guest", "guest", "TestConnection", "test"); _logger.info("Create test session"); @@ -122,7 +123,7 @@ public class TransactedTest extends TestCase public void testCommit() throws Exception { - //add some messages + // add some messages _logger.info("Send prep A"); prepProducer1.send(prepSession.createTextMessage("A")); _logger.info("Send prep B"); @@ -130,7 +131,7 @@ public class TransactedTest extends TestCase _logger.info("Send prep C"); prepProducer1.send(prepSession.createTextMessage("C")); - //send and receive some messages + // send and receive some messages _logger.info("Send X to Q2"); producer2.send(session.createTextMessage("X")); _logger.info("Send Y to Q2"); @@ -138,7 +139,6 @@ public class TransactedTest extends TestCase _logger.info("Send Z to Q2"); producer2.send(session.createTextMessage("Z")); - _logger.info("Read A from Q1"); expect("A", consumer1.receive(1000)); _logger.info("Read B from Q1"); @@ -146,13 +146,13 @@ public class TransactedTest extends TestCase _logger.info("Read C from Q1"); expect("C", consumer1.receive(1000)); - //commit + // commit _logger.info("session commit"); session.commit(); _logger.info("Start test Connection"); testCon.start(); - //ensure sent messages can be received and received messages are gone + // ensure sent messages can be received and received messages are gone _logger.info("Read X from Q2"); expect("X", testConsumer2.receive(1000)); _logger.info("Read Y from Q2"); @@ -170,7 +170,7 @@ public class TransactedTest extends TestCase public void testRollback() throws Exception { - //add some messages + // add some messages _logger.info("Send prep A"); prepProducer1.send(prepSession.createTextMessage("A")); _logger.info("Send prep B"); @@ -178,7 +178,7 @@ public class TransactedTest extends TestCase _logger.info("Send prep C"); prepProducer1.send(prepSession.createTextMessage("C")); - //Quick sleep to ensure all three get pre-fetched + // Quick sleep to ensure all three get pre-fetched Thread.sleep(500); _logger.info("Sending X Y Z"); @@ -188,14 +188,14 @@ public class TransactedTest extends TestCase _logger.info("Receiving A B"); expect("A", consumer1.receive(1000)); expect("B", consumer1.receive(1000)); - //Don't consume 'C' leave it in the prefetch cache to ensure rollback removes it. + // Don't consume 'C' leave it in the prefetch cache to ensure rollback removes it. - //rollback + // rollback _logger.info("rollback"); session.rollback(); _logger.info("Receiving A B C"); - //ensure sent messages are not visible and received messages are requeued + // ensure sent messages are not visible and received messages are requeued expect("A", consumer1.receive(1000), true); expect("B", consumer1.receive(1000), true); expect("C", consumer1.receive(1000), true); @@ -211,7 +211,7 @@ public class TransactedTest extends TestCase _logger.info("Testing we have no messages left after commit"); assertTrue(null == testConsumer1.receive(1000)); - assertTrue(null == testConsumer2.receive(1000)); + assertTrue(null == testConsumer2.receive(1000)); } public void testResendsMsgsAfterSessionClose() throws Exception diff --git a/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java b/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java index 195ed79dab..061c1ef7a4 100644 --- a/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java +++ b/java/client/src/test/java/org/apache/qpid/testutil/QpidClientConnection.java @@ -1,26 +1,27 @@ package org.apache.qpid.testutil; +import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionFactory; import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.JMSAMQException; import org.apache.qpid.url.URLSyntaxException; -import org.apache.log4j.Logger; -import javax.jms.ExceptionListener; -import javax.jms.Session; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import javax.jms.Connection; +import javax.jms.ExceptionListener; import javax.jms.JMSException; -import javax.jms.Queue; -import javax.jms.MessageProducer; import javax.jms.Message; import javax.jms.MessageConsumer; +import javax.jms.MessageProducer; +import javax.jms.Queue; +import javax.jms.Session; import javax.jms.TextMessage; public class QpidClientConnection implements ExceptionListener { - - private static final Logger _logger = Logger.getLogger(QpidClientConnection.class); + private static final Logger _logger = LoggerFactory.getLogger(QpidClientConnection.class); private boolean transacted = true; private int ackMode = Session.CLIENT_ACKNOWLEDGE; @@ -40,17 +41,16 @@ public class QpidClientConnection implements ExceptionListener setPrefetch(5000); } - public void connect() throws JMSException { if (!connected) { /* - * amqp://[user:pass@][clientid]/virtualhost? - * brokerlist='[transport://]host[:port][?option='value'[&option='value']];' - * [&failover='method[?option='value'[&option='value']]'] - * [&option='value']" - */ + * amqp://[user:pass@][clientid]/virtualhost? + * brokerlist='[transport://]host[:port][?option='value'[&option='value']];' + * [&failover='method[?option='value'[&option='value']]'] + * [&option='value']" + */ String brokerUrl = "amqp://guest:guest@" + virtualHost + "?brokerlist='" + brokerlist + "'"; try { @@ -63,7 +63,6 @@ public class QpidClientConnection implements ExceptionListener session = ((AMQConnection) connection).createSession(transacted, ackMode, prefetch); - _logger.info("starting connection"); connection.start(); @@ -124,7 +123,6 @@ public class QpidClientConnection implements ExceptionListener this.prefetch = prefetch; } - /** override as necessary */ public void onException(JMSException exception) { @@ -266,4 +264,3 @@ public class QpidClientConnection implements ExceptionListener _logger.info("consumed: " + messagesReceived); } } - |
