diff options
author | Robert Godfrey <rgodfrey@apache.org> | 2014-02-11 10:19:17 +0000 |
---|---|---|
committer | Robert Godfrey <rgodfrey@apache.org> | 2014-02-11 10:19:17 +0000 |
commit | 6183b2736fae22b8bafb509e37386fa7a037c5f3 (patch) | |
tree | 00b68f41ebc7fa1ce306c177fc779a8819299e0a | |
parent | acf22a677693d9b0dfcdfdd8e8340af8cacbcb3c (diff) | |
download | qpid-python-6183b2736fae22b8bafb509e37386fa7a037c5f3.tar.gz |
QPID-5504 : refactring of queues, and introduce management node and amqp-management module
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1567026 13f79535-47bb-0310-9956-ffa450edef68
139 files changed, 6442 insertions, 1544 deletions
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java index 924c5b9857..9f39d2c94f 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/DestinationImpl.java @@ -24,6 +24,7 @@ import org.apache.qpid.amqp_1_0.jms.Queue; import org.apache.qpid.amqp_1_0.jms.Topic; import javax.jms.JMSException; +import java.util.UUID; import java.util.WeakHashMap; public class DestinationImpl implements Destination, Queue, Topic @@ -32,6 +33,7 @@ public class DestinationImpl implements Destination, Queue, Topic new WeakHashMap<String, DestinationImpl>(); private final String _address; + private String _localTerminus; protected DestinationImpl(String address) { @@ -62,13 +64,24 @@ public class DestinationImpl implements Destination, Queue, Topic && _address.equals(((DestinationImpl)obj)._address); } - public static synchronized DestinationImpl createDestination(final String address) + public static synchronized DestinationImpl createDestination(String address) { - DestinationImpl destination = DESTINATION_CACHE.get(address); - if(destination == null) + DestinationImpl destination; + if (address.endsWith("!!")) { + address = address.substring(0, address.length() - 2); + String localTerminusName = UUID.randomUUID().toString(); destination = new DestinationImpl(address); - DESTINATION_CACHE.put(address, destination); + destination.setLocalTerminus(localTerminusName); + } + else + { + destination = DESTINATION_CACHE.get(address); + if (destination == null) + { + destination = new DestinationImpl(address); + DESTINATION_CACHE.put(address, destination); + } } return destination; } @@ -82,4 +95,14 @@ public class DestinationImpl implements Destination, Queue, Topic { return getAddress(); } + + void setLocalTerminus(final String localTerminus) + { + _localTerminus = localTerminus; + } + + String getLocalTerminus() + { + return _localTerminus; + } } diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java index 96ee1e984d..d7bb546d7a 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java @@ -24,6 +24,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.UUID; import javax.jms.Destination; import javax.jms.ExceptionListener; import javax.jms.IllegalStateException; @@ -159,7 +160,8 @@ public class MessageConsumerImpl implements MessageConsumer, QueueReceiver, Topi { try { - return _session.getClientSession().createReceiver(_session.toAddress(_destination), AcknowledgeMode.ALO, + String targetAddr = _destination.getLocalTerminus() != null ? _destination.getLocalTerminus() : UUID.randomUUID().toString(); + return _session.getClientSession().createReceiver(_session.toAddress(_destination), targetAddr, AcknowledgeMode.ALO, _linkName, _durable, getFilters(), null); } catch (ConnectionErrorException e) diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java index fed9b5904f..f2d0cb5b18 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageImpl.java @@ -75,6 +75,7 @@ public abstract class MessageImpl implements Message private boolean _isFromQueue; private boolean _isFromTopic; private long _expiration; + private DestinationImpl _replyTo; protected MessageImpl(Header header, MessageAnnotations messageAnnotations, @@ -182,11 +183,12 @@ public abstract class MessageImpl implements Message public DestinationImpl getJMSReplyTo() throws JMSException { - return toDestination(getReplyTo(), splitCommaSeparateSet((String) getMessageAnnotation(REPLY_TO_TYPE))); + return _replyTo != null ? _replyTo : toDestination(getReplyTo(), splitCommaSeparateSet((String) getMessageAnnotation(REPLY_TO_TYPE))); } public void setJMSReplyTo(Destination destination) throws NonAMQPDestinationException { + _replyTo = (DestinationImpl) destination; if( destination==null ) { setReplyTo(null); @@ -194,9 +196,16 @@ public abstract class MessageImpl implements Message } else { - DecodedDestination dd = toDecodedDestination(destination); - setReplyTo(dd.getAddress()); - messageAnnotationMap().put(REPLY_TO_TYPE, join(",", dd.getAttributes())); + if(_replyTo.getLocalTerminus() != null) + { + setReplyTo(_replyTo.getLocalTerminus()); + } + else + { + DecodedDestination dd = toDecodedDestination(destination); + setReplyTo(dd.getAddress()); + messageAnnotationMap().put(REPLY_TO_TYPE, join(",", dd.getAttributes())); + } } } diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java index e459575974..b12540d597 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java @@ -77,7 +77,11 @@ public class MessageProducerImpl implements MessageProducer, QueueSender, TopicP { try { - _sender = _session.getClientSession().createSender(_session.toAddress(_destination), new Session.SourceConfigurator() + final String sourceName = _destination.getLocalTerminus() != null + ? _destination.getLocalTerminus() + : UUID.randomUUID().toString(); + + _sender = _session.getClientSession().createSender(sourceName, _session.toAddress(_destination), new Session.SourceConfigurator() { public void configureSource(final Source source) { diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java index cb56843a72..589ee5204f 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueImpl.java @@ -20,6 +20,7 @@ package org.apache.qpid.amqp_1_0.jms.impl; import org.apache.qpid.amqp_1_0.jms.Queue; +import java.util.UUID; import java.util.WeakHashMap; public class QueueImpl extends DestinationImpl implements Queue @@ -37,13 +38,24 @@ public class QueueImpl extends DestinationImpl implements Queue return getAddress(); } - public static synchronized QueueImpl createQueue(final String address) + public static synchronized QueueImpl createQueue(String address) { - QueueImpl queue = QUEUE_CACHE.get(address); - if(queue == null) + QueueImpl queue; + if (address.endsWith("!!")) { + address = address.substring(0, address.length() - 2); + String localTerminusName = UUID.randomUUID().toString(); queue = new QueueImpl(address); - QUEUE_CACHE.put(address, queue); + queue.setLocalTerminus(localTerminusName); + } + else + { + queue = QUEUE_CACHE.get(address); + if(queue == null) + { + queue = new QueueImpl(address); + QUEUE_CACHE.put(address, queue); + } } return queue; } diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java index 4e9e9d6a39..21161ff83f 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/QueueReceiverImpl.java @@ -24,6 +24,8 @@ import org.apache.qpid.amqp_1_0.client.Receiver; import org.apache.qpid.amqp_1_0.jms.Queue; import org.apache.qpid.amqp_1_0.jms.QueueReceiver; +import java.util.UUID; + public class QueueReceiverImpl extends MessageConsumerImpl implements QueueReceiver { QueueReceiverImpl(final QueueImpl destination, @@ -40,7 +42,11 @@ public class QueueReceiverImpl extends MessageConsumerImpl implements QueueRecei { try { - return getSession().getClientSession().createMovingReceiver(getSession().toAddress(getDestination())); + final String targetAddr = + getDestination().getLocalTerminus() != null ? getDestination().getLocalTerminus() : UUID + .randomUUID().toString(); + return getSession().getClientSession().createMovingReceiver(getSession().toAddress(getDestination()), + targetAddr); } catch (ConnectionErrorException e) { diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java index 2318b8ba9b..bd67ff681a 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java @@ -460,7 +460,7 @@ public class SessionImpl implements Session, QueueSession, TopicSession { checkClosed(); checkNotTopicSession(); - return new QueueImpl(s); + return QueueImpl.valueOf(s); } public QueueReceiver createReceiver(final Queue queue) throws JMSException @@ -488,7 +488,7 @@ public class SessionImpl implements Session, QueueSession, TopicSession { checkClosed(); checkNotQueueSession(); - return new TopicImpl(s); + return TopicImpl.valueOf(s); } public TopicSubscriber createSubscriber(final Topic topic) throws JMSException diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java index 5292944075..edc583e233 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicImpl.java @@ -20,6 +20,7 @@ package org.apache.qpid.amqp_1_0.jms.impl; import org.apache.qpid.amqp_1_0.jms.Topic; +import java.util.UUID; import java.util.WeakHashMap; public class TopicImpl extends DestinationImpl implements Topic @@ -38,13 +39,24 @@ public class TopicImpl extends DestinationImpl implements Topic return getAddress(); } - public static synchronized TopicImpl createTopic(final String address) + public static synchronized TopicImpl createTopic(String address) { - TopicImpl topic = TOPIC_CACHE.get(address); - if(topic == null) + TopicImpl topic; + if (address.endsWith("!!")) { + address = address.substring(0, address.length() - 2); + String localTerminusName = UUID.randomUUID().toString(); topic = new TopicImpl(address); - TOPIC_CACHE.put(address, topic); + topic.setLocalTerminus(localTerminusName); + } + else + { + topic = TOPIC_CACHE.get(address); + if(topic == null) + { + topic = new TopicImpl(address); + TOPIC_CACHE.put(address, topic); + } } return topic; } diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java index 69e07f30a1..b89025a27b 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/TopicSubscriberImpl.java @@ -19,6 +19,7 @@ package org.apache.qpid.amqp_1_0.jms.impl; import java.util.Map; +import java.util.UUID; import javax.jms.InvalidSelectorException; import javax.jms.JMSException; import org.apache.qpid.amqp_1_0.client.AcknowledgeMode; @@ -67,7 +68,9 @@ public class TopicSubscriberImpl extends MessageConsumerImpl implements TopicSub try { String address = getSession().toAddress(getDestination()); - Receiver receiver = getSession().getClientSession().createReceiver(address, + String targetAddress = getDestination().getLocalTerminus() != null ? getDestination().getLocalTerminus() : UUID.randomUUID().toString(); + + Receiver receiver = getSession().getClientSession().createReceiver(address, targetAddress, StdDistMode.COPY, AcknowledgeMode.ALO, getLinkName(), isDurable(), getFilters(), null); diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java index cac4775b54..290895df60 100644 --- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Session.java @@ -78,8 +78,14 @@ public class Session public Sender createSender(final String targetName, final SourceConfigurator configurator) throws Sender.SenderCreationException, ConnectionClosedException { - final String sourceName = UUID.randomUUID().toString(); + return createSender(sourceName, targetName, configurator); + } + + public Sender createSender(final String sourceName, final String targetName, final SourceConfigurator configurator) + throws Sender.SenderCreationException, ConnectionClosedException + { + return new Sender(this, targetName +"<-"+sourceName, targetName, sourceName, false) { @Override @@ -150,93 +156,118 @@ public class Session public Receiver createReceiver(final String sourceAddr) throws ConnectionErrorException { - return createReceiver(sourceAddr, null, AcknowledgeMode.ALO); + return createReceiver(sourceAddr, UUID.randomUUID().toString(), null, AcknowledgeMode.ALO); } public Receiver createReceiver(final String queue, final AcknowledgeMode mode) throws ConnectionErrorException { - return createReceiver(queue, null, mode); + return createReceiver(queue, UUID.randomUUID().toString(), null, mode); } public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName) throws ConnectionErrorException { - return createReceiver(queue, null, mode, linkName); + return createReceiver(queue, UUID.randomUUID().toString(), null, mode, linkName); } public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName, boolean isDurable) throws ConnectionErrorException { - return createReceiver(queue, null, mode, linkName, isDurable); + return createReceiver(queue, UUID.randomUUID().toString(), null, mode, linkName, isDurable); } public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName, boolean isDurable, Map<Symbol, Filter> filters, Map<Binary, Outcome> unsettled) throws ConnectionErrorException { - return createReceiver(queue, null, mode, linkName, isDurable, filters, unsettled); + return createReceiver(queue, (DistributionMode) null, mode, linkName, isDurable, filters, unsettled); } - - public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName, - boolean isDurable, Map<Binary, Outcome> unsettled) + public Receiver createReceiver(final String queue, String targetName, final AcknowledgeMode mode, String linkName, boolean isDurable, + Map<Symbol, Filter> filters, Map<Binary, Outcome> unsettled) throws ConnectionErrorException { - return createReceiver(queue, null, mode, linkName, isDurable, unsettled); + return createReceiver(queue, targetName, null, mode, linkName, isDurable, filters, unsettled); } - private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode) + public Receiver createReceiver(final String queue, final AcknowledgeMode mode, String linkName, + boolean isDurable, Map<Binary, Outcome> unsettled) throws ConnectionErrorException { - return createReceiver(sourceAddr, mode, AcknowledgeMode.ALO); + return createReceiver(queue, UUID.randomUUID().toString(), null, mode, linkName, isDurable, unsettled); } - private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode, String linkName) + + private synchronized Receiver createReceiver(final String sourceAddr, + final String targetAddr, + DistributionMode mode) throws ConnectionErrorException { - return createReceiver(sourceAddr, mode, AcknowledgeMode.ALO, linkName); + return createReceiver(sourceAddr, targetAddr, mode, AcknowledgeMode.ALO); } - private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode, - final AcknowledgeMode ackMode) + private synchronized Receiver createReceiver(final String sourceAddr, + final String targetAddr, + DistributionMode mode, + final AcknowledgeMode ackMode) throws ConnectionErrorException { - return createReceiver(sourceAddr, mode, ackMode, null); + return createReceiver(sourceAddr, targetAddr, mode, ackMode, null); } - private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode, - final AcknowledgeMode ackMode, String linkName) + private synchronized Receiver createReceiver(final String sourceAddr, + final String targetAddr, + DistributionMode mode, + final AcknowledgeMode ackMode, + String linkName) throws ConnectionErrorException { - return createReceiver(sourceAddr,mode, ackMode, linkName, false); + return createReceiver(sourceAddr, targetAddr, mode, ackMode, linkName, false); } - private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode, - final AcknowledgeMode ackMode, String linkName, boolean isDurable) + private synchronized Receiver createReceiver(final String sourceAddr, + final String targetAddr, + DistributionMode mode, + final AcknowledgeMode ackMode, + String linkName, + boolean isDurable) throws ConnectionErrorException { - return createReceiver(sourceAddr, mode, ackMode, linkName, isDurable, null); + return createReceiver(sourceAddr, targetAddr, mode, ackMode, linkName, isDurable, null); } - private synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode, - final AcknowledgeMode ackMode, String linkName, boolean isDurable, - Map<Binary, Outcome> unsettled) + private synchronized Receiver createReceiver(final String sourceAddr, + final String targetAddr, + DistributionMode mode, + final AcknowledgeMode ackMode, + String linkName, + boolean isDurable, + Map<Binary, Outcome> unsettled) throws ConnectionErrorException { return createReceiver(sourceAddr,mode,ackMode, linkName, isDurable, null, unsettled); } public synchronized Receiver createReceiver(final String sourceAddr, DistributionMode mode, + final AcknowledgeMode ackMode, String linkName, boolean isDurable, + Map<Symbol, Filter> filters, Map<Binary, Outcome> unsettled) + throws ConnectionErrorException + { + return createReceiver(sourceAddr, UUID.randomUUID().toString(), mode, ackMode, linkName, isDurable, filters, unsettled); + } + + public synchronized Receiver createReceiver(final String sourceAddr, String targetAddr, DistributionMode mode, final AcknowledgeMode ackMode, String linkName, boolean isDurable, Map<Symbol, Filter> filters, Map<Binary, Outcome> unsettled) throws ConnectionErrorException { final Target target = new Target(); + target.setAddress(targetAddr); final Source source = new Source(); source.setAddress(sourceAddr); source.setDistributionMode(mode); @@ -258,12 +289,17 @@ public class Session public synchronized Receiver createCopyingReceiver(final String sourceAddr) throws ConnectionErrorException { - return createReceiver(sourceAddr, StdDistMode.COPY); + return createReceiver(sourceAddr, UUID.randomUUID().toString(), StdDistMode.COPY); } public synchronized Receiver createMovingReceiver(final String sourceAddr) throws ConnectionErrorException { - return createReceiver(sourceAddr, StdDistMode.MOVE); + return createReceiver(sourceAddr, UUID.randomUUID().toString(), StdDistMode.MOVE); + } + + public synchronized Receiver createMovingReceiver(final String sourceAddr, final String targetAddr) throws ConnectionErrorException + { + return createReceiver(sourceAddr, UUID.randomUUID().toString(), StdDistMode.MOVE); } public Receiver createTemporaryQueueReceiver() throws AmqpErrorException, ConnectionErrorException diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index bc670bd848..600c60bdb3 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java @@ -43,6 +43,7 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.store.DurableConfigurationStoreHelper; +import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.Action; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -428,10 +429,10 @@ public abstract class AbstractExchange implements Exchange return queues; } - public final int send(final ServerMessage message, + public final <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message, final InstanceProperties instanceProperties, final ServerTransaction txn, - final Action<MessageInstance<? extends Consumer>> postEnqueueAction) + final Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction) { List<? extends BaseQueue> queues = route(message, instanceProperties); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java index 33c5218b4c..78b9664cd3 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java @@ -46,6 +46,7 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.Action; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -335,10 +336,10 @@ public class DefaultExchange implements Exchange return _id; } - public final int send(final ServerMessage message, + public final <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message, final InstanceProperties instanceProperties, final ServerTransaction txn, - final Action<MessageInstance<? extends Consumer>> postEnqueueAction) + final Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction) { final AMQQueue q = _virtualHost.getQueue(message.getRoutingKey()); if(q == null) diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java index 967c629749..62f5b3634b 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.message; import org.apache.qpid.server.consumer.Consumer; +import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.Action; @@ -37,8 +38,8 @@ public interface MessageDestination extends MessageNode * @param postEnqueueAction action to perform on the result of every enqueue (may be null) * @return the number of queues in which the message was enqueued performed */ - int send(ServerMessage message, + <M extends ServerMessage<? extends StorableMessageMetaData>> int send(M message, InstanceProperties instanceProperties, ServerTransaction txn, - Action<MessageInstance<? extends Consumer>> postEnqueueAction); + Action<? super MessageInstance<?,? extends Consumer>> postEnqueueAction); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java index 97cb66cce4..49969ce3c1 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java @@ -30,7 +30,7 @@ import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.Action; import org.apache.qpid.server.util.StateChangeListener; -public interface MessageInstance<C extends Consumer> +public interface MessageInstance<M extends MessageInstance<M,C>, C extends Consumer> { @@ -45,9 +45,9 @@ public interface MessageInstance<C extends Consumer> void decrementDeliveryCount(); - void addStateChangeListener(StateChangeListener<MessageInstance<C>, State> listener); + void addStateChangeListener(StateChangeListener<? super M,State> listener); - boolean removeStateChangeListener(StateChangeListener<MessageInstance<C>, State> listener); + boolean removeStateChangeListener(StateChangeListener<? super M, State> listener); boolean acquiredByConsumer(); @@ -71,7 +71,7 @@ public interface MessageInstance<C extends Consumer> int getMaximumDeliveryCount(); - int routeToAlternate(Action<MessageInstance<? extends Consumer>> action, ServerTransaction txn); + int routeToAlternate(Action<? super MessageInstance<?, ? extends Consumer>> action, ServerTransaction txn); Filterable asFilterable(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java index 06ff76f103..49b0f2995c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java @@ -32,17 +32,17 @@ import org.apache.qpid.server.store.TransactionLogResource; import java.util.Collection; import java.util.EnumSet; -public interface MessageSource<C extends Consumer> extends TransactionLogResource, MessageNode +public interface MessageSource<C extends Consumer, S extends MessageSource<C,S>> extends TransactionLogResource, MessageNode { - C addConsumer(ConsumerTarget target, FilterManager filters, + <T extends ConsumerTarget> C addConsumer(T target, FilterManager filters, Class<? extends ServerMessage> messageClass, String consumerName, EnumSet<Consumer.Option> options) throws AMQException; Collection<C> getConsumers(); - void addConsumerRegistrationListener(ConsumerRegistrationListener listener); + void addConsumerRegistrationListener(ConsumerRegistrationListener<S> listener); - void removeConsumerRegistrationListener(ConsumerRegistrationListener listener); + void removeConsumerRegistrationListener(ConsumerRegistrationListener<S> listener); AuthorizationHolder getAuthorizationHolder(); @@ -54,10 +54,10 @@ public interface MessageSource<C extends Consumer> extends TransactionLogResourc boolean isExclusive(); - interface ConsumerRegistrationListener + interface ConsumerRegistrationListener<Q extends MessageSource<? extends Consumer,Q>> { - void consumerAdded(AMQQueue queue, Consumer consumer); - void consumerRemoved(AMQQueue queue, Consumer consumer); + void consumerAdded(Q source, Consumer consumer); + void consumerRemoved(Q queue, Consumer consumer); } /** diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java new file mode 100644 index 0000000000..f972bd78f6 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessage.java @@ -0,0 +1,254 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.message.internal; + +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.AbstractServerMessageImpl; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.util.ByteBufferInputStream; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class InternalMessage extends AbstractServerMessageImpl<InternalMessage, InternalMessageMetaData> +{ + private final Object _messageBody; + private final int _contentSize; + private InternalMessageHeader _header; + + + InternalMessage(final StoredMessage<InternalMessageMetaData> handle, + final InternalMessageHeader header, + final Object messageBody) + { + super(handle, null); + _header = header; + _messageBody = messageBody; + _contentSize = handle.getMetaData().getContentSize(); + } + + InternalMessage(final StoredMessage<InternalMessageMetaData> msg) + { + super(msg, null); + _contentSize = msg.getMetaData().getContentSize(); + ByteBuffer buf = msg.getContent(0, _contentSize); + + try + { + ObjectInputStream is = new ObjectInputStream(new ByteBufferInputStream(buf)); + _messageBody = is.readObject(); + + } + catch (IOException e) + { + throw new RuntimeException(e); + } + catch (ClassNotFoundException e) + { + throw new RuntimeException(e); + } + } + + @Override + public String getRoutingKey() + { + return null; + } + + @Override + public InternalMessageHeader getMessageHeader() + { + return _header; + } + + @Override + public long getSize() + { + return _contentSize; + } + + @Override + public long getExpiration() + { + return _header.getExpiration(); + } + + @Override + public long getArrivalTime() + { + return _header.getArrivalTime(); + } + + public Object getMessageBody() + { + return _messageBody; + } + + private static InternalMessage createMessage(final MessageStore store, + final AMQMessageHeader header, + final Serializable bodyObject, final boolean persistent) + { + InternalMessageHeader internalHeader; + if(header instanceof InternalMessageHeader) + { + internalHeader = (InternalMessageHeader) header; + } + else + { + internalHeader = new InternalMessageHeader(header); + } + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + try + { + ObjectOutputStream os = new ObjectOutputStream(bytesOut); + os.writeObject(bodyObject); + byte[] bytes = bytesOut.toByteArray(); + + + final InternalMessageMetaData metaData = InternalMessageMetaData.create(persistent, internalHeader, bytes.length); + StoredMessage<InternalMessageMetaData> handle = + store.addMessage(metaData); + handle.addContent(0, ByteBuffer.wrap(bytes)); + + return new InternalMessage(handle, internalHeader, bodyObject); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + public static InternalMessage createStringMessage(MessageStore store, AMQMessageHeader header, String messageBody) + { + return createMessage(store, header, messageBody, false); + } + + public static InternalMessage createMapMessage(MessageStore store, AMQMessageHeader header, Map<? extends Object,? extends Object> messageBody) + { + return createMessage(store, header, new LinkedHashMap<Object,Object>(messageBody), false); + } + + public static InternalMessage createListMessage(MessageStore store, AMQMessageHeader header, List<? extends Object> messageBody) + { + return createMessage(store, header, new ArrayList<Object>(messageBody), false); + } + + public static InternalMessage createBytesMessage(MessageStore store, AMQMessageHeader header, byte[] messageBody) + { + return createMessage(store, header, messageBody, false); + } + + public static InternalMessage convert(long messageNumber, boolean persistent, AMQMessageHeader header, Object messageBody) + { + InternalMessageHeader convertedHeader = new InternalMessageHeader(header); + StoredMessage<InternalMessageMetaData> handle = createReadOnlyHandle(messageNumber, persistent, convertedHeader, messageBody); + return new InternalMessage(handle, convertedHeader, messageBody); + } + + private static StoredMessage<InternalMessageMetaData> createReadOnlyHandle(final long messageNumber, + final boolean persistent, + final InternalMessageHeader header, + final Object messageBody) + { + + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + try + { + ObjectOutputStream os = new ObjectOutputStream(bytesOut); + os.writeObject(messageBody); + final byte[] bytes = bytesOut.toByteArray(); + + + final InternalMessageMetaData metaData = InternalMessageMetaData.create(persistent, header, bytes.length); + + + return new StoredMessage<InternalMessageMetaData>() + { + @Override + public InternalMessageMetaData getMetaData() + { + return metaData; + } + + @Override + public long getMessageNumber() + { + return messageNumber; + } + + @Override + public void addContent(final int offsetInMessage, final ByteBuffer src) + { + throw new UnsupportedOperationException(); + } + + @Override + public int getContent(final int offsetInMessage, final ByteBuffer dst) + { + ByteBuffer buffer = ByteBuffer.wrap(bytes); + buffer.position(offsetInMessage); + buffer = buffer.slice(); + if(dst.remaining() < buffer.remaining()) + { + buffer.limit(dst.remaining()); + } + int pos = dst.position(); + dst.put(buffer); + return dst.position()-pos; + } + + @Override + public ByteBuffer getContent(final int offsetInMessage, final int size) + { + return ByteBuffer.wrap(bytes,offsetInMessage,size); + } + + @Override + public StoreFuture flushToStore() + { + throw new UnsupportedOperationException(); + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageHeader.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageHeader.java new file mode 100644 index 0000000000..75c5a414f4 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageHeader.java @@ -0,0 +1,197 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.message.internal; + +import org.apache.qpid.server.message.AMQMessageHeader; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +public final class InternalMessageHeader implements AMQMessageHeader, Serializable +{ + private static final long serialVersionUID = 7219183903302678948L; + + private final LinkedHashMap<String, Object> _headers; + private final String _correlationId; + private final long _expiration; + private final String _userId; + private final String _appId; + private final String _messageId; + private final String _mimeType; + private final String _encoding; + private final byte _priority; + private final long _timestamp; + private final String _type; + private final String _replyTo; + private long _arrivalTime; + + public InternalMessageHeader(final Map<String, Object> headers, + final String correlationId, + final long expiration, + final String userId, + final String appId, + final String messageId, + final String mimeType, + final String encoding, + final byte priority, final long timestamp, final String type, final String replyTo) + { + _headers = headers == null ? new LinkedHashMap<String, Object>() + : new LinkedHashMap<String, Object>(headers); + + _correlationId = correlationId; + _expiration = expiration; + _userId = userId; + _appId = appId; + _messageId = messageId; + _mimeType = mimeType; + _encoding = encoding; + _priority = priority; + _timestamp = timestamp; + _type = type; + _replyTo = replyTo; + _arrivalTime = System.currentTimeMillis(); + } + + public InternalMessageHeader(final AMQMessageHeader header) + { + _correlationId = header.getCorrelationId(); + _expiration = header.getExpiration(); + _userId = header.getUserId(); + _appId = header.getAppId(); + _messageId = header.getMessageId(); + _mimeType = header.getMimeType(); + _encoding = header.getEncoding(); + _priority = header.getPriority(); + _timestamp = header.getTimestamp(); + _type = header.getType(); + _replyTo = header.getReplyTo(); + _headers = new LinkedHashMap<String, Object>(); + for(String headerName : header.getHeaderNames()) + { + _headers.put(headerName, header.getHeader(headerName)); + } + _arrivalTime = System.currentTimeMillis(); + } + + @Override + public String getCorrelationId() + { + return _correlationId; + } + + @Override + public long getExpiration() + { + return _expiration; + } + + @Override + public String getUserId() + { + return _userId; + } + + @Override + public String getAppId() + { + return _appId; + } + + @Override + public String getMessageId() + { + return _messageId; + } + + @Override + public String getMimeType() + { + return _mimeType; + } + + @Override + public String getEncoding() + { + return _encoding; + } + + @Override + public byte getPriority() + { + return _priority; + } + + @Override + public long getTimestamp() + { + return _timestamp; + } + + @Override + public String getType() + { + return _type; + } + + @Override + public String getReplyTo() + { + return _replyTo; + } + + @Override + public Object getHeader(final String name) + { + return _headers.get(name); + } + + @Override + public boolean containsHeaders(final Set<String> names) + { + return _headers.keySet().containsAll(names); + } + + @Override + public boolean containsHeader(final String name) + { + return _headers.keySet().contains(name); + } + + @Override + public Collection<String> getHeaderNames() + { + return Collections.unmodifiableCollection(_headers.keySet()); + } + + long getArrivalTime() + { + return _arrivalTime; + } + + public Map<String,Object> getHeaderMap() + { + return Collections.unmodifiableMap(new LinkedHashMap<String, Object>(_headers)); + } +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java new file mode 100644 index 0000000000..d7772657a2 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaData.java @@ -0,0 +1,95 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.message.internal; + +import org.apache.qpid.server.store.StorableMessageMetaData; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.nio.ByteBuffer; + +public class InternalMessageMetaData implements StorableMessageMetaData +{ + + + private boolean _isPersistent; + private byte[] _headerBytes; + private int _contentSize; + + public InternalMessageMetaData(final boolean isPersistent, final byte[] headerBytes, final int contentSize) + { + _isPersistent = isPersistent; + _headerBytes = headerBytes; + _contentSize = contentSize; + } + + @Override + public InternalMessageMetaDataType getType() + { + return InternalMessageMetaDataType.INSTANCE; + } + + @Override + public int getStorableSize() + { + return _headerBytes.length; + } + + @Override + public int writeToBuffer(final ByteBuffer dest) + { + dest.put(_headerBytes); + return _headerBytes.length; + } + + @Override + public int getContentSize() + { + return _contentSize; + } + + @Override + public boolean isPersistent() + { + return _isPersistent; + } + + static InternalMessageMetaData create(boolean persistent, final InternalMessageHeader header, int contentSize) + { + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + try + { + ObjectOutputStream os = new ObjectOutputStream(bytesOut); + os.writeObject(header); + byte[] bytes = bytesOut.toByteArray(); + + return new InternalMessageMetaData(persistent, bytes, contentSize); + + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaDataType.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaDataType.java new file mode 100644 index 0000000000..eb90599aef --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/message/internal/InternalMessageMetaDataType.java @@ -0,0 +1,76 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.message.internal; + +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.plugin.MessageMetaDataType; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.util.ByteBufferInputStream; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.nio.ByteBuffer; + +public class InternalMessageMetaDataType implements MessageMetaDataType<InternalMessageMetaData> +{ + public static final int INTERNAL_ORDINAL = 999; + public static final String TYPE = "INTERNAL"; + + @Override + public int ordinal() + { + return INTERNAL_ORDINAL; + } + + @Override + public InternalMessageMetaData createMetaData(final ByteBuffer buf) + { + try + { + ObjectInputStream is = new ObjectInputStream(new ByteBufferInputStream(buf)); + InternalMessageMetaData metaData = (InternalMessageMetaData) is.readObject(); + return metaData; + } + catch (IOException e) + { + throw new RuntimeException("Cannot decode message header"); + } + catch (ClassNotFoundException e) + { + throw new RuntimeException(e); + } + + } + + @Override + public ServerMessage<InternalMessageMetaData> createMessage(final StoredMessage<InternalMessageMetaData> msg) + { + return new InternalMessage(msg); + } + + @Override + public String getType() + { + return TYPE; + } + + public static final InternalMessageMetaDataType INSTANCE = new InternalMessageMetaDataType(); +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java index d96bef0463..20d0166c9d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AccessControlProvider.java @@ -27,9 +27,7 @@ import org.apache.qpid.server.security.AccessControl; public interface AccessControlProvider extends ConfiguredObject { - public static final String ID = "id"; public static final String DESCRIPTION = "description"; - public static final String NAME = "name"; public static final String STATE = "state"; public static final String DURABLE = "durable"; public static final String LIFETIME_POLICY = "lifetimePolicy"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AmqpManagement.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AmqpManagement.java new file mode 100644 index 0000000000..43b77bfe1d --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AmqpManagement.java @@ -0,0 +1,35 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) + +public @interface AmqpManagement +{ + String[] attributes(); + String[] operations(); + boolean managesChildren() default false; // for objects that manage children, a management node needs to be created + boolean creatable() default true; + String defaultImplementation() default ""; // in this case the class/interface itself is to be used +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java index f75d0211cb..c111f40cc8 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java @@ -29,9 +29,7 @@ import org.apache.qpid.server.security.SubjectCreator; public interface AuthenticationProvider extends ConfiguredObject { - public static final String ID = "id"; public static final String DESCRIPTION = "description"; - public static final String NAME = "name"; public static final String STATE = "state"; public static final String DURABLE = "durable"; public static final String LIFETIME_POLICY = "lifetimePolicy"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java index fdb009386c..d5f833e393 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Binding.java @@ -43,9 +43,7 @@ public interface Binding extends ConfiguredObject public String ARGUMENTS = "arguments"; public String CREATED = "created"; public String DURABLE = "durable"; - public String ID = "id"; public String LIFETIME_POLICY = "lifetimePolicy"; - public String NAME = "name"; public String STATE = "state"; public String TIME_TO_LIVE = "timeToLive"; public String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java index 0c1a6de58b..5df6d9475e 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java @@ -48,9 +48,7 @@ public interface Broker extends ConfiguredObject String SUPPORTED_PREFERENCES_PROVIDERS_TYPES = "supportedPreferencesProviderTypes"; String CREATED = "created"; String DURABLE = "durable"; - String ID = "id"; String LIFETIME_POLICY = "lifetimePolicy"; - String NAME = "name"; String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java index 6762e3dd93..ab9c60573a 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java @@ -25,12 +25,22 @@ import java.util.Collection; import java.util.Map; import java.util.UUID; +@AmqpManagement( + attributes = { + ConfiguredObject.ID, + ConfiguredObject.NAME + }, + operations = {}, + creatable = false +) /** * An object that can be "managed" (eg via the web interface) and usually read from configuration. */ public interface ConfiguredObject { - + public static final String ID = "id"; + public static final String NAME = "name"; +// public static final String TYPE = "type"; /** * Get the universally unique identifier for the object * diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java index 31d40c7c3e..a7350f528c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java @@ -24,6 +24,32 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +@AmqpManagement( + attributes = { + Connection.ID, + Connection.NAME, + Connection.STATE, + Connection.DURABLE, + Connection.LIFETIME_POLICY, + Connection.TIME_TO_LIVE, + Connection.CREATED, + Connection.UPDATED, + Connection.CLIENT_ID, + Connection.CLIENT_VERSION, + Connection.INCOMING, + Connection.LOCAL_ADDRESS, + Connection.PRINCIPAL, + Connection.PROPERTIES, + Connection.REMOTE_ADDRESS, + Connection.REMOTE_PROCESS_NAME, + Connection.REMOTE_PROCESS_PID, + Connection.SESSION_COUNT_LIMIT, + Connection.TRANSPORT, + Connection.PORT + }, + operations = {}, + creatable = false +) public interface Connection extends ConfiguredObject { @@ -59,8 +85,6 @@ public interface Connection extends ConfiguredObject // Attributes - public static final String ID = "id"; - public static final String NAME = "name"; public static final String STATE = "state"; public static final String DURABLE = "durable"; public static final String LIFETIME_POLICY = "lifetimePolicy"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java index 958177e713..6f8726d0c8 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java @@ -33,9 +33,7 @@ public interface Consumer extends ConfiguredObject public String SETTLEMENT_MODE = "settlementMode"; public String CREATED = "created"; public String DURABLE = "durable"; - public String ID = "id"; public String LIFETIME_POLICY = "lifetimePolicy"; - public String NAME = "name"; public String STATE = "state"; public String TIME_TO_LIVE = "timeToLive"; public String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java index e63c71e955..c4575a7359 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Exchange.java @@ -25,6 +25,22 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; +@AmqpManagement( + attributes = { + Exchange.ID, + Exchange.NAME, + Exchange.STATE, + Exchange.DURABLE, + Exchange.LIFETIME_POLICY, + Exchange.TIME_TO_LIVE, + Exchange.CREATED, + Exchange.UPDATED, + Exchange.ALTERNATE_EXCHANGE, + Exchange.TYPE + }, + operations = {} +) + public interface Exchange extends ConfiguredObject { String BINDING_COUNT = "bindingCount"; @@ -47,9 +63,7 @@ public interface Exchange extends ConfiguredObject String CREATED = "created"; String DURABLE = "durable"; - String ID = "id"; String LIFETIME_POLICY = "lifetimePolicy"; - String NAME = "name"; String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java index aacd515107..e62949708d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Group.java @@ -27,9 +27,7 @@ public interface Group extends ConfiguredObject { String CREATED = "created"; String DURABLE = "durable"; - String ID = "id"; String LIFETIME_POLICY = "lifetimePolicy"; - String NAME = "name"; String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java index 6832cc6fa6..46dd6ec3e2 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupMember.java @@ -27,9 +27,7 @@ public interface GroupMember extends ConfiguredObject { String CREATED = "created"; String DURABLE = "durable"; - String ID = "id"; String LIFETIME_POLICY = "lifetimePolicy"; - String NAME = "name"; String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java index 9016f97927..e5c64ec882 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/GroupProvider.java @@ -27,9 +27,7 @@ import java.util.Set; public interface GroupProvider extends ConfiguredObject { - public static final String ID = "id"; public static final String DESCRIPTION = "description"; - public static final String NAME = "name"; public static final String STATE = "state"; public static final String DURABLE = "durable"; public static final String LIFETIME_POLICY = "lifetimePolicy"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java index ab909390bd..1e1cbb7cef 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/KeyStore.java @@ -28,8 +28,6 @@ import javax.net.ssl.KeyManager; public interface KeyStore extends ConfiguredObject { - String ID = "id"; - String NAME = "name"; String DURABLE = "durable"; String LIFETIME_POLICY = "lifetimePolicy"; String STATE = "state"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java index b9503a5841..7cdea9d12c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Plugin.java @@ -29,9 +29,7 @@ public interface Plugin extends ConfiguredObject //Hack, using it for the class name only for consistency with the other things. String CREATED = "created"; String DURABLE = "durable"; - String ID = "id"; String LIFETIME_POLICY = "lifetimePolicy"; - String NAME = "name"; String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java index 60d62e3f27..9458ac4120 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java @@ -29,9 +29,7 @@ public interface Port extends ConfiguredObject { String CREATED = "created"; String DURABLE = "durable"; - String ID = "id"; String LIFETIME_POLICY = "lifetimePolicy"; - String NAME = "name"; String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java index fadd036a58..c895ce36f8 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java @@ -29,8 +29,6 @@ import java.util.Set; public interface PreferencesProvider extends ConfiguredObject { - String ID = "id"; - String NAME = "name"; String TYPE = "type"; String CREATED = "created"; String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java index ae2031bd71..dc65c6ef81 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java @@ -25,6 +25,40 @@ import java.util.Collection; import java.util.Collections; import org.apache.qpid.server.queue.QueueEntryVisitor; +@AmqpManagement( + attributes = { + Queue.ID, + Queue.NAME, + Queue.DESCRIPTION, + Queue.STATE, + Queue.DURABLE, + Queue.LIFETIME_POLICY, + Queue.TIME_TO_LIVE, + Queue.CREATED, + Queue.UPDATED, + Queue.QUEUE_TYPE, + Queue.ALTERNATE_EXCHANGE, + Queue.EXCLUSIVE, + Queue.OWNER, + Queue.NO_LOCAL, + Queue.LVQ_KEY, + Queue.SORT_KEY, + Queue.MESSAGE_GROUP_KEY, + Queue.MESSAGE_GROUP_SHARED_GROUPS, + Queue.MAXIMUM_DELIVERY_ATTEMPTS, + Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, + Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, + Queue.QUEUE_FLOW_STOPPED, + Queue.ALERT_THRESHOLD_MESSAGE_AGE, + Queue.ALERT_THRESHOLD_MESSAGE_SIZE, + Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, + Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, + Queue.ALERT_REPEAT_GAP, + Queue.PRIORITIES + }, + operations = {} +) + public interface Queue extends ConfiguredObject { public static final String BINDING_COUNT = "bindingCount"; @@ -69,9 +103,7 @@ public interface Queue extends ConfiguredObject - public static final String ID = "id"; public static final String DESCRIPTION = "description"; - public static final String NAME = "name"; public static final String STATE = "state"; public static final String DURABLE = "durable"; public static final String LIFETIME_POLICY = "lifetimePolicy"; @@ -98,7 +130,7 @@ public interface Queue extends ConfiguredObject public static final String QUEUE_FLOW_RESUME_SIZE_BYTES = "queueFlowResumeSizeBytes"; public static final String QUEUE_FLOW_STOPPED = "queueFlowStopped"; public static final String SORT_KEY = "sortKey"; - public static final String TYPE = "type"; + public static final String QUEUE_TYPE = "queueType"; public static final String PRIORITIES = "priorities"; public static final String CREATE_DLQ_ON_CREATION = "x-qpid-dlq-enabled"; // TODO - this value should change @@ -118,7 +150,7 @@ public interface Queue extends ConfiguredObject TIME_TO_LIVE, CREATED, UPDATED, - TYPE, + QUEUE_TYPE, ALTERNATE_EXCHANGE, EXCLUSIVE, OWNER, diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java index 355a1cf3b1..40ff3ef686 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Session.java @@ -51,8 +51,6 @@ public interface Session extends ConfiguredObject XA_TRANSACTION_BRANCH_SUSPENDS)); - public static final String ID = "id"; - public static final String NAME = "name"; public static final String STATE = "state"; public static final String DURABLE = "durable"; public static final String LIFETIME_POLICY = "lifetimePolicy"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java index d313e1832f..e4eac98bc0 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/TrustStore.java @@ -28,8 +28,6 @@ import javax.net.ssl.TrustManager; public interface TrustStore extends ConfiguredObject { - String ID = "id"; - String NAME = "name"; String DURABLE = "durable"; String LIFETIME_POLICY = "lifetimePolicy"; String STATE = "state"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java index cf1a688634..9d7dd7c0cd 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/User.java @@ -30,9 +30,7 @@ public interface User extends ConfiguredObject { String CREATED = "created"; String DURABLE = "durable"; - String ID = "id"; String LIFETIME_POLICY = "lifetimePolicy"; - String NAME = "name"; String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String UPDATED = "updated"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java index 2b5176aa65..f0241f8b30 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java @@ -31,6 +31,43 @@ import java.util.Collection; import java.util.Collections; import java.util.Map; +@AmqpManagement( + attributes = { + VirtualHost.ID, + VirtualHost.NAME, + VirtualHost.TYPE, + VirtualHost.STATE, + VirtualHost.DURABLE, + VirtualHost.LIFETIME_POLICY, + VirtualHost.TIME_TO_LIVE, + VirtualHost.CREATED, + VirtualHost.UPDATED, + VirtualHost.SUPPORTED_EXCHANGE_TYPES, + VirtualHost.SUPPORTED_QUEUE_TYPES, + VirtualHost.QUEUE_DEAD_LETTER_QUEUE_ENABLED, + VirtualHost.HOUSEKEEPING_CHECK_PERIOD, + VirtualHost.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, + VirtualHost.QUEUE_FLOW_CONTROL_SIZE_BYTES, + VirtualHost.QUEUE_FLOW_RESUME_SIZE_BYTES, + VirtualHost.CONFIG_STORE_TYPE, + VirtualHost.CONFIG_STORE_PATH, + VirtualHost.STORE_TYPE, + VirtualHost.STORE_PATH, + VirtualHost.STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, + VirtualHost.STORE_TRANSACTION_IDLE_TIMEOUT_WARN, + VirtualHost.STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, + VirtualHost.STORE_TRANSACTION_OPEN_TIMEOUT_WARN, + VirtualHost.QUEUE_ALERT_REPEAT_GAP, + VirtualHost.QUEUE_ALERT_THRESHOLD_MESSAGE_AGE, + VirtualHost.QUEUE_ALERT_THRESHOLD_MESSAGE_SIZE, + VirtualHost.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, + VirtualHost.QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, + VirtualHost.CONFIG_PATH + }, + operations = {}, + managesChildren = true +) + public interface VirtualHost extends ConfiguredObject { // Statistics @@ -81,9 +118,7 @@ public interface VirtualHost extends ConfiguredObject String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes"; String CREATED = "created"; String DURABLE = "durable"; - String ID = "id"; String LIFETIME_POLICY = "lifetimePolicy"; - String NAME = "name"; String STATE = "state"; String TIME_TO_LIVE = "timeToLive"; String TYPE = "type"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java index d59b13902b..e2c29ede51 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java @@ -26,13 +26,13 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import org.apache.qpid.AMQException; import org.apache.qpid.AMQStoreException; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.message.MessageSource; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.ConfiguredObjectFinder; import org.apache.qpid.server.model.Exchange; @@ -49,8 +49,9 @@ import org.apache.qpid.server.store.DurableConfigurationStoreHelper; import org.apache.qpid.server.consumer.Consumer; import org.apache.qpid.server.util.MapValueConverter; -final class QueueAdapter extends AbstractAdapter implements Queue, - AMQQueue.ConsumerRegistrationListener, AMQQueue.NotificationListener +final class QueueAdapter<Q extends AMQQueue<?,Q,?>> extends AbstractAdapter implements Queue, + MessageSource.ConsumerRegistrationListener<Q>, + AMQQueue.NotificationListener { @SuppressWarnings("serial") static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>(){{ @@ -66,10 +67,11 @@ final class QueueAdapter extends AbstractAdapter implements Queue, put(DESCRIPTION, String.class); }}); - private final AMQQueue _queue; + private final AMQQueue<?,Q,?> _queue; + private final Map<Binding, BindingAdapter> _bindingAdapters = new HashMap<Binding, BindingAdapter>(); - private Map<Consumer, ConsumerAdapter> _consumerAdapters = + private final Map<Consumer, ConsumerAdapter> _consumerAdapters = new HashMap<Consumer, ConsumerAdapter>(); @@ -77,7 +79,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, private QueueStatisticsAdapter _statistics; private QueueNotificationListener _queueNotificationListener; - public QueueAdapter(final VirtualHostAdapter virtualHostAdapter, final AMQQueue queue) + public QueueAdapter(final VirtualHostAdapter virtualHostAdapter, final AMQQueue<?,Q,?> queue) { super(queue.getId(), virtualHostAdapter.getTaskExecutor()); _vhost = virtualHostAdapter; @@ -124,11 +126,10 @@ final class QueueAdapter extends AbstractAdapter implements Queue, private void populateConsumers() { - Collection<Consumer> actualConsumers = _queue.getConsumers(); + Collection<? extends Consumer> actualConsumers = _queue.getConsumers(); synchronized (_consumerAdapters) { - Iterator<Consumer> iter = _consumerAdapters.keySet().iterator(); for(Consumer consumer : actualConsumers) { if(!_consumerAdapters.containsKey(consumer)) @@ -321,7 +322,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, { // TODO } - else if(TYPE.equals(name)) + else if(QUEUE_TYPE.equals(name)) { // TODO } @@ -396,9 +397,10 @@ final class QueueAdapter extends AbstractAdapter implements Queue, } else if(LVQ_KEY.equals(name)) { - if(_queue instanceof ConflationQueue) + AMQQueue queue = _queue; + if(queue instanceof ConflationQueue) { - return ((ConflationQueue)_queue).getConflationKey(); + return ((ConflationQueue)queue).getConflationKey(); } } else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name)) @@ -427,22 +429,24 @@ final class QueueAdapter extends AbstractAdapter implements Queue, } else if(SORT_KEY.equals(name)) { - if(_queue instanceof SortedQueue) + AMQQueue queue = _queue; + if(queue instanceof SortedQueue) { - return ((SortedQueue)_queue).getSortedPropertyName(); + return ((SortedQueue)queue).getSortedPropertyName(); } } - else if(TYPE.equals(name)) + else if(QUEUE_TYPE.equals(name)) { - if(_queue instanceof SortedQueue) + AMQQueue queue = _queue; + if(queue instanceof SortedQueue) { return "sorted"; } - if(_queue instanceof ConflationQueue) + if(queue instanceof ConflationQueue) { return "lvq"; } - if(_queue instanceof AMQPriorityQueue) + if(queue instanceof PriorityQueue) { return "priority"; } @@ -486,9 +490,10 @@ final class QueueAdapter extends AbstractAdapter implements Queue, } else if(PRIORITIES.equals(name)) { - if(_queue instanceof AMQPriorityQueue) + AMQQueue queue = _queue; + if(queue instanceof PriorityQueue) { - return ((AMQPriorityQueue)_queue).getPriorities(); + return ((PriorityQueue)queue).getPriorities(); } } return super.getAttribute(name); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java index f2ce20c74d..c43dc34d2f 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -66,7 +66,6 @@ import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; @@ -190,7 +189,10 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { if(!_exchangeAdapters.containsKey(exchange)) { - _exchangeAdapters.put(exchange, new ExchangeAdapter(this,exchange)); + final ExchangeAdapter adapter = new ExchangeAdapter(this, exchange); + _exchangeAdapters.put(exchange, adapter); + childAdded(adapter); + } } } @@ -208,7 +210,9 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { if(!_queueAdapters.containsKey(queue)) { - _queueAdapters.put(queue, new QueueAdapter(this, queue)); + final QueueAdapter adapter = new QueueAdapter(this, queue); + _queueAdapters.put(queue, adapter); + childAdded(adapter); } } } @@ -381,9 +385,9 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { attributes = new HashMap<String, Object>(attributes); - if (attributes.containsKey(Queue.TYPE)) + if (attributes.containsKey(Queue.QUEUE_TYPE)) { - String typeAttribute = MapValueConverter.getStringAttribute(Queue.TYPE, attributes, null); + String typeAttribute = MapValueConverter.getStringAttribute(Queue.QUEUE_TYPE, attributes, null); QueueType queueType = null; try { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemNodeCreator.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemNodeCreator.java index a117524254..5b371c0851 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemNodeCreator.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemNodeCreator.java @@ -31,6 +31,7 @@ public interface SystemNodeCreator extends Pluggable void removeSystemNode(MessageNode node); VirtualHost getVirtualHost(); + org.apache.qpid.server.model.VirtualHost getVirtualHostModel(); } void register(SystemNodeRegistry registry); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java index 75994f6d81..28fadd4162 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java @@ -27,12 +27,11 @@ import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.SimpleAMQQueue; /** * Session model interface. * Extends {@link Comparable} to allow objects to be inserted into a {@link ConcurrentSkipListSet} - * when monitoring the blocking and blocking of queues/sessions in {@link SimpleAMQQueue}. + * when monitoring the blocking and blocking of queues/sessions in {@link AMQQueue}. */ public interface AMQSessionModel extends Comparable<AMQSessionModel> { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index 62927edc29..76477a0a9b 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java @@ -37,8 +37,8 @@ import java.util.Collection; import java.util.List; import java.util.Set; -public interface AMQQueue<C extends Consumer> extends Comparable<AMQQueue<C>>, ExchangeReferrer, BaseQueue, - MessageSource<C>, CapacityChecker, MessageDestination +public interface AMQQueue<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, C extends Consumer> + extends Comparable<Q>, ExchangeReferrer, BaseQueue<C>, MessageSource<C,Q>, CapacityChecker, MessageDestination { public interface NotificationListener @@ -87,41 +87,35 @@ public interface AMQQueue<C extends Consumer> extends Comparable<AMQQueue<C>>, E int getMessageCount(); - int getUndeliveredMessageCount(); - long getQueueDepth(); - long getReceivedMessageCount(); - long getOldestMessageArrivalTime(); boolean isDeleted(); int delete() throws AMQException; - void requeue(QueueEntry entry); + void requeue(E entry); - void dequeue(QueueEntry entry, Consumer sub); + void dequeue(E entry); - void decrementUnackedMsgCount(QueueEntry queueEntry); + void decrementUnackedMsgCount(E queueEntry); - boolean resend(final QueueEntry entry, final Consumer consumer) throws AMQException; + boolean resend(final E entry, final C consumer) throws AMQException; void addQueueDeleteTask(Action<AMQQueue> task); void removeQueueDeleteTask(Action<AMQQueue> task); - List<QueueEntry> getMessagesOnTheQueue(); - - List<QueueEntry> getMessagesOnTheQueue(long fromMessageId, long toMessageId); + List<E> getMessagesOnTheQueue(); List<Long> getMessagesOnTheQueue(int num); List<Long> getMessagesOnTheQueue(int num, int offset); - QueueEntry getMessageOnTheQueue(long messageId); + E getMessageOnTheQueue(long messageId); /** * Returns a list of QueEntries from a given range of queue positions, eg messages 5 to 10 on the queue. @@ -132,9 +126,9 @@ public interface AMQQueue<C extends Consumer> extends Comparable<AMQQueue<C>>, E * @param toPosition * @return */ - public List<QueueEntry> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition); + public List<E> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition); - void visit(QueueEntryVisitor visitor); + void visit(QueueEntryVisitor<E> visitor); long getMaximumMessageSize(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index 38c205bc00..4e0a9048e1 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java @@ -288,11 +288,11 @@ public class AMQQueueFactory implements QueueFactory } else if(priorities > 1) { - q = new AMQPriorityQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments, priorities); + q = new PriorityQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments, priorities); } else { - q = new SimpleAMQQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments); + q = new StandardQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments); } q.setDeleteOnNoConsumers(deleteOnNoConsumer); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AssignedConsumerMessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AssignedConsumerMessageGroupManager.java index a9b36c1b24..efc82c0ab4 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AssignedConsumerMessageGroupManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AssignedConsumerMessageGroupManager.java @@ -28,7 +28,7 @@ import java.util.Iterator; import java.util.concurrent.ConcurrentHashMap; -public class AssignedConsumerMessageGroupManager implements MessageGroupManager +public class AssignedConsumerMessageGroupManager<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements MessageGroupManager<E,Q,L> { private static final Logger _logger = LoggerFactory.getLogger(AssignedConsumerMessageGroupManager.class); @@ -53,25 +53,18 @@ public class AssignedConsumerMessageGroupManager implements MessageGroupManager return val; } - public QueueConsumer getAssignedConsumer(final QueueEntry entry) + public QueueConsumer getAssignedConsumer(final E entry) { Object groupVal = entry.getMessage().getMessageHeader().getHeader(_groupId); return groupVal == null ? null : _groupMap.get(groupVal.hashCode() & _groupMask); } - public boolean acceptMessage(QueueConsumer sub, QueueEntry entry) + public boolean acceptMessage(QueueConsumer<?,E,Q,L> sub, E entry) { - if(assignMessage(sub, entry)) - { - return entry.acquire(sub); - } - else - { - return false; - } + return assignMessage(sub, entry) && entry.acquire(sub); } - private boolean assignMessage(QueueConsumer sub, QueueEntry entry) + private boolean assignMessage(QueueConsumer sub, E entry) { Object groupVal = entry.getMessage().getMessageHeader().getHeader(_groupId); if(groupVal == null) @@ -105,16 +98,16 @@ public class AssignedConsumerMessageGroupManager implements MessageGroupManager } } - public QueueEntry findEarliestAssignedAvailableEntry(QueueConsumer sub) + public E findEarliestAssignedAvailableEntry(QueueConsumer sub) { EntryFinder visitor = new EntryFinder(sub); sub.getQueue().visit(visitor); return visitor.getEntry(); } - private class EntryFinder implements QueueEntryVisitor + private class EntryFinder implements QueueEntryVisitor<E> { - private QueueEntry _entry; + private E _entry; private QueueConsumer _sub; public EntryFinder(final QueueConsumer sub) @@ -122,7 +115,7 @@ public class AssignedConsumerMessageGroupManager implements MessageGroupManager _sub = sub; } - public boolean visit(final QueueEntry entry) + public boolean visit(final E entry) { if(!entry.isAvailable()) { @@ -148,7 +141,7 @@ public class AssignedConsumerMessageGroupManager implements MessageGroupManager } } - public QueueEntry getEntry() + public E getEntry() { return _entry; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java index c1c3bd37e6..31c54dcdd2 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java @@ -28,9 +28,9 @@ import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.store.TransactionLogResource; import org.apache.qpid.server.util.Action; -public interface BaseQueue extends TransactionLogResource +public interface BaseQueue<C extends Consumer> extends TransactionLogResource { - void enqueue(ServerMessage message, Action<MessageInstance<? extends Consumer>> action) throws AMQException; + void enqueue(ServerMessage message, Action<? super MessageInstance<?,C>> action) throws AMQException; boolean isDurable(); boolean isDeleted(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java index c2813bb7a5..a1ff51959c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueue.java @@ -26,7 +26,7 @@ import java.util.UUID; import org.apache.qpid.server.virtualhost.VirtualHost; -public class ConflationQueue extends SimpleAMQQueue +public class ConflationQueue extends SimpleAMQQueue<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList> { protected ConflationQueue(UUID id, String name, @@ -42,7 +42,7 @@ public class ConflationQueue extends SimpleAMQQueue public String getConflationKey() { - return ((ConflationQueueList) getEntries()).getConflationKey(); + return getEntries().getConflationKey(); } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java index 7469e95394..a98a4ac144 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java @@ -32,23 +32,38 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; -public class ConflationQueueList extends SimpleQueueEntryList +public class ConflationQueueList extends OrderedQueueEntryList<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList> { private static final Logger LOGGER = LoggerFactory.getLogger(ConflationQueueList.class); + private static final HeadCreator<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList> HEAD_CREATOR = new HeadCreator<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList>() + { + + @Override + public ConflationQueueEntry createHead(final ConflationQueueList list) + { + return list.createHead(); + } + }; + private final String _conflationKey; - private final ConcurrentHashMap<Object, AtomicReference<QueueEntry>> _latestValuesMap = - new ConcurrentHashMap<Object, AtomicReference<QueueEntry>>(); + private final ConcurrentHashMap<Object, AtomicReference<ConflationQueueEntry>> _latestValuesMap = + new ConcurrentHashMap<Object, AtomicReference<ConflationQueueEntry>>(); - private final QueueEntry _deleteInProgress = new SimpleQueueEntryImpl(this); - private final QueueEntry _newerEntryAlreadyBeenAndGone = new SimpleQueueEntryImpl(this); + private final ConflationQueueEntry _deleteInProgress = new ConflationQueueEntry(this); + private final ConflationQueueEntry _newerEntryAlreadyBeenAndGone = new ConflationQueueEntry(this); - public ConflationQueueList(AMQQueue<QueueConsumer> queue, String conflationKey) + public ConflationQueueList(ConflationQueue queue, String conflationKey) { - super(queue); + super(queue, HEAD_CREATOR); _conflationKey = conflationKey; } + private ConflationQueueEntry createHead() + { + return new ConflationQueueEntry(this); + } + public String getConflationKey() { return _conflationKey; @@ -66,7 +81,7 @@ public class ConflationQueueList extends SimpleQueueEntryList @Override public ConflationQueueEntry add(final ServerMessage message) { - final ConflationQueueEntry addedEntry = (ConflationQueueEntry) (super.add(message)); + final ConflationQueueEntry addedEntry = super.add(message); final Object keyValue = message.getMessageHeader().getHeader(_conflationKey); if (keyValue != null) @@ -76,14 +91,14 @@ public class ConflationQueueList extends SimpleQueueEntryList LOGGER.debug("Adding entry " + addedEntry + " for message " + message.getMessageNumber() + " with conflation key " + keyValue); } - final AtomicReference<QueueEntry> referenceToEntry = new AtomicReference<QueueEntry>(addedEntry); - AtomicReference<QueueEntry> entryReferenceFromMap = null; - QueueEntry entryFromMap; + final AtomicReference<ConflationQueueEntry> referenceToEntry = new AtomicReference<ConflationQueueEntry>(addedEntry); + AtomicReference<ConflationQueueEntry> entryReferenceFromMap; + ConflationQueueEntry entryFromMap; // Iterate until we have got a valid atomic reference object and either the referent is newer than the current // entry, or the current entry has replaced it in the reference. Note that the _deletedEntryPlaceholder is a special value // indicating that the reference object is no longer valid (it is being removed from the map). - boolean keepTryingToUpdateEntryReference = true; + boolean keepTryingToUpdateEntryReference; do { do @@ -139,16 +154,16 @@ public class ConflationQueueList extends SimpleQueueEntryList * adds and removes during execution of this method.</li> * </ul> */ - private AtomicReference<QueueEntry> getOrPutIfAbsent(final Object key, final AtomicReference<QueueEntry> referenceToAddedValue) + private AtomicReference<ConflationQueueEntry> getOrPutIfAbsent(final Object key, final AtomicReference<ConflationQueueEntry> referenceToAddedValue) { - AtomicReference<QueueEntry> latestValueReference = _latestValuesMap.putIfAbsent(key, referenceToAddedValue); + AtomicReference<ConflationQueueEntry> latestValueReference = _latestValuesMap.putIfAbsent(key, referenceToAddedValue); if(latestValueReference == null) { latestValueReference = _latestValuesMap.get(key); if(latestValueReference == null) { - return new AtomicReference<QueueEntry>(_newerEntryAlreadyBeenAndGone); + return new AtomicReference<ConflationQueueEntry>(_newerEntryAlreadyBeenAndGone); } } return latestValueReference; @@ -177,12 +192,17 @@ public class ConflationQueueList extends SimpleQueueEntryList } } - private final class ConflationQueueEntry extends SimpleQueueEntryImpl + final class ConflationQueueEntry extends OrderedQueueEntry<ConflationQueueEntry, ConflationQueue, ConflationQueueList> { - private AtomicReference<QueueEntry> _latestValueReference; + private AtomicReference<ConflationQueueEntry> _latestValueReference; + + private ConflationQueueEntry(final ConflationQueueList queueEntryList) + { + super(queueEntryList); + } - public ConflationQueueEntry(SimpleQueueEntryList queueEntryList, ServerMessage message) + public ConflationQueueEntry(ConflationQueueList queueEntryList, ServerMessage message) { super(queueEntryList, message); } @@ -206,7 +226,7 @@ public class ConflationQueueList extends SimpleQueueEntryList } - public void setLatestValueReference(final AtomicReference<QueueEntry> latestValueReference) + public void setLatestValueReference(final AtomicReference<ConflationQueueEntry> latestValueReference) { _latestValueReference = latestValueReference; } @@ -227,12 +247,12 @@ public class ConflationQueueList extends SimpleQueueEntryList /** * Exposed purposes of unit test only. */ - Map<Object, AtomicReference<QueueEntry>> getLatestValuesMap() + Map<Object, AtomicReference<ConflationQueueEntry>> getLatestValuesMap() { return Collections.unmodifiableMap(_latestValuesMap); } - static class Factory implements QueueEntryListFactory + static class Factory implements QueueEntryListFactory<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList> { private final String _conflationKey; @@ -241,7 +261,8 @@ public class ConflationQueueList extends SimpleQueueEntryList _conflationKey = conflationKey; } - public ConflationQueueList createQueueEntryList(AMQQueue queue) + @Override + public ConflationQueueList createQueueEntryList(final ConflationQueue queue) { return new ConflationQueueList(queue, _conflationKey); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java index 4c74e5ba0b..e67591ae07 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java @@ -32,22 +32,22 @@ import org.apache.qpid.server.message.ServerMessage; import java.util.HashMap; import java.util.Map; -public class DefinedGroupMessageGroupManager implements MessageGroupManager +public class DefinedGroupMessageGroupManager<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements MessageGroupManager<E,Q,L> { private static final Logger _logger = LoggerFactory.getLogger(DefinedGroupMessageGroupManager.class); private final String _groupId; private final String _defaultGroup; private final Map<Object, Group> _groupMap = new HashMap<Object, Group>(); - private final ConsumerResetHelper _resetHelper; + private final ConsumerResetHelper<E,Q,L> _resetHelper; private final class Group { private final Object _group; - private QueueConsumer _consumer; + private QueueConsumer<?,E,Q,L> _consumer; private int _activeCount; - private Group(final Object key, final QueueConsumer consumer) + private Group(final Object key, final QueueConsumer<?,E,Q,L> consumer) { _group = key; _consumer = consumer; @@ -104,7 +104,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager return !(_consumer == null || (_activeCount == 0 && _consumer.isClosed())); } - public QueueConsumer getConsumer() + public QueueConsumer<?,E,Q,L> getConsumer() { return _consumer; } @@ -120,14 +120,14 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager } } - public DefinedGroupMessageGroupManager(final String groupId, String defaultGroup, ConsumerResetHelper resetHelper) + public DefinedGroupMessageGroupManager(final String groupId, String defaultGroup, ConsumerResetHelper<E,Q,L> resetHelper) { _groupId = groupId; _defaultGroup = defaultGroup; _resetHelper = resetHelper; } - public synchronized QueueConsumer getAssignedConsumer(final QueueEntry entry) + public synchronized QueueConsumer<?,E,Q,L> getAssignedConsumer(final E entry) { Object groupId = getKey(entry); @@ -135,19 +135,12 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager return group == null || !group.isValid() ? null : group.getConsumer(); } - public synchronized boolean acceptMessage(final QueueConsumer sub, final QueueEntry entry) + public synchronized boolean acceptMessage(final QueueConsumer<?,E,Q,L> sub, final E entry) { - if(assignMessage(sub, entry)) - { - return entry.acquire(sub); - } - else - { - return false; - } + return assignMessage(sub, entry) && entry.acquire(sub); } - private boolean assignMessage(final QueueConsumer sub, final QueueEntry entry) + private boolean assignMessage(final QueueConsumer<?,E,Q,L> sub, final E entry) { Object groupId = getKey(entry); Group group = _groupMap.get(groupId); @@ -171,7 +164,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager if(assignedSub == sub) { - entry.addStateChangeListener(new GroupStateChangeListener(group, entry)); + entry.addStateChangeListener(new GroupStateChangeListener(group)); return true; } else @@ -180,16 +173,16 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager } } - public synchronized QueueEntry findEarliestAssignedAvailableEntry(final QueueConsumer sub) + public synchronized E findEarliestAssignedAvailableEntry(final QueueConsumer<?,E,Q,L> sub) { EntryFinder visitor = new EntryFinder(sub); sub.getQueue().visit(visitor); return visitor.getEntry(); } - private class EntryFinder implements QueueEntryVisitor + private class EntryFinder implements QueueEntryVisitor<E> { - private QueueEntry _entry; + private E _entry; private QueueConsumer _sub; public EntryFinder(final QueueConsumer sub) @@ -197,7 +190,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager _sub = sub; } - public boolean visit(final QueueEntry entry) + public boolean visit(final E entry) { if(!entry.isAvailable()) { @@ -218,7 +211,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager } } - public QueueEntry getEntry() + public E getEntry() { return _entry; } @@ -229,7 +222,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager { } - private Object getKey(QueueEntry entry) + private Object getKey(E entry) { ServerMessage message = entry.getMessage(); AMQMessageHeader messageHeader = message == null ? null : message.getMessageHeader(); @@ -241,17 +234,16 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager return groupVal; } - private class GroupStateChangeListener implements StateChangeListener<MessageInstance<QueueConsumer>, QueueEntry.State> + private class GroupStateChangeListener implements StateChangeListener<MessageInstance<?, ? extends QueueConsumer>, QueueEntry.State> { private final Group _group; - public GroupStateChangeListener(final Group group, - final MessageInstance<QueueConsumer> entry) + public GroupStateChangeListener(final Group group) { _group = group; } - public void stateChanged(final MessageInstance<QueueConsumer> entry, + public void stateChanged(final MessageInstance<?, ? extends QueueConsumer> entry, final MessageInstance.State oldState, final MessageInstance.State newState) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java index 740a96bf2d..ba9dbc8a70 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/MessageGroupManager.java @@ -20,20 +20,20 @@ */ package org.apache.qpid.server.queue; -public interface MessageGroupManager +public interface MessageGroupManager<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> { - public interface ConsumerResetHelper + public interface ConsumerResetHelper<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> { - public void resetSubPointersForGroups(QueueConsumer consumer, boolean clearAssignments); + public void resetSubPointersForGroups(QueueConsumer<?,E,Q,L> consumer, boolean clearAssignments); - boolean isEntryAheadOfConsumer(QueueEntry entry, QueueConsumer sub); + boolean isEntryAheadOfConsumer(E entry, QueueConsumer<?,E,Q,L> sub); } - QueueConsumer getAssignedConsumer(QueueEntry entry); + QueueConsumer getAssignedConsumer(E entry); - boolean acceptMessage(QueueConsumer sub, QueueEntry entry); + boolean acceptMessage(QueueConsumer<?,E,Q,L> sub, E entry); - QueueEntry findEarliestAssignedAvailableEntry(QueueConsumer sub); + E findEarliestAssignedAvailableEntry(QueueConsumer<?,E,Q,L> sub); void clearAssignments(QueueConsumer sub); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java index 251a1f55ed..369f42b183 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java @@ -24,46 +24,46 @@ import org.apache.qpid.server.message.ServerMessage; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -public class SimpleQueueEntryImpl extends QueueEntryImpl +public abstract class OrderedQueueEntry<E extends OrderedQueueEntry<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends OrderedQueueEntryList<E,Q,L>> extends QueueEntryImpl<E,Q,L> { - static final AtomicReferenceFieldUpdater<SimpleQueueEntryImpl, SimpleQueueEntryImpl> + static final AtomicReferenceFieldUpdater<OrderedQueueEntry, OrderedQueueEntry> _nextUpdater = AtomicReferenceFieldUpdater.newUpdater - (SimpleQueueEntryImpl.class, SimpleQueueEntryImpl.class, "_next"); + (OrderedQueueEntry.class, OrderedQueueEntry.class, "_next"); - private volatile SimpleQueueEntryImpl _next; + private volatile E _next; - public SimpleQueueEntryImpl(SimpleQueueEntryList queueEntryList) + public OrderedQueueEntry(L queueEntryList) { super(queueEntryList); } - public SimpleQueueEntryImpl(SimpleQueueEntryList queueEntryList, ServerMessage message, final long entryId) + public OrderedQueueEntry(L queueEntryList, ServerMessage message, final long entryId) { super(queueEntryList, message, entryId); } - public SimpleQueueEntryImpl(SimpleQueueEntryList queueEntryList, ServerMessage message) + public OrderedQueueEntry(L queueEntryList, ServerMessage message) { super(queueEntryList, message); } - public SimpleQueueEntryImpl getNextNode() + public E getNextNode() { return _next; } - public SimpleQueueEntryImpl getNextValidEntry() + public E getNextValidEntry() { - SimpleQueueEntryImpl next = getNextNode(); + E next = getNextNode(); while(next != null && next.isDeleted()) { - final SimpleQueueEntryImpl newNext = next.getNextNode(); + final E newNext = next.getNextNode(); if(newNext != null) { - SimpleQueueEntryList._nextUpdater.compareAndSet(this,next, newNext); + OrderedQueueEntryList._nextUpdater.compareAndSet(this,next, newNext); next = getNextNode(); } else diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java new file mode 100644 index 0000000000..f2491bdb0c --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java @@ -0,0 +1,198 @@ +/* +* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +* +*/ +package org.apache.qpid.server.queue; + +import org.apache.qpid.server.message.ServerMessage; + +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; + +public abstract class OrderedQueueEntryList<E extends OrderedQueueEntry<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends OrderedQueueEntryList<E,Q,L>> implements SimpleQueueEntryList<E,Q,L> +{ + + private final E _head; + + private volatile E _tail; + + static final AtomicReferenceFieldUpdater<OrderedQueueEntryList, OrderedQueueEntry> + _tailUpdater = + AtomicReferenceFieldUpdater.newUpdater + (OrderedQueueEntryList.class, OrderedQueueEntry.class, "_tail"); + + + private final Q _queue; + + static final AtomicReferenceFieldUpdater<OrderedQueueEntry, OrderedQueueEntry> + _nextUpdater = OrderedQueueEntry._nextUpdater; + + private AtomicLong _scavenges = new AtomicLong(0L); + private final long _scavengeCount = Integer.getInteger("qpid.queue.scavenge_count", 50); + private final AtomicReference<E> _unscavengedHWM = new AtomicReference<E>(); + + + public OrderedQueueEntryList(Q queue, HeadCreator<E,Q,L> headCreator) + { + _queue = queue; + _head = headCreator.createHead((L)this); + _tail = _head; + } + + void scavenge() + { + E hwm = _unscavengedHWM.getAndSet(null); + E next = _head.getNextValidEntry(); + + if(hwm != null) + { + while (next != null && hwm.compareTo(next)>0) + { + next = next.getNextValidEntry(); + } + } + } + + + public Q getQueue() + { + return _queue; + } + + + public E add(ServerMessage message) + { + E node = createQueueEntry(message); + for (;;) + { + OrderedQueueEntry tail = _tail; + OrderedQueueEntry next = tail.getNextNode(); + if (tail == _tail) + { + if (next == null) + { + node.setEntryId(tail.getEntryId()+1); + if (_nextUpdater.compareAndSet(tail, null, node)) + { + _tailUpdater.compareAndSet(this, tail, node); + + return node; + } + } + else + { + _tailUpdater.compareAndSet(this,tail, next); + } + } + } + } + + abstract protected E createQueueEntry(ServerMessage<?> message); + + public E next(E node) + { + return node.getNextValidEntry(); + } + + public static interface HeadCreator<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> + { + E createHead(L list); + } + + public static class QueueEntryIteratorImpl<E extends OrderedQueueEntry<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends OrderedQueueEntryList<E,Q,L>> implements QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> + { + private E _lastNode; + + QueueEntryIteratorImpl(E startNode) + { + _lastNode = startNode; + } + + public boolean atTail() + { + return _lastNode.getNextValidEntry() == null; + } + + public E getNode() + { + return _lastNode; + } + + public boolean advance() + { + E nextValidNode = _lastNode.getNextValidEntry(); + + if(nextValidNode != null) + { + _lastNode = nextValidNode; + } + + return nextValidNode != null; + } + } + + public QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> iterator() + { + return new QueueEntryIteratorImpl<E,Q,L>(_head); + } + + + public E getHead() + { + return _head; + } + + public void entryDeleted(E queueEntry) + { + E next = _head.getNextNode(); + E newNext = _head.getNextValidEntry(); + + // the head of the queue has not been deleted, hence the deletion must have been mid queue. + if (next == newNext) + { + E unscavengedHWM = _unscavengedHWM.get(); + while(unscavengedHWM == null || unscavengedHWM.compareTo(queueEntry)<0) + { + _unscavengedHWM.compareAndSet(unscavengedHWM, queueEntry); + unscavengedHWM = _unscavengedHWM.get(); + } + if (_scavenges.incrementAndGet() > _scavengeCount) + { + _scavenges.set(0L); + scavenge(); + } + } + else + { + E unscavengedHWM = _unscavengedHWM.get(); + if(unscavengedHWM != null && (next == null || unscavengedHWM.compareTo(next) < 0)) + { + _unscavengedHWM.compareAndSet(unscavengedHWM, null); + } + } + } + + public int getPriorities() + { + return 0; + } + + +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java index 6918ae683c..7cf245c8f8 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/OutOfOrderQueue.java @@ -25,30 +25,30 @@ import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Map; import java.util.UUID; -public abstract class OutOfOrderQueue extends SimpleAMQQueue +public abstract class OutOfOrderQueue<E extends QueueEntryImpl<E,Q,L>, Q extends OutOfOrderQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> extends SimpleAMQQueue<E,Q,L> { protected OutOfOrderQueue(UUID id, String name, boolean durable, String owner, boolean autoDelete, boolean exclusive, - VirtualHost virtualHost, QueueEntryListFactory entryListFactory, Map<String, Object> arguments) + VirtualHost virtualHost, QueueEntryListFactory<E,Q,L> entryListFactory, Map<String, Object> arguments) { super(id, name, durable, owner, autoDelete, exclusive, virtualHost, entryListFactory, arguments); } @Override - protected void checkConsumersNotAheadOfDelivery(final QueueEntry entry) + protected void checkConsumersNotAheadOfDelivery(final E entry) { // check that all consumers are not in advance of the entry - QueueConsumerList.ConsumerNodeIterator subIter = getConsumerList().iterator(); + QueueConsumerList.ConsumerNodeIterator<E,Q,L> subIter = getConsumerList().iterator(); while(subIter.advance() && !entry.isAcquired()) { - final QueueConsumer consumer = subIter.getNode().getConsumer(); + final QueueConsumer<?,E,Q,L> consumer = subIter.getNode().getConsumer(); if(!consumer.isClosed()) { - QueueContext context = consumer.getQueueContext(); + QueueContext<E,Q,L> context = consumer.getQueueContext(); if(context != null) { - QueueEntry released = context.getReleasedEntry(); + E released = context.getReleasedEntry(); while(!entry.isAcquired() && (released == null || released.compareTo(entry) > 0)) { if(QueueContext._releasedUpdater.compareAndSet(context,released,entry)) diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueue.java index 46c2a635b7..4440d045d1 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueue.java @@ -25,22 +25,22 @@ import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Map; import java.util.UUID; -public class AMQPriorityQueue extends OutOfOrderQueue +public class PriorityQueue extends OutOfOrderQueue<PriorityQueueList.PriorityQueueEntry, PriorityQueue, PriorityQueueList> { - protected AMQPriorityQueue(UUID id, - final String name, - final boolean durable, - final String owner, - final boolean autoDelete, - boolean exclusive, - final VirtualHost virtualHost, - Map<String, Object> arguments, int priorities) + protected PriorityQueue(UUID id, + final String name, + final boolean durable, + final String owner, + final boolean autoDelete, + boolean exclusive, + final VirtualHost virtualHost, + Map<String, Object> arguments, int priorities) { super(id, name, durable, owner, autoDelete, exclusive, virtualHost, new PriorityQueueList.Factory(priorities), arguments); } public int getPriorities() { - return ((PriorityQueueList) getEntries()).getPriorities(); + return getEntries().getPriorities(); } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java index 05d84327d4..e877983643 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java @@ -22,132 +22,162 @@ package org.apache.qpid.server.queue; import org.apache.qpid.server.message.ServerMessage; -public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl> +abstract public class PriorityQueueList extends OrderedQueueEntryList<PriorityQueueList.PriorityQueueEntry, PriorityQueue, PriorityQueueList> { - private final AMQQueue<QueueConsumer> _queue; - private final PriorityQueueEntrySubList[] _priorityLists; - private final int _priorities; - private final int _priorityOffset; - public PriorityQueueList(AMQQueue queue, int priorities) - { - _queue = queue; - _priorityLists = new PriorityQueueEntrySubList[priorities]; - _priorities = priorities; - _priorityOffset = 5-((priorities + 1)/2); - for(int i = 0; i < priorities; i++) - { - _priorityLists[i] = new PriorityQueueEntrySubList(queue, i); - } - } - public int getPriorities() + public PriorityQueueList(final PriorityQueue queue, + final HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList> headCreator) { - return _priorities; + super(queue, headCreator); } - public AMQQueue<QueueConsumer> getQueue() + static class PriorityQueueMasterList extends PriorityQueueList { - return _queue; - } + private static final HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList> DUMMY_HEAD_CREATOR = + new HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList>() + { + @Override + public PriorityQueueEntry createHead(final PriorityQueueList list) + { + return null; + } + }; + private final PriorityQueue _queue; + private final PriorityQueueEntrySubList[] _priorityLists; + private final int _priorities; + private final int _priorityOffset; - public SimpleQueueEntryImpl add(ServerMessage message) - { - int index = message.getMessageHeader().getPriority() - _priorityOffset; - if(index >= _priorities) + public PriorityQueueMasterList(PriorityQueue queue, int priorities) { - index = _priorities-1; + super(queue, DUMMY_HEAD_CREATOR); + _queue = queue; + _priorityLists = new PriorityQueueEntrySubList[priorities]; + _priorities = priorities; + _priorityOffset = 5-((priorities + 1)/2); + for(int i = 0; i < priorities; i++) + { + _priorityLists[i] = new PriorityQueueEntrySubList(queue, i); + } } - else if(index < 0) + + public int getPriorities() { - index = 0; + return _priorities; } - return _priorityLists[index].add(message); - - } - - public SimpleQueueEntryImpl next(SimpleQueueEntryImpl node) - { - SimpleQueueEntryImpl next = node.getNextValidEntry(); - if(next == null) + public PriorityQueue getQueue() { - final QueueEntryList<?> nodeEntryList = node.getQueueEntryList(); - int index; - for(index = _priorityLists.length-1; _priorityLists[index] != nodeEntryList; index--) {}; + return _queue; + } - while(next == null && index != 0) + public PriorityQueueEntry add(ServerMessage message) + { + int index = message.getMessageHeader().getPriority() - _priorityOffset; + if(index >= _priorities) + { + index = _priorities-1; + } + else if(index < 0) { - index--; - next = _priorityLists[index].getHead().getNextValidEntry(); + index = 0; } + return _priorityLists[index].add(message); } - return next; - } - private final class PriorityQueueEntryListIterator implements QueueEntryIterator<SimpleQueueEntryImpl> - { - private final SimpleQueueEntryList.QueueEntryIteratorImpl[] _iterators = new SimpleQueueEntryList.QueueEntryIteratorImpl[ _priorityLists.length ]; - private SimpleQueueEntryImpl _lastNode; + @Override + protected PriorityQueueEntry createQueueEntry(final ServerMessage<?> message) + { + throw new UnsupportedOperationException(); + } - PriorityQueueEntryListIterator() + public PriorityQueueEntry next(PriorityQueueEntry node) { - for(int i = 0; i < _priorityLists.length; i++) + PriorityQueueEntry next = node.getNextValidEntry(); + + if(next == null) { - _iterators[i] = _priorityLists[i].iterator(); + final PriorityQueueList nodeEntryList = node.getQueueEntryList(); + int index; + for(index = _priorityLists.length-1; _priorityLists[index] != nodeEntryList; index--) + { + // do nothing loop is just to find the index + } + + while(next == null && index != 0) + { + index--; + next = _priorityLists[index].getHead().getNextValidEntry(); + } + } - _lastNode = _iterators[_iterators.length - 1].getNode(); + return next; } - - public boolean atTail() + private final class PriorityQueueEntryListIterator implements QueueEntryIterator<PriorityQueueEntry, PriorityQueue, PriorityQueueList, QueueConsumer<?,PriorityQueueEntry, PriorityQueue, PriorityQueueList>> { - for(int i = 0; i < _iterators.length; i++) + private final QueueEntryIterator<PriorityQueueEntry, PriorityQueue, PriorityQueueList,QueueConsumer<?,PriorityQueueEntry, PriorityQueue, PriorityQueueList>>[] _iterators = new QueueEntryIterator[ _priorityLists.length ]; + private PriorityQueueEntry _lastNode; + + PriorityQueueEntryListIterator() { - if(!_iterators[i].atTail()) + for(int i = 0; i < _priorityLists.length; i++) { - return false; + _iterators[i] = _priorityLists[i].iterator(); } + _lastNode = _iterators[_iterators.length - 1].getNode(); } - return true; - } - public SimpleQueueEntryImpl getNode() - { - return _lastNode; - } - public boolean advance() - { - for(int i = _iterators.length-1; i >= 0; i--) + public boolean atTail() { - if(_iterators[i].advance()) + for(int i = 0; i < _iterators.length; i++) { - _lastNode = _iterators[i].getNode(); - return true; + if(!_iterators[i].atTail()) + { + return false; + } } + return true; + } + + public PriorityQueueEntry getNode() + { + return _lastNode; + } + + public boolean advance() + { + for(int i = _iterators.length-1; i >= 0; i--) + { + if(_iterators[i].advance()) + { + _lastNode = _iterators[i].getNode(); + return true; + } + } + return false; } - return false; } - } - public PriorityQueueEntryListIterator iterator() - { - return new PriorityQueueEntryListIterator(); - } + public PriorityQueueEntryListIterator iterator() + { - public SimpleQueueEntryImpl getHead() - { - return _priorityLists[_priorities-1].getHead(); - } + return new PriorityQueueEntryListIterator(); + } - public void entryDeleted(final SimpleQueueEntryImpl queueEntry) - { + public PriorityQueueEntry getHead() + { + return _priorityLists[_priorities-1].getHead(); + } - } + public void entryDeleted(final PriorityQueueEntry queueEntry) + { - static class Factory implements QueueEntryListFactory + } + } + static class Factory implements QueueEntryListFactory<PriorityQueueEntry, PriorityQueue, PriorityQueueList> { private final int _priorities; @@ -156,26 +186,34 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl> _priorities = priorities; } - public PriorityQueueList createQueueEntryList(AMQQueue queue) + public PriorityQueueList createQueueEntryList(PriorityQueue queue) { - return new PriorityQueueList(queue, _priorities); + return new PriorityQueueMasterList(queue, _priorities); } } - private static class PriorityQueueEntrySubList extends SimpleQueueEntryList + static class PriorityQueueEntrySubList extends PriorityQueueList { + private static final HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList> HEAD_CREATOR = new HeadCreator<PriorityQueueEntry, PriorityQueue, PriorityQueueList>() + { + @Override + public PriorityQueueEntry createHead(final PriorityQueueList list) + { + return new PriorityQueueEntry(list); + } + }; private int _listPriority; - public PriorityQueueEntrySubList(AMQQueue<QueueConsumer> queue, int listPriority) + public PriorityQueueEntrySubList(PriorityQueue queue, int listPriority) { - super(queue); + super(queue, HEAD_CREATOR); _listPriority = listPriority; } @Override - protected PriorityQueueEntryImpl createQueueEntry(ServerMessage<?> message) + protected PriorityQueueEntry createQueueEntry(ServerMessage<?> message) { - return new PriorityQueueEntryImpl(this, message); + return new PriorityQueueEntry(this, message); } public int getListPriority() @@ -184,17 +222,22 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl> } } - private static class PriorityQueueEntryImpl extends SimpleQueueEntryImpl + static class PriorityQueueEntry extends OrderedQueueEntry<PriorityQueueEntry, PriorityQueue, PriorityQueueList> { - public PriorityQueueEntryImpl(PriorityQueueEntrySubList queueEntryList, ServerMessage<?> message) + private PriorityQueueEntry(final PriorityQueueList queueEntryList) + { + super(queueEntryList); + } + + public PriorityQueueEntry(PriorityQueueEntrySubList queueEntryList, ServerMessage<?> message) { super(queueEntryList, message); } @Override - public int compareTo(final QueueEntry o) + public int compareTo(final PriorityQueueEntry o) { - PriorityQueueEntrySubList pqel = (PriorityQueueEntrySubList)((PriorityQueueEntryImpl)o).getQueueEntryList(); + PriorityQueueEntrySubList pqel = (PriorityQueueEntrySubList)o.getQueueEntryList(); int otherPriority = pqel.getListPriority(); int thisPriority = ((PriorityQueueEntrySubList) getQueueEntryList()).getListPriority(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java index ff7840255a..5c891797f5 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java @@ -47,7 +47,7 @@ import java.util.concurrent.locks.ReentrantLock; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SUBSCRIPTION_FORMAT; -class QueueConsumer<T extends ConsumerTarget> implements Consumer +class QueueConsumer<T extends ConsumerTarget, E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements Consumer { public static enum State @@ -61,10 +61,9 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer private final AtomicBoolean _targetClosed = new AtomicBoolean(false); private final AtomicBoolean _closed = new AtomicBoolean(false); private final long _id; - private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE); private final Lock _stateChangeLock = new ReentrantLock(); private final long _createTime = System.currentTimeMillis(); - private final MessageInstance.ConsumerAcquiredState _owningState = new MessageInstance.ConsumerAcquiredState(this); + private final MessageInstance.ConsumerAcquiredState<QueueConsumer<T,E,Q,L>> _owningState = new MessageInstance.ConsumerAcquiredState<QueueConsumer<T,E,Q,L>>(this); private final boolean _acquires; private final boolean _seesRequeues; private final String _consumerName; @@ -74,8 +73,10 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer private final FilterManager _filters; private final Class<? extends ServerMessage> _messageClass; private final Object _sessionReference; - private SimpleAMQQueue _queue; - private GenericActor _logActor; + private Q _queue; + private GenericActor _logActor = new GenericActor("[" + MessageFormat.format(SUBSCRIPTION_FORMAT, getId()) + + "(UNKNOWN)" + + "] "); static final EnumMap<ConsumerTarget.State, State> STATE_MAP = new EnumMap<ConsumerTarget.State, State>(ConsumerTarget.State.class); @@ -89,10 +90,10 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer private final T _target; private final SubFlushRunner _runner = new SubFlushRunner(this); - private volatile QueueContext _queueContext; - private StateChangeListener<? extends Consumer, State> _stateListener = new StateChangeListener<Consumer, State>() + private volatile QueueContext<E,Q,L> _queueContext; + private StateChangeListener<? super QueueConsumer<T,E,Q,L>, State> _stateListener = new StateChangeListener<QueueConsumer<T,E,Q,L>, State>() { - public void stateChanged(Consumer sub, State oldState, State newState) + public void stateChanged(QueueConsumer sub, State oldState, State newState) { CurrentActor.get().message(SubscriptionMessages.STATE(newState.toString())); } @@ -158,8 +159,7 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer throw new RuntimeException(e); } } - final StateChangeListener<Consumer, State> stateListener = - (StateChangeListener<Consumer, State>) getStateListener(); + final StateChangeListener<? super QueueConsumer<T,E,Q,L>, State> stateListener = getStateListener(); if(stateListener != null) { stateListener.stateChanged(this, STATE_MAP.get(oldState), STATE_MAP.get(newState)); @@ -251,12 +251,12 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer return STATE_MAP.get(_target.getState()); } - public final SimpleAMQQueue getQueue() + public final Q getQueue() { return _queue; } - final void setQueue(SimpleAMQQueue queue, boolean exclusive) + final void setQueue(Q queue, boolean exclusive) { if(getQueue() != null) { @@ -300,9 +300,9 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer getQueue().flushConsumer(this); } - boolean resend(final MessageInstance entry) throws AMQException + boolean resend(final E entry) throws AMQException { - return getQueue().resend((QueueEntry)entry, this); + return getQueue().resend(entry, this); } final SubFlushRunner getRunner() @@ -315,31 +315,26 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer return _id; } - public final StateChangeListener<? extends Consumer, State> getStateListener() + public final StateChangeListener<? super QueueConsumer<T,E,Q,L>, State> getStateListener() { return _stateListener; } - public final void setStateListener(StateChangeListener<? extends Consumer, State> listener) + public final void setStateListener(StateChangeListener<? super QueueConsumer<T,E,Q,L>, State> listener) { _stateListener = listener; } - final QueueContext getQueueContext() + final QueueContext<E,Q,L> getQueueContext() { return _queueContext; } - final void setQueueContext(QueueContext queueContext) + final void setQueueContext(QueueContext<E,Q,L> queueContext) { _queueContext = queueContext; } - protected boolean updateState(State from, State to) - { - return _state.compareAndSet(from, to); - } - public final boolean isActive() { return getState() == State.ACTIVE; @@ -355,7 +350,7 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer _noLocal = noLocal; } - public final boolean hasInterest(MessageInstance entry) + public final boolean hasInterest(E entry) { //check that the message hasn't been rejected if (entry.isRejectedBy(this)) @@ -405,7 +400,6 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer filterLogString.append(delimiter); } filterLogString.append("Browser"); - hasEntries = true; } return filterLogString.toString(); @@ -431,7 +425,7 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer return _createTime; } - final MessageInstance.ConsumerAcquiredState getOwningState() + final MessageInstance.ConsumerAcquiredState<QueueConsumer<T,E,Q,L>> getOwningState() { return _owningState; } @@ -466,7 +460,7 @@ class QueueConsumer<T extends ConsumerTarget> implements Consumer return _deliveredCount.longValue(); } - final void send(final QueueEntry entry, final boolean batch) throws AMQException + final void send(final E entry, final boolean batch) throws AMQException { _deliveredCount.incrementAndGet(); ServerMessage message = entry.getMessage(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerList.java index 82e9d58cf3..2cf0e93e9c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerList.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerList.java @@ -24,19 +24,19 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -class QueueConsumerList +class QueueConsumerList<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E, Q,L>, L extends SimpleQueueEntryList<E,Q,L>> { - private final ConsumerNode _head = new ConsumerNode(); + private final ConsumerNode<E,Q,L> _head = new ConsumerNode<E,Q,L>(); - private final AtomicReference<ConsumerNode> _tail = new AtomicReference<ConsumerNode>(_head); - private final AtomicReference<ConsumerNode> _subNodeMarker = new AtomicReference<ConsumerNode>(_head); + private final AtomicReference<ConsumerNode<E,Q,L>> _tail = new AtomicReference<ConsumerNode<E,Q,L>>(_head); + private final AtomicReference<ConsumerNode<E,Q,L>> _subNodeMarker = new AtomicReference<ConsumerNode<E,Q,L>>(_head); private final AtomicInteger _size = new AtomicInteger(); - public static final class ConsumerNode + public static final class ConsumerNode<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E, Q,L>, L extends SimpleQueueEntryList<E,Q,L>> { private final AtomicBoolean _deleted = new AtomicBoolean(); - private final AtomicReference<ConsumerNode> _next = new AtomicReference<ConsumerNode>(); - private final QueueConsumer _sub; + private final AtomicReference<ConsumerNode<E,Q,L>> _next = new AtomicReference<ConsumerNode<E,Q,L>>(); + private final QueueConsumer<?,E,Q,L> _sub; public ConsumerNode() { @@ -45,7 +45,7 @@ class QueueConsumerList _deleted.set(true); } - public ConsumerNode(final QueueConsumer sub) + public ConsumerNode(final QueueConsumer<?,E,Q,L> sub) { //used for regular node construction _sub = sub; @@ -57,12 +57,12 @@ class QueueConsumerList * * @return the next non-deleted node, or null if none was found. */ - public ConsumerNode findNext() + public ConsumerNode<E,Q,L> findNext() { - ConsumerNode next = nextNode(); + ConsumerNode<E,Q,L> next = nextNode(); while(next != null && next.isDeleted()) { - final ConsumerNode newNext = next.nextNode(); + final ConsumerNode<E,Q,L> newNext = next.nextNode(); if(newNext != null) { //try to move our _next reference forward to the 'newNext' @@ -86,7 +86,7 @@ class QueueConsumerList * * @return the immediately next node in the structure, or null if at the tail. */ - protected ConsumerNode nextNode() + protected ConsumerNode<E,Q,L> nextNode() { return _next.get(); } @@ -97,7 +97,7 @@ class QueueConsumerList * @param node the ConsumerNode to set as 'next' * @return whether the operation succeeded */ - private boolean setNext(final ConsumerNode node) + private boolean setNext(final ConsumerNode<E,Q,L> node) { return _next.compareAndSet(null, node); } @@ -112,18 +112,18 @@ class QueueConsumerList return _deleted.compareAndSet(false,true); } - public QueueConsumer getConsumer() + public QueueConsumer<?,E,Q,L> getConsumer() { return _sub; } } - private void insert(final ConsumerNode node, final boolean count) + private void insert(final ConsumerNode<E,Q,L> node, final boolean count) { for (;;) { - ConsumerNode tail = _tail.get(); - ConsumerNode next = tail.nextNode(); + ConsumerNode<E,Q,L> tail = _tail.get(); + ConsumerNode<E,Q,L> next = tail.nextNode(); if (tail == _tail.get()) { if (next == null) @@ -146,16 +146,16 @@ class QueueConsumerList } } - public void add(final QueueConsumer sub) + public void add(final QueueConsumer<?,E,Q,L> sub) { - ConsumerNode node = new ConsumerNode(sub); + ConsumerNode<E,Q,L> node = new ConsumerNode<E,Q,L>(sub); insert(node, true); } - public boolean remove(final QueueConsumer sub) + public boolean remove(final QueueConsumer<?, E,Q,L> sub) { - ConsumerNode prevNode = _head; - ConsumerNode node = _head.nextNode(); + ConsumerNode<E,Q,L> prevNode = _head; + ConsumerNode<E,Q,L> node = _head.nextNode(); while(node != null) { @@ -170,7 +170,7 @@ class QueueConsumerList //correctness reasons, however we have just 'deleted' //the tail. Inserting an empty dummy node after it will //let us scavenge the node containing the Consumer. - insert(new ConsumerNode(), false); + insert(new ConsumerNode<E,Q,L>(), false); } //advance the next node reference in the 'prevNode' to scavenge @@ -189,9 +189,9 @@ class QueueConsumerList return false; } - private void nodeMarkerCleanup(final ConsumerNode node) + private void nodeMarkerCleanup(final ConsumerNode<E,Q,L> node) { - ConsumerNode markedNode = _subNodeMarker.get(); + ConsumerNode<E,Q,L> markedNode = _subNodeMarker.get(); if(node == markedNode) { //if the marked node is the one we are removing, then @@ -200,7 +200,7 @@ class QueueConsumerList //into the list and find the next node to use. //Because we inserted a dummy if node was the //tail, markedNode.nextNode() can never be null. - ConsumerNode dummy = new ConsumerNode(); + ConsumerNode<E,Q,L> dummy = new ConsumerNode<E,Q,L>(); dummy.setNext(markedNode.nextNode()); //if the CAS fails the marked node has changed, thus @@ -219,7 +219,7 @@ class QueueConsumerList } } - public boolean updateMarkedNode(final ConsumerNode expected, final ConsumerNode nextNode) + public boolean updateMarkedNode(final ConsumerNode<E,Q,L> expected, final ConsumerNode<E,Q,L> nextNode) { return _subNodeMarker.compareAndSet(expected, nextNode); } @@ -231,41 +231,41 @@ class QueueConsumerList * * @return the previously marked node (or a dummy if it was subsequently deleted) */ - public ConsumerNode getMarkedNode() + public ConsumerNode<E,Q,L> getMarkedNode() { return _subNodeMarker.get(); } - public static class ConsumerNodeIterator + public static class ConsumerNodeIterator<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E, Q,L>, L extends SimpleQueueEntryList<E,Q,L>> { - private ConsumerNode _lastNode; + private ConsumerNode<E,Q,L> _lastNode; - ConsumerNodeIterator(ConsumerNode startNode) + ConsumerNodeIterator(ConsumerNode<E,Q,L> startNode) { _lastNode = startNode; } - public ConsumerNode getNode() + public ConsumerNode<E,Q,L> getNode() { return _lastNode; } public boolean advance() { - ConsumerNode nextNode = _lastNode.findNext(); + ConsumerNode<E,Q,L> nextNode = _lastNode.findNext(); _lastNode = nextNode; return _lastNode != null; } } - public ConsumerNodeIterator iterator() + public ConsumerNodeIterator<E,Q,L> iterator() { - return new ConsumerNodeIterator(_head); + return new ConsumerNodeIterator<E,Q,L>(_head); } - public ConsumerNode getHead() + public ConsumerNode<E,Q,L> getHead() { return _head; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java index 861bd3dea1..7a59c154b6 100755 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueContext.java @@ -23,32 +23,32 @@ package org.apache.qpid.server.queue; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -final class QueueContext +final class QueueContext<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> { - private volatile QueueEntry _lastSeenEntry; - private volatile QueueEntry _releasedEntry; + private volatile E _lastSeenEntry; + private volatile E _releasedEntry; - static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry> + static final AtomicReferenceFieldUpdater<QueueContext, QueueEntryImpl> _lastSeenUpdater = AtomicReferenceFieldUpdater.newUpdater - (QueueContext.class, QueueEntry.class, "_lastSeenEntry"); - static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry> + (QueueContext.class, QueueEntryImpl.class, "_lastSeenEntry"); + static final AtomicReferenceFieldUpdater<QueueContext, QueueEntryImpl> _releasedUpdater = AtomicReferenceFieldUpdater.newUpdater - (QueueContext.class, QueueEntry.class, "_releasedEntry"); + (QueueContext.class, QueueEntryImpl.class, "_releasedEntry"); - public QueueContext(QueueEntry head) + public QueueContext(E head) { _lastSeenEntry = head; } - public QueueEntry getLastSeenEntry() + public E getLastSeenEntry() { return _lastSeenEntry; } - QueueEntry getReleasedEntry() + E getReleasedEntry() { return _releasedEntry; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java index 6a42088c47..9a49cd6088 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java @@ -20,20 +20,21 @@ */ package org.apache.qpid.server.queue; +import org.apache.qpid.server.consumer.Consumer; import org.apache.qpid.server.message.MessageInstance; -public interface QueueEntry extends MessageInstance<QueueConsumer>, Comparable<QueueEntry> +public interface QueueEntry<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, C extends Consumer> extends MessageInstance<E,C>, Comparable<E> { - AMQQueue<QueueConsumer> getQueue(); + Q getQueue(); long getSize(); boolean isQueueDeleted(); - QueueEntry getNextNode(); + E getNextNode(); - QueueEntry getNextValidEntry(); + E getNextValidEntry(); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index 4ee9df5e5d..173705c0f7 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java @@ -44,11 +44,11 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import java.util.concurrent.atomic.AtomicLongFieldUpdater; import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; -public abstract class QueueEntryImpl implements QueueEntry +public abstract class QueueEntryImpl<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements QueueEntry<E,Q,QueueConsumer<?,E,Q,L>> { private static final Logger _log = Logger.getLogger(QueueEntryImpl.class); - private final QueueEntryList _queueEntryList; + private final L _queueEntryList; private final MessageReference _message; @@ -63,7 +63,7 @@ public abstract class QueueEntryImpl implements QueueEntry (QueueEntryImpl.class, EntryState.class, "_state"); - private volatile Set<StateChangeListener<MessageInstance<QueueConsumer>, State>> _stateChangeListeners; + private volatile Set<StateChangeListener<? super E, State>> _stateChangeListeners; private static final AtomicReferenceFieldUpdater<QueueEntryImpl, Set> @@ -90,14 +90,14 @@ public abstract class QueueEntryImpl implements QueueEntry private boolean _deliveredToConsumer; - public QueueEntryImpl(QueueEntryList<?> queueEntryList) + public QueueEntryImpl(L queueEntryList) { this(queueEntryList,null,Long.MIN_VALUE); _state = DELETED_STATE; } - public QueueEntryImpl(QueueEntryList<?> queueEntryList, ServerMessage message, final long entryId) + public QueueEntryImpl(L queueEntryList, ServerMessage message, final long entryId) { _queueEntryList = queueEntryList; @@ -107,7 +107,7 @@ public abstract class QueueEntryImpl implements QueueEntry populateInstanceProperties(); } - public QueueEntryImpl(QueueEntryList<?> queueEntryList, ServerMessage message) + public QueueEntryImpl(L queueEntryList, ServerMessage message) { _queueEntryList = queueEntryList; _message = message == null ? null : message.newReference(); @@ -138,7 +138,7 @@ public abstract class QueueEntryImpl implements QueueEntry return _entryId; } - public AMQQueue<QueueConsumer> getQueue() + public Q getQueue() { return _queueEntryList.getQueue(); } @@ -234,12 +234,12 @@ public abstract class QueueEntryImpl implements QueueEntry if(state instanceof ConsumerAcquiredState) { - getQueue().decrementUnackedMsgCount(this); + getQueue().decrementUnackedMsgCount((E) this); } if(!getQueue().isDeleted()) { - getQueue().requeue(this); + getQueue().requeue((E)this); if(_stateChangeListeners != null) { notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE); @@ -315,13 +315,12 @@ public abstract class QueueEntryImpl implements QueueEntry if((state.getState() == State.ACQUIRED) &&_stateUpdater.compareAndSet(this, state, DEQUEUED_STATE)) { - Consumer s = null; if (state instanceof ConsumerAcquiredState) { - getQueue().decrementUnackedMsgCount(this); + getQueue().decrementUnackedMsgCount((E) this); } - getQueue().dequeue(this,s); + getQueue().dequeue((E)this); if(_stateChangeListeners != null) { notifyStateChange(state.getState() , QueueEntry.State.DEQUEUED); @@ -333,9 +332,9 @@ public abstract class QueueEntryImpl implements QueueEntry private void notifyStateChange(final State oldState, final State newState) { - for(StateChangeListener<MessageInstance<QueueConsumer>, State> l : _stateChangeListeners) + for(StateChangeListener<? super E, State> l : _stateChangeListeners) { - l.stateChanged(this, oldState, newState); + l.stateChanged((E)this, oldState, newState); } } @@ -345,7 +344,7 @@ public abstract class QueueEntryImpl implements QueueEntry if(state != DELETED_STATE && _stateUpdater.compareAndSet(this,state,DELETED_STATE)) { - _queueEntryList.entryDeleted(this); + _queueEntryList.entryDeleted((E)this); onDelete(); _message.release(); @@ -364,7 +363,7 @@ public abstract class QueueEntryImpl implements QueueEntry dispose(); } - public int routeToAlternate(final Action<MessageInstance<? extends Consumer>> action, ServerTransaction txn) + public int routeToAlternate(final Action<? super MessageInstance<?, ? extends Consumer>> action, ServerTransaction txn) { final AMQQueue currentQueue = getQueue(); Exchange alternateExchange = currentQueue.getAlternateExchange(); @@ -378,11 +377,10 @@ public abstract class QueueEntryImpl implements QueueEntry if (alternateExchange != null) { - enqueues = alternateExchange.send(getMessage(), - getInstanceProperties(), - txn, - action); + getInstanceProperties(), + txn, + action); } else { @@ -406,8 +404,8 @@ public abstract class QueueEntryImpl implements QueueEntry { txn.commit(); } - return enqueues; + return enqueues; } public boolean isQueueDeleted() @@ -415,21 +413,21 @@ public abstract class QueueEntryImpl implements QueueEntry return getQueue().isDeleted(); } - public void addStateChangeListener(StateChangeListener<MessageInstance<QueueConsumer>, State> listener) + public void addStateChangeListener(StateChangeListener<? super E,State> listener) { - Set<StateChangeListener<MessageInstance<QueueConsumer>, State>> listeners = _stateChangeListeners; + Set<StateChangeListener<? super E, State>> listeners = _stateChangeListeners; if(listeners == null) { - _listenersUpdater.compareAndSet(this, null, new CopyOnWriteArraySet<StateChangeListener<MessageInstance<QueueConsumer>, State>>()); + _listenersUpdater.compareAndSet(this, null, new CopyOnWriteArraySet<StateChangeListener<? super E, State>>()); listeners = _stateChangeListeners; } listeners.add(listener); } - public boolean removeStateChangeListener(StateChangeListener<MessageInstance<QueueConsumer>, State> listener) + public boolean removeStateChangeListener(StateChangeListener<? super E, State> listener) { - Set<StateChangeListener<MessageInstance<QueueConsumer>, State>> listeners = _stateChangeListeners; + Set<StateChangeListener<? super E, State>> listeners = _stateChangeListeners; if(listeners != null) { return listeners.remove(listener); @@ -439,9 +437,9 @@ public abstract class QueueEntryImpl implements QueueEntry } - public int compareTo(final QueueEntry o) + public int compareTo(final E o) { - QueueEntryImpl other = (QueueEntryImpl)o; + E other = o; return getEntryId() > other.getEntryId() ? 1 : getEntryId() < other.getEntryId() ? -1 : 0; } @@ -449,7 +447,7 @@ public abstract class QueueEntryImpl implements QueueEntry { } - public QueueEntryList getQueueEntryList() + public L getQueueEntryList() { return _queueEntryList; } @@ -497,10 +495,10 @@ public abstract class QueueEntryImpl implements QueueEntry @Override public boolean resend() throws AMQException { - QueueConsumer sub = getDeliveredConsumer(); + QueueConsumer<?,E,Q,L> sub = getDeliveredConsumer(); if(sub != null) { - return sub.resend(this); + return sub.resend((E)this); } return false; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java index 73ebb0f300..72502feb3d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryIterator.java @@ -20,11 +20,13 @@ */ package org.apache.qpid.server.queue; -public interface QueueEntryIterator<QE extends QueueEntry> +import org.apache.qpid.server.consumer.Consumer; + +public interface QueueEntryIterator<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, L extends QueueEntryList<E,Q,L,C>, C extends Consumer> { boolean atTail(); - QE getNode(); + E getNode(); boolean advance(); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java index ad1f703f51..a49320e9d6 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java @@ -20,21 +20,23 @@ */ package org.apache.qpid.server.queue; +import org.apache.qpid.server.consumer.Consumer; import org.apache.qpid.server.message.ServerMessage; -public interface QueueEntryList<Q extends QueueEntry> +public interface QueueEntryList<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, L extends QueueEntryList<E,Q,L,C>, C extends Consumer> { - AMQQueue<QueueConsumer> getQueue(); + Q getQueue(); - Q add(ServerMessage message); + E add(ServerMessage message); - Q next(Q node); + E next(E node); - QueueEntryIterator<Q> iterator(); + QueueEntryIterator<E,Q,L,C> iterator(); - Q getHead(); + E getHead(); - void entryDeleted(Q queueEntry); + void entryDeleted(E queueEntry); int getPriorities(); + } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java index 4dbce45f67..ae8b6560be 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListFactory.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.queue; -interface QueueEntryListFactory +interface QueueEntryListFactory<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> { - public QueueEntryList createQueueEntryList(AMQQueue queue); + public L createQueueEntryList(Q queue); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java index 9ecaf6dafd..e6b5ac5611 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java @@ -16,7 +16,9 @@ */ package org.apache.qpid.server.queue; -public interface QueueEntryVisitor +import org.apache.qpid.server.consumer.Consumer; + +public interface QueueEntryVisitor<E extends QueueEntry> { - boolean visit(QueueEntry entry); + boolean visit(E entry); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index f4a9794fcd..4450a3ed0c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -43,7 +43,6 @@ import org.apache.qpid.server.logging.actors.QueueActor; import org.apache.qpid.server.logging.messages.QueueMessages; import org.apache.qpid.server.logging.subjects.QueueLogSubject; import org.apache.qpid.server.message.InstanceProperties; -import org.apache.qpid.server.message.MessageDestination; import org.apache.qpid.server.message.MessageInstance; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; @@ -52,6 +51,7 @@ import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.security.AuthorizationHolder; import org.apache.qpid.server.consumer.Consumer; import org.apache.qpid.server.consumer.ConsumerTarget; +import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.txn.ServerTransaction; @@ -59,9 +59,9 @@ import org.apache.qpid.server.util.Action; import org.apache.qpid.server.util.StateChangeListener; import org.apache.qpid.server.virtualhost.VirtualHost; -public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, - StateChangeListener<QueueConsumer, QueueConsumer.State>, - MessageGroupManager.ConsumerResetHelper +abstract class SimpleAMQQueue<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E, Q,L>, L extends SimpleQueueEntryList<E,Q,L>> implements AMQQueue<E, Q, QueueConsumer<?,E,Q,L>>, + StateChangeListener<QueueConsumer<?,E,Q,L>, QueueConsumer.State>, + MessageGroupManager.ConsumerResetHelper<E,Q,L> { private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class); @@ -94,11 +94,11 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, private Exchange _alternateExchange; - private final QueueEntryList<QueueEntry> _entries; + private final L _entries; - private final QueueConsumerList _consumerList = new QueueConsumerList(); + private final QueueConsumerList<E,Q,L> _consumerList = new QueueConsumerList<E,Q,L>(); - private volatile QueueConsumer _exclusiveSubscriber; + private volatile QueueConsumer<?,E,Q,L> _exclusiveSubscriber; @@ -163,8 +163,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, private LogSubject _logSubject; private LogActor _logActor; - private static final String SUB_FLUSH_RUNNER = "SUB_FLUSH_RUNNER"; - private boolean _nolocal; + private boolean _noLocal; private final AtomicBoolean _overfull = new AtomicBoolean(false); private boolean _deleteOnNoConsumers; @@ -177,20 +176,15 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, /** the maximum delivery count for each message on this queue or 0 if maximum delivery count is not to be enforced. */ private int _maximumDeliveryCount; - private final MessageGroupManager _messageGroupManager; + private final MessageGroupManager<E,Q,L> _messageGroupManager; - private final Collection<ConsumerRegistrationListener> _consumerListeners = - new ArrayList<ConsumerRegistrationListener>(); + private final Collection<ConsumerRegistrationListener<Q>> _consumerListeners = + new ArrayList<ConsumerRegistrationListener<Q>>(); private AMQQueue.NotificationListener _notificationListener; private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length]; - public SimpleAMQQueue(UUID id, String queueName, boolean durable, String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String, Object> arguments) - { - this(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, new SimpleQueueEntryList.Factory(), arguments); - } - protected SimpleAMQQueue(UUID id, String name, boolean durable, @@ -198,7 +192,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, - QueueEntryListFactory entryListFactory, Map<String,Object> arguments) + QueueEntryListFactory<E,Q,L> entryListFactory, Map<String,Object> arguments) { if (name == null) @@ -217,7 +211,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, _autoDelete = autoDelete; _exclusive = exclusive; _virtualHost = virtualHost; - _entries = entryListFactory.createQueueEntryList(this); + _entries = entryListFactory.createQueueEntryList((Q)this); _arguments = Collections.synchronizedMap(arguments == null ? new LinkedHashMap<String, Object>() : new LinkedHashMap<String, Object>(arguments)); _id = id; @@ -243,13 +237,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, { Object defaultGroup = arguments.get(Queue.MESSAGE_GROUP_DEFAULT_GROUP); _messageGroupManager = - new DefinedGroupMessageGroupManager(String.valueOf(arguments.get(Queue.MESSAGE_GROUP_KEY)), + new DefinedGroupMessageGroupManager<E,Q,L>(String.valueOf(arguments.get(Queue.MESSAGE_GROUP_KEY)), defaultGroup == null ? DEFAULT_SHARED_MESSAGE_GROUP : defaultGroup.toString(), this); } else { - _messageGroupManager = new AssignedConsumerMessageGroupManager(String.valueOf(arguments.get( + _messageGroupManager = new AssignedConsumerMessageGroupManager<E,Q,L>(String.valueOf(arguments.get( Queue.MESSAGE_GROUP_KEY)), DEFAULT_MAX_GROUPS); } } @@ -281,21 +275,20 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } catch (RejectedExecutionException ree) { - if (_stopped.get()) - { - // Ignore - SubFlusherRunner or QueueRunner submitted execution as queue was being stopped. - } - else + // Ignore - SubFlusherRunner or QueueRunner submitted execution as queue was being stopped. + if(!_stopped.get()) { _logger.error("Unexpected rejected execution", ree); throw ree; + } + } } public void setNoLocal(boolean nolocal) { - _nolocal = nolocal; + _noLocal = nolocal; } public UUID getId() @@ -384,7 +377,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, @Override - public synchronized QueueConsumer addConsumer(final ConsumerTarget target, + public synchronized <T extends ConsumerTarget> QueueConsumer<T,E,Q,L> addConsumer(final T target, final FilterManager filters, final Class<? extends ServerMessage> messageClass, final String consumerName, @@ -412,10 +405,10 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, throw new ExistingConsumerPreventsExclusive(); } - QueueConsumer consumer = new QueueConsumer(filters, messageClass, - optionSet.contains(Consumer.Option.ACQUIRES), - optionSet.contains(Consumer.Option.SEES_REQUEUES), - consumerName, optionSet.contains(Consumer.Option.TRANSIENT), target); + QueueConsumer<T,E,Q,L> consumer = new QueueConsumer<T,E,Q,L>(filters, messageClass, + optionSet.contains(Consumer.Option.ACQUIRES), + optionSet.contains(Consumer.Option.SEES_REQUEUES), + consumerName, optionSet.contains(Consumer.Option.TRANSIENT), target); target.consumerAdded(consumer); @@ -430,21 +423,21 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } consumer.setStateListener(this); - consumer.setQueueContext(new QueueContext(_entries.getHead())); + consumer.setQueueContext(new QueueContext<E,Q,L>(_entries.getHead())); if (!isDeleted()) { - consumer.setQueue(this, exclusive); - if(_nolocal) + consumer.setQueue((Q)this, exclusive); + if(_noLocal) { - consumer.setNoLocal(_nolocal); + consumer.setNoLocal(true); } synchronized (_consumerListeners) { - for(ConsumerRegistrationListener listener : _consumerListeners) + for(ConsumerRegistrationListener<Q> listener : _consumerListeners) { - listener.consumerAdded(this, consumer); + listener.consumerAdded((Q)this, consumer); } } @@ -466,7 +459,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - synchronized void unregisterConsumer(final QueueConsumer consumer) throws AMQException + synchronized void unregisterConsumer(final QueueConsumer<?,E,Q,L> consumer) throws AMQException { if (consumer == null) { @@ -494,9 +487,9 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, synchronized (_consumerListeners) { - for(ConsumerRegistrationListener listener : _consumerListeners) + for(ConsumerRegistrationListener<Q> listener : _consumerListeners) { - listener.consumerRemoved(this, consumer); + listener.consumerRemoved((Q)this, consumer); } } @@ -519,10 +512,10 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - public Collection<QueueConsumer> getConsumers() + public Collection<QueueConsumer<?,E,Q,L>> getConsumers() { - List<QueueConsumer> consumers = new ArrayList<QueueConsumer>(); - QueueConsumerList.ConsumerNodeIterator iter = _consumerList.iterator(); + List<QueueConsumer<?,E,Q,L>> consumers = new ArrayList<QueueConsumer<?,E,Q,L>>(); + QueueConsumerList.ConsumerNodeIterator<E,Q,L> iter = _consumerList.iterator(); while(iter.advance()) { consumers.add(iter.getNode().getConsumer()); @@ -531,7 +524,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - public void addConsumerRegistrationListener(final ConsumerRegistrationListener listener) + public void addConsumerRegistrationListener(final ConsumerRegistrationListener<Q> listener) { synchronized (_consumerListeners) { @@ -539,7 +532,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - public void removeConsumerRegistrationListener(final ConsumerRegistrationListener listener) + public void removeConsumerRegistrationListener(final ConsumerRegistrationListener<Q> listener) { synchronized (_consumerListeners) { @@ -547,9 +540,9 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - public void resetSubPointersForGroups(QueueConsumer consumer, boolean clearAssignments) + public void resetSubPointersForGroups(QueueConsumer<?,E,Q,L> consumer, boolean clearAssignments) { - QueueEntry entry = _messageGroupManager.findEarliestAssignedAvailableEntry(consumer); + E entry = _messageGroupManager.findEarliestAssignedAvailableEntry(consumer); if(clearAssignments) { _messageGroupManager.clearAssignments(consumer); @@ -557,11 +550,11 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, if(entry != null) { - QueueConsumerList.ConsumerNodeIterator subscriberIter = _consumerList.iterator(); + QueueConsumerList.ConsumerNodeIterator<E,Q,L> subscriberIter = _consumerList.iterator(); // iterate over all the subscribers, and if they are in advance of this queue entry then move them backwards while (subscriberIter.advance()) { - QueueConsumer sub = subscriberIter.getNode().getConsumer(); + QueueConsumer<?,E,Q,L> sub = subscriberIter.getNode().getConsumer(); // we don't make browsers send the same stuff twice if (sub.seesRequeues()) @@ -599,11 +592,6 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - public int getBindingCountHigh() - { - return _bindingCountHigh.get(); - } - public void removeBinding(final Binding binding) { _bindings.remove(binding); @@ -626,7 +614,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, // ------ Enqueue / Dequeue - public void enqueue(ServerMessage message, Action<MessageInstance<? extends Consumer>> action) throws AMQException + public void enqueue(ServerMessage message, Action<? super MessageInstance<?, QueueConsumer<?,E,Q,L>>> action) throws AMQException { incrementQueueCount(); incrementQueueSize(message); @@ -634,8 +622,8 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, _totalMessagesReceived.incrementAndGet(); - QueueEntry entry; - final QueueConsumer exclusiveSub = _exclusiveSubscriber; + E entry; + final QueueConsumer<?,E,Q,L> exclusiveSub = _exclusiveSubscriber; entry = _entries.add(message); if(action != null || (exclusiveSub == null && _queueRunner.isIdle())) @@ -645,8 +633,8 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, iterate over consumers and if any is at the end of the queue and can deliver this message, then deliver the message */ - QueueConsumerList.ConsumerNode node = _consumerList.getMarkedNode(); - QueueConsumerList.ConsumerNode nextNode = node.findNext(); + QueueConsumerList.ConsumerNode<E,Q,L> node = _consumerList.getMarkedNode(); + QueueConsumerList.ConsumerNode<E,Q,L> nextNode = node.findNext(); if (nextNode == null) { nextNode = _consumerList.getHead().findNext(); @@ -682,7 +670,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, else { // if consumer at end, and active, offer - QueueConsumer sub = nextNode.getConsumer(); + QueueConsumer<?,E,Q,L> sub = nextNode.getConsumer(); deliverToConsumer(sub, entry); } nextNode = nextNode.findNext(); @@ -714,7 +702,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - private void deliverToConsumer(final QueueConsumer sub, final QueueEntry entry) + private void deliverToConsumer(final QueueConsumer<?,E,Q,L> sub, final E entry) throws AMQException { @@ -746,7 +734,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - private boolean assign(final QueueConsumer sub, final QueueEntry entry) + private boolean assign(final QueueConsumer<?,E,Q,L> sub, final E entry) { if(_messageGroupManager == null) { @@ -760,7 +748,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - private boolean mightAssign(final QueueConsumer sub, final QueueEntry entry) + private boolean mightAssign(final QueueConsumer<?,E,Q,L> sub, final E entry) { if(_messageGroupManager == null || !sub.acquires()) { @@ -770,7 +758,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return (assigned == null) || (assigned == sub); } - protected void checkConsumersNotAheadOfDelivery(final QueueEntry entry) + protected void checkConsumersNotAheadOfDelivery(final E entry) { // This method is only required for queues which mess with ordering // Simple Queues don't :-) @@ -804,7 +792,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, getAtomicQueueCount().incrementAndGet(); } - private void deliverMessage(final QueueConsumer sub, final QueueEntry entry, boolean batch) + private void deliverMessage(final QueueConsumer<?,E,Q,L> sub, final E entry, boolean batch) throws AMQException { setLastSeenEntry(sub, entry); @@ -815,18 +803,18 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, sub.send(entry, batch); } - private boolean consumerReadyAndHasInterest(final QueueConsumer sub, final QueueEntry entry) throws AMQException + private boolean consumerReadyAndHasInterest(final QueueConsumer<?,E,Q,L> sub, final E entry) throws AMQException { return sub.hasInterest(entry) && (getNextAvailableEntry(sub) == entry); } - private void setLastSeenEntry(final QueueConsumer sub, final QueueEntry entry) + private void setLastSeenEntry(final QueueConsumer<?,E,Q,L> sub, final E entry) { - QueueContext subContext = sub.getQueueContext(); + QueueContext<E,Q,L> subContext = sub.getQueueContext(); if (subContext != null) { - QueueEntry releasedEntry = subContext.getReleasedEntry(); + E releasedEntry = subContext.getReleasedEntry(); QueueContext._lastSeenUpdater.set(subContext, entry); if(releasedEntry == entry) @@ -836,13 +824,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - private void updateSubRequeueEntry(final QueueConsumer sub, final QueueEntry entry) + private void updateSubRequeueEntry(final QueueConsumer<?,E,Q,L> sub, final E entry) { - QueueContext subContext = sub.getQueueContext(); + QueueContext<E,Q,L> subContext = sub.getQueueContext(); if(subContext != null) { - QueueEntry oldEntry; + E oldEntry; while((oldEntry = subContext.getReleasedEntry()) == null || oldEntry.compareTo(entry) > 0) { @@ -854,13 +842,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - public void requeue(QueueEntry entry) + public void requeue(E entry) { - QueueConsumerList.ConsumerNodeIterator subscriberIter = _consumerList.iterator(); + QueueConsumerList.ConsumerNodeIterator<E,Q,L> subscriberIter = _consumerList.iterator(); // iterate over all the subscribers, and if they are in advance of this queue entry then move them backwards while (subscriberIter.advance() && entry.isAvailable()) { - QueueConsumer sub = subscriberIter.getNode().getConsumer(); + QueueConsumer<?,E,Q,L> sub = subscriberIter.getNode().getConsumer(); // we don't make browsers send the same stuff twice if (sub.seesRequeues()) @@ -873,7 +861,8 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - public void dequeue(QueueEntry entry, Consumer sub) + @Override + public void dequeue(E entry) { decrementQueueCount(); decrementQueueSize(entry); @@ -886,7 +875,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - private void decrementQueueSize(final QueueEntry entry) + private void decrementQueueSize(final E entry) { final ServerMessage message = entry.getMessage(); long size = message.getSize(); @@ -905,7 +894,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, _dequeueCount.incrementAndGet(); } - public boolean resend(final QueueEntry entry, final Consumer consumer) throws AMQException + public boolean resend(final E entry, final QueueConsumer<?,E,Q,L> consumer) throws AMQException { /* TODO : This is wrong as the consumer may be suspended, we should instead change the state of the message entry to resend and move back the consumer pointer. */ @@ -915,7 +904,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, { if (!consumer.isClosed()) { - deliverMessage((QueueConsumer) consumer, entry, false); + deliverMessage(consumer, entry, false); return true; } else @@ -981,11 +970,11 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, public long getOldestMessageArrivalTime() { - QueueEntry entry = getOldestQueueEntry(); + E entry = getOldestQueueEntry(); return entry == null ? Long.MAX_VALUE : entry.getMessage().getArrivalTime(); } - protected QueueEntry getOldestQueueEntry() + protected E getOldestQueueEntry() { return _entries.next(_entries.getHead()); } @@ -995,13 +984,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return _deleted.get(); } - public List<QueueEntry> getMessagesOnTheQueue() + public List<E> getMessagesOnTheQueue() { - ArrayList<QueueEntry> entryList = new ArrayList<QueueEntry>(); - QueueEntryIterator queueListIterator = _entries.iterator(); + ArrayList<E> entryList = new ArrayList<E>(); + QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator(); while (queueListIterator.advance()) { - QueueEntry node = queueListIterator.getNode(); + E node = queueListIterator.getNode(); if (node != null && !node.isDeleted()) { entryList.add(node); @@ -1011,7 +1000,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - public void stateChanged(QueueConsumer sub, QueueConsumer.State oldState, QueueConsumer.State newState) + public void stateChanged(QueueConsumer<?,E,Q,L> sub, QueueConsumer.State oldState, QueueConsumer.State newState) { if (oldState == QueueConsumer.State.ACTIVE && newState != QueueConsumer.State.ACTIVE) { @@ -1029,7 +1018,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - public int compareTo(final AMQQueue o) + public int compareTo(final Q o) { return _name.compareTo(o.getName()); } @@ -1049,7 +1038,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return _exclusiveSubscriber != null; } - private void setExclusiveSubscriber(QueueConsumer exclusiveSubscriber) + private void setExclusiveSubscriber(QueueConsumer<?,E,Q,L> exclusiveSubscriber) { _exclusiveSubscriber = exclusiveSubscriber; } @@ -1060,32 +1049,32 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } /** Used to track bindings to exchanges so that on deletion they can easily be cancelled. */ - protected QueueEntryList getEntries() + protected L getEntries() { return _entries; } - protected QueueConsumerList getConsumerList() + protected QueueConsumerList<E,Q,L> getConsumerList() { return _consumerList; } - public static interface QueueEntryFilter + public static interface QueueEntryFilter<E extends QueueEntry> { - public boolean accept(QueueEntry entry); + public boolean accept(E entry); public boolean filterComplete(); } - public List<QueueEntry> getMessagesOnTheQueue(final long fromMessageId, final long toMessageId) + public List<E> getMessagesOnTheQueue(final long fromMessageId, final long toMessageId) { - return getMessagesOnTheQueue(new QueueEntryFilter() + return getMessagesOnTheQueue(new QueueEntryFilter<E>() { - public boolean accept(QueueEntry entry) + public boolean accept(E entry) { final long messageId = entry.getMessage().getMessageNumber(); return messageId >= fromMessageId && messageId <= toMessageId; @@ -1098,13 +1087,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, }); } - public QueueEntry getMessageOnTheQueue(final long messageId) + public E getMessageOnTheQueue(final long messageId) { - List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() + List<E> entries = getMessagesOnTheQueue(new QueueEntryFilter<E>() { private boolean _complete; - public boolean accept(QueueEntry entry) + public boolean accept(E entry) { _complete = entry.getMessage().getMessageNumber() == messageId; return _complete; @@ -1118,13 +1107,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return entries.isEmpty() ? null : entries.get(0); } - public List<QueueEntry> getMessagesOnTheQueue(QueueEntryFilter filter) + public List<E> getMessagesOnTheQueue(QueueEntryFilter<E> filter) { - ArrayList<QueueEntry> entryList = new ArrayList<QueueEntry>(); - QueueEntryIterator queueListIterator = _entries.iterator(); + ArrayList<E> entryList = new ArrayList<E>(); + QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator(); while (queueListIterator.advance() && !filter.filterComplete()) { - QueueEntry node = queueListIterator.getNode(); + E node = queueListIterator.getNode(); if (!node.isDeleted() && filter.accept(node)) { entryList.add(node); @@ -1134,13 +1123,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - public void visit(final QueueEntryVisitor visitor) + public void visit(final QueueEntryVisitor<E> visitor) { - QueueEntryIterator queueListIterator = _entries.iterator(); + QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator(); while(queueListIterator.advance()) { - QueueEntry node = queueListIterator.getNode(); + E node = queueListIterator.getNode(); if(!node.isDeleted()) { @@ -1157,17 +1146,17 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, * * The 'queue position' index starts from 1. Using 0 in 'from' will be ignored and continue from 1. * Using 0 in the 'to' field will return an empty list regardless of the 'from' value. - * @param fromPosition - * @param toPosition - * @return + * @param fromPosition first message position + * @param toPosition last message position + * @return list of messages */ - public List<QueueEntry> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition) + public List<E> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition) { - return getMessagesOnTheQueue(new QueueEntryFilter() + return getMessagesOnTheQueue(new QueueEntryFilter<E>() { private long position = 0; - public boolean accept(QueueEntry entry) + public boolean accept(E entry) { position++; return (position >= fromPosition) && (position <= toPosition); @@ -1196,12 +1185,12 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, // TODO - now only used by the tests public void deleteMessageFromTop() { - QueueEntryIterator queueListIterator = _entries.iterator(); + QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator(); boolean noDeletes = true; while (noDeletes && queueListIterator.advance()) { - QueueEntry node = queueListIterator.getNode(); + E node = queueListIterator.getNode(); if (node.acquire()) { dequeueEntry(node); @@ -1224,14 +1213,14 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, throw new AMQSecurityException("Permission denied: queue " + getName()); } - QueueEntryIterator queueListIterator = _entries.iterator(); + QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator(); long count = 0; ServerTransaction txn = new LocalTransaction(getVirtualHost().getMessageStore()); while (queueListIterator.advance()) { - QueueEntry node = queueListIterator.getNode(); + E node = queueListIterator.getNode(); if (node.acquire()) { dequeueEntry(node, txn); @@ -1248,13 +1237,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return count; } - private void dequeueEntry(final QueueEntry node) + private void dequeueEntry(final E node) { ServerTransaction txn = new AutoCommitTransaction(getVirtualHost().getMessageStore()); dequeueEntry(node, txn); } - private void dequeueEntry(final QueueEntry node, ServerTransaction txn) + private void dequeueEntry(final E node, ServerTransaction txn) { txn.dequeue(this, node.getMessage(), new ServerTransaction.Action() @@ -1283,7 +1272,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } // TODO list all thrown exceptions - public int delete() throws AMQSecurityException, AMQException + public int delete() throws AMQException { // Check access if (!_virtualHost.getSecurityManager().authoriseDelete(this)) @@ -1313,10 +1302,10 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() + List<E> entries = getMessagesOnTheQueue(new QueueEntryFilter<E>() { - public boolean accept(QueueEntry entry) + public boolean accept(E entry) { return entry.acquire(); } @@ -1330,7 +1319,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, ServerTransaction txn = new LocalTransaction(getVirtualHost().getMessageStore()); - for(final QueueEntry entry : entries) + for(final E entry : entries) { // TODO log requeues with a post enqueue action int requeues = entry.routeToAlternate(null, txn); @@ -1435,7 +1424,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - public void deliverAsync(QueueConsumer sub) + public void deliverAsync(QueueConsumer<?,E,Q,L> sub) { if(_exclusiveSubscriber == null) { @@ -1449,7 +1438,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } - void flushConsumer(QueueConsumer sub) throws AMQException + void flushConsumer(QueueConsumer<?,E,Q,L> sub) throws AMQException { // Access control if (!getVirtualHost().getSecurityManager().authoriseConsume(this)) @@ -1459,7 +1448,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, flushConsumer(sub, Long.MAX_VALUE); } - boolean flushConsumer(QueueConsumer sub, long iterations) throws AMQException + boolean flushConsumer(QueueConsumer<?,E,Q,L> sub, long iterations) throws AMQException { boolean atTail = false; final boolean keepSendLockHeld = iterations <= SimpleAMQQueue.MAX_ASYNC_DELIVERIES; @@ -1480,8 +1469,8 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, sub.getSendLock(); } - atTail = attemptDelivery((QueueConsumer)sub, true); - if (atTail && getNextAvailableEntry((QueueConsumer)sub) == null) + atTail = attemptDelivery(sub, true); + if (atTail && getNextAvailableEntry(sub) == null) { queueEmpty = true; } @@ -1532,12 +1521,12 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, * Looks up the next node for the consumer and attempts to deliver it. * * - * @param sub - * @param batch + * @param sub the consumer + * @param batch true if processing can be batched * @return true if we have completed all possible deliveries for this sub. * @throws AMQException */ - private boolean attemptDelivery(QueueConsumer sub, boolean batch) throws AMQException + private boolean attemptDelivery(QueueConsumer<?,E,Q,L> sub, boolean batch) throws AMQException { boolean atTail = false; @@ -1545,7 +1534,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, if (subActive) { - QueueEntry node = getNextAvailableEntry(sub); + E node = getNextAvailableEntry(sub); if (node != null && node.isAvailable()) { @@ -1582,11 +1571,11 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, protected void advanceAllConsumers() throws AMQException { - QueueConsumerList.ConsumerNodeIterator consumerNodeIterator = _consumerList.iterator(); + QueueConsumerList.ConsumerNodeIterator<E,Q,L> consumerNodeIterator = _consumerList.iterator(); while (consumerNodeIterator.advance()) { - QueueConsumerList.ConsumerNode subNode = consumerNodeIterator.getNode(); - QueueConsumer sub = subNode.getConsumer(); + QueueConsumerList.ConsumerNode<E,Q,L> subNode = consumerNodeIterator.getNode(); + QueueConsumer<?,E,Q,L> sub = subNode.getConsumer(); if(sub.acquires()) { getNextAvailableEntry(sub); @@ -1598,16 +1587,16 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - private QueueEntry getNextAvailableEntry(final QueueConsumer sub) + private E getNextAvailableEntry(final QueueConsumer<?,E,Q,L> sub) throws AMQException { - QueueContext context = sub.getQueueContext(); + QueueContext<E,Q,L> context = sub.getQueueContext(); if(context != null) { - QueueEntry lastSeen = context.getLastSeenEntry(); - QueueEntry releasedNode = context.getReleasedEntry(); + E lastSeen = context.getLastSeenEntry(); + E releasedNode = context.getReleasedEntry(); - QueueEntry node = (releasedNode != null && lastSeen.compareTo(releasedNode)>=0) ? releasedNode : _entries.next(lastSeen); + E node = (releasedNode != null && lastSeen.compareTo(releasedNode)>=0) ? releasedNode : _entries.next(lastSeen); boolean expired = false; while (node != null && (!node.isAvailable() || (expired = node.expired()) || !sub.hasInterest(node) || @@ -1639,12 +1628,12 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, } } - public boolean isEntryAheadOfConsumer(QueueEntry entry, QueueConsumer sub) + public boolean isEntryAheadOfConsumer(E entry, QueueConsumer<?,E,Q,L> sub) { - QueueContext context = sub.getQueueContext(); + QueueContext<E,Q,L> context = sub.getQueueContext(); if(context != null) { - QueueEntry releasedNode = context.getReleasedEntry(); + E releasedNode = context.getReleasedEntry(); return releasedNode != null && releasedNode.compareTo(entry) < 0; } else @@ -1681,7 +1670,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, */ public long processQueue(QueueRunner runner) throws AMQException { - long stateChangeCount = Long.MIN_VALUE; + long stateChangeCount; long previousStateChangeCount = Long.MIN_VALUE; long rVal = Long.MIN_VALUE; boolean deliveryIncomplete = true; @@ -1716,11 +1705,11 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, boolean allConsumersDone = true; boolean consumerDone; - QueueConsumerList.ConsumerNodeIterator consumerNodeIterator = _consumerList.iterator(); + QueueConsumerList.ConsumerNodeIterator<E,Q,L> consumerNodeIterator = _consumerList.iterator(); //iterate over the subscribers and try to advance their pointer while (consumerNodeIterator.advance()) { - QueueConsumer sub = consumerNodeIterator.getNode().getConsumer(); + QueueConsumer<?,E,Q,L> sub = consumerNodeIterator.getNode().getConsumer(); sub.getSendLock(); try @@ -1802,11 +1791,11 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, public void checkMessageStatus() throws AMQException { - QueueEntryIterator queueListIterator = _entries.iterator(); + QueueEntryIterator<E,Q,L,QueueConsumer<?,E,Q,L>> queueListIterator = _entries.iterator(); while (queueListIterator.advance()) { - QueueEntry node = queueListIterator.getNode(); + E node = queueListIterator.getNode(); // Only process nodes that are not currently deleted and not dequeued if (!node.isDeleted()) { @@ -1953,12 +1942,12 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return _notificationChecks; } - private final class QueueEntryListener implements StateChangeListener<MessageInstance<QueueConsumer>, QueueEntry.State> + private final class QueueEntryListener implements StateChangeListener<E, QueueEntry.State> { - private final QueueConsumer _sub; + private final QueueConsumer<?,E,Q,L> _sub; - public QueueEntryListener(final QueueConsumer sub) + public QueueEntryListener(final QueueConsumer<?,E,Q,L> sub) { _sub = sub; } @@ -1974,7 +1963,7 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return System.identityHashCode(_sub); } - public void stateChanged(MessageInstance entry, QueueEntry.State oldSate, QueueEntry.State newState) + public void stateChanged(E entry, QueueEntry.State oldSate, QueueEntry.State newState) { entry.removeStateChangeListener(this); deliverAsync(_sub); @@ -2082,13 +2071,13 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return _unackedMsgBytes.get(); } - public void decrementUnackedMsgCount(QueueEntry queueEntry) + public void decrementUnackedMsgCount(E queueEntry) { _unackedMsgCount.decrementAndGet(); _unackedMsgBytes.addAndGet(-queueEntry.getSize()); } - private void incrementUnackedMsgCount(QueueEntry entry) + private void incrementUnackedMsgCount(E entry) { _unackedMsgCount.incrementAndGet(); _unackedMsgBytes.addAndGet(entry.getSize()); @@ -2159,10 +2148,10 @@ public class SimpleAMQQueue implements AMQQueue<QueueConsumer>, return (String) _arguments.get(Queue.DESCRIPTION); } - public final int send(final ServerMessage message, + public final <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message, final InstanceProperties instanceProperties, final ServerTransaction txn, - final Action<MessageInstance<? extends Consumer>> postEnqueueAction) + final Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction) { txn.enqueue(this,message, new ServerTransaction.Action() { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java index 101771c7cc..b6954e0696 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java @@ -1,205 +1,25 @@ /* -* -* Licensed to the Apache Software Foundation (ASF) under one -* or more contributor license agreements. See the NOTICE file -* distributed with this work for additional information -* regarding copyright ownership. The ASF licenses this file -* to you under the Apache License, Version 2.0 (the -* "License"); you may not use this file except in compliance -* with the License. You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, -* software distributed under the License is distributed on an -* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -* KIND, either express or implied. See the License for the -* specific language governing permissions and limitations -* under the License. -* -*/ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ package org.apache.qpid.server.queue; -import org.apache.qpid.server.message.ServerMessage; - -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - -public class SimpleQueueEntryList implements QueueEntryList<SimpleQueueEntryImpl> +public interface SimpleQueueEntryList<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> extends QueueEntryList<E,Q,L,QueueConsumer<?,E,Q,L>> { - - private final SimpleQueueEntryImpl _head; - - private volatile SimpleQueueEntryImpl _tail; - - static final AtomicReferenceFieldUpdater<SimpleQueueEntryList, SimpleQueueEntryImpl> - _tailUpdater = - AtomicReferenceFieldUpdater.newUpdater - (SimpleQueueEntryList.class, SimpleQueueEntryImpl.class, "_tail"); - - - private final AMQQueue<QueueConsumer> _queue; - - static final AtomicReferenceFieldUpdater<SimpleQueueEntryImpl, SimpleQueueEntryImpl> - _nextUpdater = SimpleQueueEntryImpl._nextUpdater; - - private AtomicLong _scavenges = new AtomicLong(0L); - private final long _scavengeCount = Integer.getInteger("qpid.queue.scavenge_count", 50); - private final AtomicReference<SimpleQueueEntryImpl> _unscavengedHWM = new AtomicReference<SimpleQueueEntryImpl>(); - - - public SimpleQueueEntryList(AMQQueue<QueueConsumer> queue) - { - _queue = queue; - _head = new SimpleQueueEntryImpl(this); - _tail = _head; - } - - void scavenge() - { - SimpleQueueEntryImpl hwm = _unscavengedHWM.getAndSet(null); - SimpleQueueEntryImpl next = _head.getNextValidEntry(); - - if(hwm != null) - { - while (next != null && hwm.compareTo(next)>0) - { - next = next.getNextValidEntry(); - } - } - } - - - public AMQQueue<QueueConsumer> getQueue() - { - return _queue; - } - - - public SimpleQueueEntryImpl add(ServerMessage message) - { - SimpleQueueEntryImpl node = createQueueEntry(message); - for (;;) - { - SimpleQueueEntryImpl tail = _tail; - SimpleQueueEntryImpl next = tail.getNextNode(); - if (tail == _tail) - { - if (next == null) - { - node.setEntryId(tail.getEntryId()+1); - if (_nextUpdater.compareAndSet(tail, null, node)) - { - _tailUpdater.compareAndSet(this, tail, node); - - return node; - } - } - else - { - _tailUpdater.compareAndSet(this,tail, next); - } - } - } - } - - protected SimpleQueueEntryImpl createQueueEntry(ServerMessage<?> message) - { - return new SimpleQueueEntryImpl(this, message); - } - - public SimpleQueueEntryImpl next(SimpleQueueEntryImpl node) - { - return node.getNextValidEntry(); - } - - public static class QueueEntryIteratorImpl implements QueueEntryIterator<SimpleQueueEntryImpl> - { - private SimpleQueueEntryImpl _lastNode; - - QueueEntryIteratorImpl(SimpleQueueEntryImpl startNode) - { - _lastNode = startNode; - } - - public boolean atTail() - { - return _lastNode.getNextValidEntry() == null; - } - - public SimpleQueueEntryImpl getNode() - { - return _lastNode; - } - - public boolean advance() - { - SimpleQueueEntryImpl nextValidNode = _lastNode.getNextValidEntry(); - - if(nextValidNode != null) - { - _lastNode = nextValidNode; - } - - return nextValidNode != null; - } - } - - public QueueEntryIteratorImpl iterator() - { - return new QueueEntryIteratorImpl(_head); - } - - - public SimpleQueueEntryImpl getHead() - { - return _head; - } - - public void entryDeleted(SimpleQueueEntryImpl queueEntry) - { - SimpleQueueEntryImpl next = _head.getNextNode(); - SimpleQueueEntryImpl newNext = _head.getNextValidEntry(); - - // the head of the queue has not been deleted, hence the deletion must have been mid queue. - if (next == newNext) - { - SimpleQueueEntryImpl unscavengedHWM = _unscavengedHWM.get(); - while(unscavengedHWM == null || unscavengedHWM.compareTo(queueEntry)<0) - { - _unscavengedHWM.compareAndSet(unscavengedHWM, queueEntry); - unscavengedHWM = _unscavengedHWM.get(); - } - if (_scavenges.incrementAndGet() > _scavengeCount) - { - _scavenges.set(0L); - scavenge(); - } - } - else - { - SimpleQueueEntryImpl unscavengedHWM = _unscavengedHWM.get(); - if(unscavengedHWM != null && (next == null || unscavengedHWM.compareTo(next) < 0)) - { - _unscavengedHWM.compareAndSet(unscavengedHWM, null); - } - } - } - - public int getPriorities() - { - return 0; - } - - static class Factory implements QueueEntryListFactory - { - - public SimpleQueueEntryList createQueueEntryList(AMQQueue queue) - { - return new SimpleQueueEntryList(queue); - } - } - - } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java index cad1aa6d4f..2cae18f3ec 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueue.java @@ -29,7 +29,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Map; import java.util.UUID; -public class SortedQueue extends OutOfOrderQueue +public class SortedQueue extends OutOfOrderQueue<SortedQueueEntry, SortedQueue, SortedQueueEntryList> { //Lock object to synchronize enqueue. Used instead of the object //monitor to prevent lock order issues with consumer sendLocks @@ -41,17 +41,33 @@ public class SortedQueue extends OutOfOrderQueue final boolean durable, final String owner, final boolean autoDelete, final boolean exclusive, final VirtualHost virtualHost, Map<String, Object> arguments, String sortedPropertyName) { + this(id, name, durable, owner, autoDelete, exclusive, + virtualHost, arguments, sortedPropertyName, new SortedQueueEntryListFactory(sortedPropertyName)); + } + + + protected SortedQueue(UUID id, final String name, + final boolean durable, final String owner, final boolean autoDelete, + final boolean exclusive, final VirtualHost virtualHost, + Map<String, Object> arguments, + String sortedPropertyName, + QueueEntryListFactory<SortedQueueEntry,SortedQueue,SortedQueueEntryList> factory) + { super(id, name, durable, owner, autoDelete, exclusive, - virtualHost, new SortedQueueEntryListFactory(sortedPropertyName), arguments); + virtualHost, factory, arguments); this._sortedPropertyName = sortedPropertyName; } + public String getSortedPropertyName() { return _sortedPropertyName; } - public void enqueue(ServerMessage message, Action<MessageInstance<? extends Consumer>> action) throws AMQException + @Override + public void enqueue(final ServerMessage message, + final Action<? super MessageInstance<?, QueueConsumer<?, SortedQueueEntry, SortedQueue, SortedQueueEntryList>>> action) + throws AMQException { synchronized (_sortedQueueLock) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntry.java index 1052adbe67..30d58138fb 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryImpl.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntry.java @@ -24,37 +24,37 @@ import org.apache.qpid.server.message.ServerMessage; /** * An implementation of QueueEntryImpl to be used in SortedQueueEntryList. */ -public class SortedQueueEntryImpl extends QueueEntryImpl +public class SortedQueueEntry extends QueueEntryImpl<SortedQueueEntry, SortedQueue, SortedQueueEntryList> { public static enum Colour { RED, BLACK }; - private volatile SortedQueueEntryImpl _next; - private SortedQueueEntryImpl _prev; + private volatile SortedQueueEntry _next; + private SortedQueueEntry _prev; private String _key; private Colour _colour = Colour.BLACK; - private SortedQueueEntryImpl _parent; - private SortedQueueEntryImpl _left; - private SortedQueueEntryImpl _right; + private SortedQueueEntry _parent; + private SortedQueueEntry _left; + private SortedQueueEntry _right; - public SortedQueueEntryImpl(final SortedQueueEntryList queueEntryList) + public SortedQueueEntry(final SortedQueueEntryList queueEntryList) { super(queueEntryList); } - public SortedQueueEntryImpl(final SortedQueueEntryList queueEntryList, - final ServerMessage message, final long entryId) + public SortedQueueEntry(final SortedQueueEntryList queueEntryList, + final ServerMessage message, final long entryId) { super(queueEntryList, message, entryId); } @Override - public int compareTo(final QueueEntry o) + public int compareTo(final SortedQueueEntry o) { - final String otherKey = ((SortedQueueEntryImpl) o)._key; + final String otherKey = o._key; final int compare = _key == null ? (otherKey == null ? 0 : -1) : otherKey == null ? 1 : _key.compareTo(otherKey); return compare == 0 ? super.compareTo(o) : compare; } @@ -69,33 +69,33 @@ public class SortedQueueEntryImpl extends QueueEntryImpl return _key; } - public SortedQueueEntryImpl getLeft() + public SortedQueueEntry getLeft() { return _left; } - public SortedQueueEntryImpl getNextNode() + public SortedQueueEntry getNextNode() { return _next; } @Override - public SortedQueueEntryImpl getNextValidEntry() + public SortedQueueEntry getNextValidEntry() { return getNextNode(); } - public SortedQueueEntryImpl getParent() + public SortedQueueEntry getParent() { return _parent; } - public SortedQueueEntryImpl getPrev() + public SortedQueueEntry getPrev() { return _prev; } - public SortedQueueEntryImpl getRight() + public SortedQueueEntry getRight() { return _right; } @@ -110,27 +110,27 @@ public class SortedQueueEntryImpl extends QueueEntryImpl _key = key; } - public void setLeft(final SortedQueueEntryImpl left) + public void setLeft(final SortedQueueEntry left) { _left = left; } - public void setNext(final SortedQueueEntryImpl next) + public void setNext(final SortedQueueEntry next) { _next = next; } - public void setParent(final SortedQueueEntryImpl parent) + public void setParent(final SortedQueueEntry parent) { _parent = parent; } - public void setPrev(final SortedQueueEntryImpl prev) + public void setPrev(final SortedQueueEntry prev) { _prev = prev; } - public void setRight(final SortedQueueEntryImpl right) + public void setRight(final SortedQueueEntry right) { _right = right; } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java index 336ee566eb..05b874cd91 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java @@ -21,7 +21,7 @@ package org.apache.qpid.server.queue; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.SortedQueueEntryImpl.Colour; +import org.apache.qpid.server.queue.SortedQueueEntry.Colour; /** * A sorted implementation of QueueEntryList. @@ -30,28 +30,28 @@ import org.apache.qpid.server.queue.SortedQueueEntryImpl.Colour; * ISBN-13: 978-0262033848 * see http://en.wikipedia.org/wiki/Red-black_tree */ -public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl> +public class SortedQueueEntryList implements SimpleQueueEntryList<SortedQueueEntry, SortedQueue, SortedQueueEntryList> { - private final SortedQueueEntryImpl _head; - private SortedQueueEntryImpl _root; + private final SortedQueueEntry _head; + private SortedQueueEntry _root; private long _entryId = Long.MIN_VALUE; private final Object _lock = new Object(); - private final AMQQueue<QueueConsumer> _queue; + private final SortedQueue _queue; private final String _propertyName; - public SortedQueueEntryList(final AMQQueue<QueueConsumer> queue, final String propertyName) + public SortedQueueEntryList(final SortedQueue queue, final String propertyName) { _queue = queue; - _head = new SortedQueueEntryImpl(this); + _head = new SortedQueueEntry(this); _propertyName = propertyName; } - public AMQQueue<QueueConsumer> getQueue() + public SortedQueue getQueue() { return _queue; } - public SortedQueueEntryImpl add(final ServerMessage message) + public SortedQueueEntry add(final ServerMessage message) { synchronized(_lock) { @@ -62,7 +62,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl key = val.toString(); } - final SortedQueueEntryImpl entry = new SortedQueueEntryImpl(this,message, ++_entryId); + final SortedQueueEntry entry = new SortedQueueEntry(this,message, ++_entryId); entry.setKey(key); insert(entry); @@ -75,9 +75,9 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl * Red Black Tree insert implementation. * @param entry the entry to insert. */ - private void insert(final SortedQueueEntryImpl entry) + private void insert(final SortedQueueEntry entry) { - SortedQueueEntryImpl node = _root; + SortedQueueEntry node; if((node = _root) == null) { _root = entry; @@ -87,7 +87,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl } else { - SortedQueueEntryImpl parent = null; + SortedQueueEntry parent = null; while(node != null) { parent = node; @@ -105,7 +105,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl if(entry.compareTo(parent) < 0) { parent.setLeft(entry); - final SortedQueueEntryImpl prev = parent.getPrev(); + final SortedQueueEntry prev = parent.getPrev(); entry.setNext(parent); prev.setNext(entry); entry.setPrev(prev); @@ -115,7 +115,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl { parent.setRight(entry); - final SortedQueueEntryImpl next = parent.getNextValidEntry(); + final SortedQueueEntry next = parent.getNextValidEntry(); entry.setNext(next); parent.setNext(entry); @@ -130,15 +130,15 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl insertFixup(entry); } - private void insertFixup(SortedQueueEntryImpl entry) + private void insertFixup(SortedQueueEntry entry) { while(isParentColour(entry, Colour.RED)) { - final SortedQueueEntryImpl grandparent = nodeGrandparent(entry); + final SortedQueueEntry grandparent = nodeGrandparent(entry); if(nodeParent(entry) == leftChild(grandparent)) { - final SortedQueueEntryImpl y = rightChild(grandparent); + final SortedQueueEntry y = rightChild(grandparent); if(isNodeColour(y, Colour.RED)) { setColour(nodeParent(entry), Colour.BLACK); @@ -160,7 +160,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl } else { - final SortedQueueEntryImpl y = leftChild(grandparent); + final SortedQueueEntry y = leftChild(grandparent); if(isNodeColour(y, Colour.RED)) { setColour(nodeParent(entry), Colour.BLACK); @@ -184,11 +184,11 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl _root.setColour(Colour.BLACK); } - private void leftRotate(final SortedQueueEntryImpl entry) + private void leftRotate(final SortedQueueEntry entry) { if(entry != null) { - final SortedQueueEntryImpl rightChild = rightChild(entry); + final SortedQueueEntry rightChild = rightChild(entry); entry.setRight(rightChild.getLeft()); if(entry.getRight() != null) { @@ -212,11 +212,11 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl } } - private void rightRotate(final SortedQueueEntryImpl entry) + private void rightRotate(final SortedQueueEntry entry) { if(entry != null) { - final SortedQueueEntryImpl leftChild = leftChild(entry); + final SortedQueueEntry leftChild = leftChild(entry); entry.setLeft(leftChild.getRight()); if(entry.getLeft() != null) { @@ -240,7 +240,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl } } - private void setColour(final SortedQueueEntryImpl node, final Colour colour) + private void setColour(final SortedQueueEntry node, final Colour colour) { if(node != null) { @@ -248,45 +248,45 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl } } - private SortedQueueEntryImpl leftChild(final SortedQueueEntryImpl node) + private SortedQueueEntry leftChild(final SortedQueueEntry node) { return node == null ? null : node.getLeft(); } - private SortedQueueEntryImpl rightChild(final SortedQueueEntryImpl node) + private SortedQueueEntry rightChild(final SortedQueueEntry node) { return node == null ? null : node.getRight(); } - private SortedQueueEntryImpl nodeParent(final SortedQueueEntryImpl node) + private SortedQueueEntry nodeParent(final SortedQueueEntry node) { return node == null ? null : node.getParent(); } - private SortedQueueEntryImpl nodeGrandparent(final SortedQueueEntryImpl node) + private SortedQueueEntry nodeGrandparent(final SortedQueueEntry node) { return nodeParent(nodeParent(node)); } - private boolean isParentColour(final SortedQueueEntryImpl node, final SortedQueueEntryImpl.Colour colour) + private boolean isParentColour(final SortedQueueEntry node, final SortedQueueEntry.Colour colour) { return node != null && isNodeColour(node.getParent(), colour); } - protected boolean isNodeColour(final SortedQueueEntryImpl node, final SortedQueueEntryImpl.Colour colour) + protected boolean isNodeColour(final SortedQueueEntry node, final SortedQueueEntry.Colour colour) { return (node == null ? Colour.BLACK : node.getColour()) == colour; } - public SortedQueueEntryImpl next(final SortedQueueEntryImpl node) + public SortedQueueEntry next(final SortedQueueEntry node) { synchronized(_lock) { if(node.isDeleted() && _head != node) { - SortedQueueEntryImpl current = _head; - SortedQueueEntryImpl next; + SortedQueueEntry current = _head; + SortedQueueEntry next; while(current != null) { next = current.getNextValidEntry(); @@ -308,22 +308,22 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl } } - public QueueEntryIterator<SortedQueueEntryImpl> iterator() + public QueueEntryIterator<SortedQueueEntry,SortedQueue,SortedQueueEntryList,QueueConsumer<?,SortedQueueEntry,SortedQueue,SortedQueueEntryList>> iterator() { return new QueueEntryIteratorImpl(_head); } - public SortedQueueEntryImpl getHead() + public SortedQueueEntry getHead() { return _head; } - protected SortedQueueEntryImpl getRoot() + protected SortedQueueEntry getRoot() { return _root; } - public void entryDeleted(final SortedQueueEntryImpl entry) + public void entryDeleted(final SortedQueueEntry entry) { synchronized(_lock) { @@ -336,20 +336,20 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl // Then deal with the easy doubly linked list deletion (need to do // this after the swap as the swap uses next - final SortedQueueEntryImpl prev = entry.getPrev(); + final SortedQueueEntry prev = entry.getPrev(); if(prev != null) { prev.setNext(entry.getNextValidEntry()); } - final SortedQueueEntryImpl next = entry.getNextValidEntry(); + final SortedQueueEntry next = entry.getNextValidEntry(); if(next != null) { next.setPrev(prev); } // now deal with splicing - final SortedQueueEntryImpl chosenChild; + final SortedQueueEntry chosenChild; if(leftChild(entry) != null) { @@ -428,14 +428,14 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl /** * Swaps the position of the node in the tree with it's successor * (that is the node with the next highest key) - * @param entry + * @param entry the entry to be swapped with its successor */ - private void swapWithSuccessor(final SortedQueueEntryImpl entry) + private void swapWithSuccessor(final SortedQueueEntry entry) { - final SortedQueueEntryImpl next = entry.getNextValidEntry(); - final SortedQueueEntryImpl nextParent = next.getParent(); - final SortedQueueEntryImpl nextLeft = next.getLeft(); - final SortedQueueEntryImpl nextRight = next.getRight(); + final SortedQueueEntry next = entry.getNextValidEntry(); + final SortedQueueEntry nextParent = next.getParent(); + final SortedQueueEntry nextLeft = next.getLeft(); + final SortedQueueEntry nextRight = next.getRight(); final Colour nextColour = next.getColour(); // Special case - the successor is the right child of the node @@ -530,7 +530,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl } } - private void deleteFixup(SortedQueueEntryImpl entry) + private void deleteFixup(SortedQueueEntry entry) { int i = 0; while(entry != null && entry != _root @@ -545,7 +545,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl if(entry == leftChild(nodeParent(entry))) { - SortedQueueEntryImpl rightSibling = rightChild(nodeParent(entry)); + SortedQueueEntry rightSibling = rightChild(nodeParent(entry)); if(isNodeColour(rightSibling, Colour.RED)) { setColour(rightSibling, Colour.BLACK); @@ -578,7 +578,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl } else { - SortedQueueEntryImpl leftSibling = leftChild(nodeParent(entry)); + SortedQueueEntry leftSibling = leftChild(nodeParent(entry)); if(isNodeColour(leftSibling, Colour.RED)) { setColour(leftSibling, Colour.BLACK); @@ -613,16 +613,16 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl setColour(entry, Colour.BLACK); } - private Colour getColour(final SortedQueueEntryImpl x) + private Colour getColour(final SortedQueueEntry x) { return x == null ? null : x.getColour(); } - public class QueueEntryIteratorImpl implements QueueEntryIterator<SortedQueueEntryImpl> + public class QueueEntryIteratorImpl implements QueueEntryIterator<SortedQueueEntry,SortedQueue,SortedQueueEntryList,QueueConsumer<?,SortedQueueEntry,SortedQueue,SortedQueueEntryList>> { - private SortedQueueEntryImpl _lastNode; + private SortedQueueEntry _lastNode; - public QueueEntryIteratorImpl(final SortedQueueEntryImpl startNode) + public QueueEntryIteratorImpl(final SortedQueueEntry startNode) { _lastNode = startNode; } @@ -632,7 +632,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl return next(_lastNode) == null; } - public SortedQueueEntryImpl getNode() + public SortedQueueEntry getNode() { return _lastNode; } @@ -641,7 +641,7 @@ public class SortedQueueEntryList implements QueueEntryList<SortedQueueEntryImpl { if(!atTail()) { - SortedQueueEntryImpl nextNode = next(_lastNode); + SortedQueueEntry nextNode = next(_lastNode); while(nextNode.isDeleted() && next(nextNode) != null) { nextNode = next(nextNode); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java index 87c79178f0..69ffcd67a7 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryListFactory.java @@ -19,7 +19,7 @@ */ package org.apache.qpid.server.queue; -public class SortedQueueEntryListFactory implements QueueEntryListFactory +public class SortedQueueEntryListFactory implements QueueEntryListFactory<SortedQueueEntry,SortedQueue,SortedQueueEntryList> { private final String _propertyName; @@ -30,9 +30,8 @@ public class SortedQueueEntryListFactory implements QueueEntryListFactory } @Override - public QueueEntryList<SortedQueueEntryImpl> createQueueEntryList(final AMQQueue queue) + public SortedQueueEntryList createQueueEntryList(final SortedQueue queue) { return new SortedQueueEntryList(queue, _propertyName); } - } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueue.java new file mode 100644 index 0000000000..e2ccdc45cf --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueue.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.queue; + +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.Map; +import java.util.UUID; + +public class StandardQueue extends SimpleAMQQueue<StandardQueueEntry,StandardQueue,StandardQueueEntryList> +{ + public StandardQueue(final UUID id, + final String name, + final boolean durable, + final String owner, + final boolean autoDelete, + final boolean exclusive, + final VirtualHost virtualHost, + final Map<String, Object> arguments) + { + super(id, name, durable, owner, autoDelete, exclusive, virtualHost, new StandardQueueEntryList.Factory(), arguments); + } +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntry.java new file mode 100644 index 0000000000..368015e9c0 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntry.java @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.queue; + +import org.apache.qpid.server.message.ServerMessage; + +public class StandardQueueEntry extends OrderedQueueEntry<StandardQueueEntry, StandardQueue, StandardQueueEntryList> +{ + protected StandardQueueEntry(final StandardQueueEntryList queueEntryList) + { + super(queueEntryList); + } + + public StandardQueueEntry(final StandardQueueEntryList queueEntryList, + final ServerMessage message, + final long entryId) + { + super(queueEntryList, message, entryId); + } + + public StandardQueueEntry(final StandardQueueEntryList queueEntryList, final ServerMessage message) + { + super(queueEntryList, message); + } + + +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntryList.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntryList.java new file mode 100644 index 0000000000..11ad04e61c --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/StandardQueueEntryList.java @@ -0,0 +1,57 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.queue; + +import org.apache.qpid.server.message.ServerMessage; + +public class StandardQueueEntryList extends OrderedQueueEntryList<StandardQueueEntry, StandardQueue, StandardQueueEntryList> +{ + + private static final HeadCreator<StandardQueueEntry, StandardQueue, StandardQueueEntryList> HEAD_CREATOR = new HeadCreator<StandardQueueEntry, StandardQueue, StandardQueueEntryList>() + { + @Override + public StandardQueueEntry createHead(final StandardQueueEntryList list) + { + return new StandardQueueEntry(list); + } + }; + + public StandardQueueEntryList(final StandardQueue queue) + { + super(queue, HEAD_CREATOR); + } + + + protected StandardQueueEntry createQueueEntry(ServerMessage<?> message) + { + return new StandardQueueEntry(this, message); + } + + static class Factory implements QueueEntryListFactory<StandardQueueEntry, StandardQueue, StandardQueueEntryList> + { + + public StandardQueueEntryList createQueueEntryList(StandardQueue queue) + { + return new StandardQueueEntryList(queue); + } + } + +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java index de7369f5ed..eff9bdf433 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java @@ -47,7 +47,7 @@ public class DurableConfigurationStoreHelper Queue.EXCLUSIVE, Queue.ALTERNATE_EXCHANGE)); - public static void updateQueue(DurableConfigurationStore store, AMQQueue<? extends Consumer> queue) throws AMQStoreException + public static void updateQueue(DurableConfigurationStore store, AMQQueue<?,?,?> queue) throws AMQStoreException { Map<String, Object> attributesMap = new LinkedHashMap<String, Object>(); attributesMap.put(Queue.NAME, queue.getName()); @@ -72,7 +72,7 @@ public class DurableConfigurationStoreHelper store.update(queue.getId(), QUEUE, attributesMap); } - public static void createQueue(DurableConfigurationStore store, AMQQueue<? extends Consumer> queue) + public static void createQueue(DurableConfigurationStore store, AMQQueue<?,?,?> queue) throws AMQStoreException { Map<String, Object> attributesMap = new HashMap<String, Object>(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java index 9a23e00f90..3d42b07117 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java @@ -105,6 +105,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg private final DtxRegistry _dtxRegistry; private final AMQQueueFactory _queueFactory; private final SystemNodeRegistry _systemNodeRegistry = new SystemNodeRegistry(); + private final org.apache.qpid.server.model.VirtualHost _model; private volatile State _state = State.INITIALISING; @@ -141,6 +142,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg _vhostConfig = hostConfig; _name = _vhostConfig.getName(); _dtxRegistry = new DtxRegistry(); + _model = virtualHost; _id = UUIDGenerator.generateVhostUUID(_name); @@ -1001,5 +1003,11 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg { return AbstractVirtualHost.this; } + + @Override + public org.apache.qpid.server.model.VirtualHost getVirtualHostModel() + { + return _model; + } } } diff --git a/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType b/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType new file mode 100644 index 0000000000..a744bfff53 --- /dev/null +++ b/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.message.internal.InternalMessageMetaDataType diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java index f60f173de9..4dd9831454 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java @@ -27,7 +27,7 @@ import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.queue.AMQPriorityQueue; +import org.apache.qpid.server.queue.PriorityQueue; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.util.BrokerTestHelper; @@ -113,17 +113,17 @@ public class VirtualHostConfigurationTest extends QpidTestCase // Check that atest was a priority queue with 5 priorities AMQQueue atest = vhost.getQueue("atest"); - assertTrue(atest instanceof AMQPriorityQueue); - assertEquals(5, ((AMQPriorityQueue) atest).getPriorities()); + assertTrue(atest instanceof PriorityQueue); + assertEquals(5, ((PriorityQueue) atest).getPriorities()); // Check that ptest was a priority queue with 10 priorities AMQQueue ptest = vhost.getQueue("ptest"); - assertTrue(ptest instanceof AMQPriorityQueue); - assertEquals(10, ((AMQPriorityQueue) ptest).getPriorities()); + assertTrue(ptest instanceof PriorityQueue); + assertEquals(10, ((PriorityQueue) ptest).getPriorities()); // Check that ntest wasn't a priority queue AMQQueue ntest = vhost.getQueue("ntest"); - assertFalse(ntest instanceof AMQPriorityQueue); + assertFalse(ntest instanceof PriorityQueue); } public void testQueueAlerts() throws Exception diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java index ea9d0ac693..8cab2e9058 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java @@ -74,7 +74,7 @@ public class TopicExchangeTest extends QpidTestCase public void testNoRoute() throws AMQException { - AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false, + AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.*.#.b",queue, _exchange, null)); @@ -86,7 +86,7 @@ public class TopicExchangeTest extends QpidTestCase public void testDirectMatch() throws AMQException { - AMQQueue<Consumer> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false, + AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.b",queue, _exchange, null)); @@ -109,7 +109,7 @@ public class TopicExchangeTest extends QpidTestCase public void testStarMatch() throws AMQException { - AMQQueue<Consumer> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, false, null); + AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.*",queue, _exchange, null)); @@ -140,7 +140,7 @@ public class TopicExchangeTest extends QpidTestCase public void testHashMatch() throws AMQException { - AMQQueue<Consumer> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, false, null); + AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.#",queue, _exchange, null)); @@ -191,7 +191,7 @@ public class TopicExchangeTest extends QpidTestCase public void testMidHash() throws AMQException { - AMQQueue<Consumer> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, + AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.*.#.b",queue, _exchange, null)); @@ -217,7 +217,7 @@ public class TopicExchangeTest extends QpidTestCase public void testMatchAfterHash() throws AMQException { - AMQQueue<Consumer> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, + AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.*.#.b.c",queue, _exchange, null)); @@ -256,7 +256,7 @@ public class TopicExchangeTest extends QpidTestCase public void testHashAfterHash() throws AMQException { - AMQQueue<Consumer> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, + AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.*.#.b.c.#.d",queue, _exchange, null)); @@ -278,7 +278,7 @@ public class TopicExchangeTest extends QpidTestCase public void testHashHash() throws AMQException { - AMQQueue<Consumer> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, + AMQQueue<?,?,?> queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.#.*.#.d",queue, _exchange, null)); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java index bcf54c97a4..febce9ea2e 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java @@ -231,7 +231,7 @@ public class AMQQueueFactoryTest extends QpidTestCase false, attributes); - assertEquals("Queue not a priority queue", AMQPriorityQueue.class, queue.getClass()); + assertEquals("Queue not a priority queue", PriorityQueue.class, queue.getClass()); verifyQueueRegistered("testPriorityQueue"); verifyRegisteredQueueCount(1); } @@ -246,7 +246,7 @@ public class AMQQueueFactoryTest extends QpidTestCase false, false, null); - assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass()); + assertEquals("Queue not a simple queue", StandardQueue.class, queue.getClass()); verifyQueueRegistered(queueName); //verify that no alternate exchange or DLQ were produced diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java index d67c70c831..c2291f5eed 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java @@ -28,6 +28,9 @@ import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.Collections; +import java.util.UUID; + public class ConflationQueueListTest extends TestCase { private static final String CONFLATION_KEY = "CONFLATION_KEY"; @@ -37,13 +40,15 @@ public class ConflationQueueListTest extends TestCase private static final String TEST_KEY_VALUE2 = "testKeyValue2"; private ConflationQueueList _list; - private AMQQueue _queue = createTestQueue(); + private ConflationQueue _queue; @Override protected void setUp() throws Exception { super.setUp(); - _list = new ConflationQueueList(_queue, CONFLATION_KEY); + _queue = new ConflationQueue(UUID.randomUUID(), getName(), false, null, false, false, mock(VirtualHost.class), + Collections.<String,Object>emptyMap(),CONFLATION_KEY); + _list = _queue.getEntries(); } public void testListHasNoEntries() @@ -175,7 +180,8 @@ public class ConflationQueueListTest extends TestCase private int countEntries(ConflationQueueList list) { - QueueEntryIterator<SimpleQueueEntryImpl> iterator = list.iterator(); + QueueEntryIterator<ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList,QueueConsumer<?,ConflationQueueList.ConflationQueueEntry, ConflationQueue, ConflationQueueList>> iterator = + list.iterator(); int count = 0; while(iterator.advance()) { diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java index 66c12717db..d1bc5effc0 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java @@ -33,6 +33,7 @@ import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.security.AuthorizationHolder; import org.apache.qpid.server.consumer.Consumer; import org.apache.qpid.server.consumer.ConsumerTarget; +import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.Action; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -45,7 +46,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; -public class MockAMQQueue implements AMQQueue<QueueConsumer> +public class MockAMQQueue implements AMQQueue { private boolean _deleted = false; private String _name; @@ -178,6 +179,8 @@ public class MockAMQQueue implements AMQQueue<QueueConsumer> return null; } + + public boolean isDurable() { return false; @@ -210,32 +213,55 @@ public class MockAMQQueue implements AMQQueue<QueueConsumer> } @Override - public QueueConsumer addConsumer(final ConsumerTarget target, + public boolean resend(final QueueEntry entry, final Consumer consumer) throws AMQException + { + return false; + } + + @Override + public void addQueueDeleteTask(final Action task) + { + + } + + @Override + public void enqueue(final ServerMessage message, final Action action) throws AMQException + { + + } + + @Override + public int compareTo(final Object o) + { + return 0; + } + + @Override + public Consumer addConsumer(final ConsumerTarget target, final FilterManager filters, - final Class<? extends ServerMessage> messageClass, + final Class messageClass, final String consumerName, - final EnumSet<Consumer.Option> options) throws AMQException + final EnumSet options) throws AMQException { return new QueueConsumer(filters, messageClass, options.contains(Consumer.Option.ACQUIRES), - options.contains(Consumer.Option.SEES_REQUEUES), consumerName, - options.contains(Consumer.Option.TRANSIENT), target ); + options.contains(Consumer.Option.SEES_REQUEUES), consumerName, + options.contains(Consumer.Option.TRANSIENT), target ); } + public String getName() { return _name; } - @Override - public int send(final ServerMessage message, - final InstanceProperties instanceProperties, - final ServerTransaction txn, - final Action<MessageInstance<? extends Consumer>> postEnqueueAction) + public int send(final ServerMessage message, + final InstanceProperties instanceProperties, + final ServerTransaction txn, + final Action postEnqueueAction) { return 0; } - public Collection<QueueConsumer> getConsumers() { return Collections.emptyList(); @@ -312,38 +338,39 @@ public class MockAMQQueue implements AMQQueue<QueueConsumer> return getMessageCount(); } - public void enqueue(ServerMessage message, Action<MessageInstance<? extends Consumer>> action) throws AMQException - { - } - public void requeue(QueueEntry entry) { } - public void dequeue(QueueEntry entry, Consumer sub) + public void dequeue(QueueEntry entry) { } - public boolean resend(QueueEntry entry, Consumer consumer) throws AMQException + public boolean resend(QueueEntry entry, QueueConsumer consumer) throws AMQException { return false; } - public void addQueueDeleteTask(Action<AMQQueue> task) + @Override + public void removeQueueDeleteTask(final Action task) { + } - public void removeQueueDeleteTask(final Action<AMQQueue> task) + @Override + public void decrementUnackedMsgCount(final QueueEntry queueEntry) { + } - public List<QueueEntry> getMessagesOnTheQueue() + @Override + public List getMessagesOnTheQueue() { return null; } - public List<QueueEntry> getMessagesOnTheQueue(long fromMessageId, long toMessageId) + public List getMessagesOnTheQueue(long fromMessageId, long toMessageId) { return null; } @@ -363,7 +390,7 @@ public class MockAMQQueue implements AMQQueue<QueueConsumer> return null; } - public List<QueueEntry> getMessagesRangeOnTheQueue(long fromPosition, long toPosition) + public List getMessagesRangeOnTheQueue(long fromPosition, long toPosition) { return null; } @@ -570,10 +597,6 @@ public class MockAMQQueue implements AMQQueue<QueueConsumer> return 0; } - public void decrementUnackedMsgCount(QueueEntry queueEntry) - { - - } public long getUnackedMessageCount() { @@ -617,4 +640,5 @@ public class MockAMQQueue implements AMQQueue<QueueConsumer> { return null; } + } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java index 89b366567d..386bb46044 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java @@ -32,7 +32,7 @@ import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.Action; import org.apache.qpid.server.util.StateChangeListener; -public class MockQueueEntry implements QueueEntry +public class MockMessageInstance implements MessageInstance<MockMessageInstance,Consumer> { private ServerMessage _message; @@ -42,13 +42,15 @@ public class MockQueueEntry implements QueueEntry return false; } - public boolean acquire(QueueConsumer sub) + @Override + public int getMaximumDeliveryCount() { - return false; + return 0; } @Override - public int getMaximumDeliveryCount() + public int routeToAlternate(final Action<? super MessageInstance<?, ? extends Consumer>> action, + final ServerTransaction txn) { return 0; } @@ -58,27 +60,24 @@ public class MockQueueEntry implements QueueEntry return false; } - public boolean isAcquiredBy(QueueConsumer consumer) + @Override + public boolean isAcquiredBy(final Consumer consumer) { return false; } - public void addStateChangeListener(StateChangeListener<MessageInstance<QueueConsumer>, State> listener) - { - - } - public void delete() { } - public int routeToAlternate(final Action<MessageInstance<? extends Consumer>> action, final ServerTransaction txn) + public boolean expired() throws AMQException { - return 0; + return false; } - public boolean expired() throws AMQException + @Override + public boolean acquire(final Consumer sub) { return false; } @@ -88,7 +87,7 @@ public class MockQueueEntry implements QueueEntry return false; } - public QueueConsumer getDeliveredConsumer() + public Consumer getDeliveredConsumer() { return null; } @@ -103,11 +102,6 @@ public class MockQueueEntry implements QueueEntry return _message; } - public AMQQueue<QueueConsumer> getQueue() - { - return null; - } - public long getSize() { return 0; @@ -118,32 +112,19 @@ public class MockQueueEntry implements QueueEntry return false; } - - public boolean isQueueDeleted() + public void reject() { - - return false; } - - public boolean isRejectedBy(QueueConsumer consumer) + @Override + public boolean isRejectedBy(final Consumer consumer) { - return false; } - public void reject() - { - - - } - - public void release() { - - } @Override @@ -153,26 +134,18 @@ public class MockQueueEntry implements QueueEntry } - public boolean removeStateChangeListener(StateChangeListener<MessageInstance<QueueConsumer>, State> listener) - { - - return false; - } - public void setRedelivered() { - - } public AMQMessageHeader getMessageHeader() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public boolean isPersistent() { - return false; //To change body of implemented methods use File | Settings | File Templates. + return false; } public boolean isRedelivered() @@ -180,12 +153,6 @@ public class MockQueueEntry implements QueueEntry return false; } - public int compareTo(QueueEntry o) - { - - return 0; - } - public void setMessage(ServerMessage msg) { _message = msg; @@ -195,31 +162,32 @@ public class MockQueueEntry implements QueueEntry { return false; } - - public QueueEntry getNextNode() + @Override + public int getDeliveryCount() { - return null; + return 0; } - public QueueEntry getNextValidEntry() + @Override + public void incrementDeliveryCount() { - return null; } @Override - public int getDeliveryCount() + public void decrementDeliveryCount() { - return 0; } @Override - public void incrementDeliveryCount() + public void addStateChangeListener(final StateChangeListener<? super MockMessageInstance, State> listener) { + } @Override - public void decrementDeliveryCount() + public boolean removeStateChangeListener(final StateChangeListener<? super MockMessageInstance, State> listener) { + return false; } @Override @@ -237,6 +205,6 @@ public class MockQueueEntry implements QueueEntry @Override public TransactionLogResource getOwningResource() { - return getQueue(); + return null; } } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java index e8c0470915..3db5d0fb62 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueListTest.java @@ -26,12 +26,16 @@ import static org.mockito.Mockito.when; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; +import java.util.Collections; +import java.util.UUID; + public class PriorityQueueListTest extends QpidTestCase { private static final byte[] PRIORITIES = {4, 5, 5, 4}; - PriorityQueueList _list = new PriorityQueueList(null, 10); + PriorityQueueList _list; private QueueEntry _priority4message1; private QueueEntry _priority4message2; @@ -42,6 +46,17 @@ public class PriorityQueueListTest extends QpidTestCase { QueueEntry[] entries = new QueueEntry[PRIORITIES.length]; + PriorityQueue queue = new PriorityQueue(UUID.randomUUID(), + getName(), + false, + null, + false, + false, + mock(VirtualHost.class), + Collections.<String,Object>emptyMap(), + 10); + _list = queue.getEntries(); + for (int i = 0; i < PRIORITIES.length; i++) { ServerMessage<?> message = mock(ServerMessage.class); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java index ced00dc578..56cd29b0bd 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java @@ -24,6 +24,8 @@ import java.util.Collections; import junit.framework.AssertionFailedError; import org.apache.qpid.AMQException; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageInstance; import org.apache.qpid.server.message.ServerMessage; @@ -34,9 +36,10 @@ import java.util.EnumSet; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.consumer.Consumer; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class AMQPriorityQueueTest extends SimpleAMQQueueTest +public class PriorityQueueTest extends SimpleAMQQueueTestBase { @Override diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java index 95139d8740..b67b2dda32 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java @@ -22,12 +22,18 @@ import junit.framework.TestCase; import org.apache.qpid.AMQException; import org.apache.qpid.server.consumer.ConsumerTarget; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.message.MessageInstance.EntryState; import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.virtualhost.VirtualHost; import java.lang.reflect.Field; +import java.util.Collections; +import java.util.UUID; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -57,6 +63,15 @@ public abstract class QueueEntryImplTestBase extends TestCase _queueEntry3 = getQueueEntryImpl(3); } + + protected void mockLogging() + { + final LogActor logActor = mock(LogActor.class); + when(logActor.getRootMessageLogger()).thenReturn(mock(RootMessageLogger.class)); + CurrentActor.setDefault(logActor); + } + + public void testAcquire() { assertTrue("Queue entry should be in AVAILABLE state before invoking of acquire method", @@ -185,7 +200,9 @@ public abstract class QueueEntryImplTestBase extends TestCase { int numberOfEntries = 5; QueueEntryImpl[] entries = new QueueEntryImpl[numberOfEntries]; - SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test")); + StandardQueue queue = new StandardQueue(UUID.randomUUID(), getName(), false, null, false, false, + mock(VirtualHost.class), Collections.<String,Object>emptyMap()); + OrderedQueueEntryList queueEntryList = queue.getEntries(); // create test entries for(int i = 0; i < numberOfEntries ; i++) diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java index a1bc9e50c7..3af268c189 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java @@ -25,6 +25,7 @@ import org.apache.qpid.AMQException; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.consumer.Consumer; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -32,20 +33,21 @@ import static org.mockito.Mockito.when; /** * Abstract test class for QueueEntryList implementations. */ -public abstract class QueueEntryListTestBase extends TestCase +public abstract class QueueEntryListTestBase<E extends QueueEntry<E,Q,C>, Q extends AMQQueue<E,Q,C>, L extends QueueEntryList<E,Q,L,C>, C extends Consumer> extends TestCase { - protected static final AMQQueue _testQueue = new MockAMQQueue("test"); - public abstract QueueEntryList<QueueEntry> getTestList(); - public abstract QueueEntryList<QueueEntry> getTestList(boolean newList); + public abstract L getTestList(); + public abstract L getTestList(boolean newList); public abstract long getExpectedFirstMsgId(); public abstract int getExpectedListLength(); public abstract ServerMessage getTestMessageToAdd() throws AMQException; public void testGetQueue() { - assertEquals("Unexpected head entry returned by getHead()", getTestList().getQueue(), _testQueue); + assertEquals("Unexpected head entry returned by getHead()", getTestList().getQueue(), getTestQueue()); } + protected abstract Q getTestQueue(); + /** * Test to add a message with properties specific to the queue type. * @see QueueEntryListTestBase#getTestList() @@ -54,10 +56,10 @@ public abstract class QueueEntryListTestBase extends TestCase */ public void testAddSpecificMessage() throws AMQException { - final QueueEntryList<QueueEntry> list = getTestList(); + final L list = getTestList(); list.add(getTestMessageToAdd()); - final QueueEntryIterator<?> iter = list.iterator(); + final QueueEntryIterator<E,Q,L,C> iter = list.iterator(); int count = 0; while(iter.advance()) { @@ -75,11 +77,11 @@ public abstract class QueueEntryListTestBase extends TestCase */ public void testAddGenericMessage() throws AMQException { - final QueueEntryList<QueueEntry> list = getTestList(); + final L list = getTestList(); final ServerMessage message = createServerMessage(666l); list.add(message); - final QueueEntryIterator<?> iter = list.iterator(); + final QueueEntryIterator<E,Q,L,C> iter = list.iterator(); int count = 0; while(iter.advance()) { @@ -109,8 +111,8 @@ public abstract class QueueEntryListTestBase extends TestCase */ public void testListNext() { - final QueueEntryList<QueueEntry> entryList = getTestList(); - QueueEntry entry = entryList.getHead(); + final L entryList = getTestList(); + E entry = entryList.getHead(); int count = 0; while(entryList.next(entry) != null) { @@ -127,7 +129,7 @@ public abstract class QueueEntryListTestBase extends TestCase */ public void testIterator() { - final QueueEntryIterator<?> iter = getTestList().iterator(); + final QueueEntryIterator<E,Q,L,C> iter = getTestList().iterator(); int count = 0; while(iter.advance()) { @@ -145,10 +147,10 @@ public abstract class QueueEntryListTestBase extends TestCase public void testDequeuedMessagedNotPresentInIterator() throws Exception { final int numberOfMessages = getExpectedListLength(); - final QueueEntryList<QueueEntry> entryList = getTestList(); + final L entryList = getTestList(); // dequeue all even messages - final QueueEntryIterator<?> it1 = entryList.iterator(); + final QueueEntryIterator<E,Q,L,C> it1 = entryList.iterator(); int counter = 0; while (it1.advance()) { @@ -161,7 +163,7 @@ public abstract class QueueEntryListTestBase extends TestCase } // iterate and check that dequeued messages are not returned by iterator - final QueueEntryIterator<?> it2 = entryList.iterator(); + final QueueEntryIterator<E,Q,L,C> it2 = entryList.iterator(); int counter2 = 0; while(it2.advance()) { @@ -180,7 +182,7 @@ public abstract class QueueEntryListTestBase extends TestCase */ public void testGetHead() { - final QueueEntry head = getTestList().getHead(); + final E head = getTestList().getHead(); assertNull("Head entry should not contain an actual message", head.getMessage()); assertEquals("Unexpected message id for first list entry", getExpectedFirstMsgId(), getTestList().next(head) .getMessage().getMessageNumber()); @@ -192,16 +194,16 @@ public abstract class QueueEntryListTestBase extends TestCase */ public void testEntryDeleted() { - final QueueEntry head = getTestList().getHead(); + final E head = getTestList().getHead(); - final QueueEntry first = getTestList().next(head); + final E first = getTestList().next(head); first.delete(); - final QueueEntry second = getTestList().next(head); + final E second = getTestList().next(head); assertNotSame("After deletion the next entry should be different", first.getMessage().getMessageNumber(), second .getMessage().getMessageNumber()); - final QueueEntry third = getTestList().next(first); + final E third = getTestList().next(first); assertEquals("After deletion the deleted nodes next node should be the same as the next from head", second .getMessage().getMessageNumber(), third.getMessage().getMessageNumber()); } @@ -215,11 +217,11 @@ public abstract class QueueEntryListTestBase extends TestCase */ public void testIteratorIgnoresDeletedFinalNode() throws Exception { - QueueEntryList<QueueEntry> list = getTestList(true); + L list = getTestList(true); int i = 0; - QueueEntry queueEntry1 = list.add(createServerMessage(i++)); - QueueEntry queueEntry2 = list.add(createServerMessage(i++)); + E queueEntry1 = list.add(createServerMessage(i++)); + E queueEntry2 = list.add(createServerMessage(i++)); assertSame(queueEntry2, list.next(queueEntry1)); assertNull(list.next(queueEntry2)); @@ -228,7 +230,7 @@ public abstract class QueueEntryListTestBase extends TestCase queueEntry2.delete(); assertTrue("Deleting node should have succeeded", queueEntry2.isDeleted()); - QueueEntryIterator<QueueEntry> iter = list.iterator(); + QueueEntryIterator<E,Q,L,C> iter = list.iterator(); //verify the iterator isn't 'atTail', can advance, and returns the 1st QueueEntry assertFalse("Iterator should not have been 'atTail'", iter.atTail()); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java index 674af36b77..87182dc8dc 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SelfValidatingSortedQueueEntryList.java @@ -22,7 +22,7 @@ package org.apache.qpid.server.queue; import junit.framework.Assert; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.SortedQueueEntryImpl.Colour; +import org.apache.qpid.server.queue.SortedQueueEntry.Colour; /** * Test extension of SortedQueueEntryList that provides data structure validation tests. @@ -30,22 +30,28 @@ import org.apache.qpid.server.queue.SortedQueueEntryImpl.Colour; */ public class SelfValidatingSortedQueueEntryList extends SortedQueueEntryList { - public SelfValidatingSortedQueueEntryList(AMQQueue queue, String propertyName) + public SelfValidatingSortedQueueEntryList(SortedQueue queue, String propertyName) { super(queue, propertyName); } + @Override + public SortedQueue getQueue() + { + return super.getQueue(); + } + @Override /** Overridden to automatically check queue properties before and after. */ - public SortedQueueEntryImpl add(final ServerMessage message) + public SortedQueueEntry add(final ServerMessage message) { assertQueueProperties(); //before add - final SortedQueueEntryImpl result = super.add(message); + final SortedQueueEntry result = super.add(message); assertQueueProperties(); //after add return result; } @Override /** Overridden to automatically check queue properties before and after. */ - public void entryDeleted(SortedQueueEntryImpl entry) + public void entryDeleted(SortedQueueEntry entry) { assertQueueProperties(); //before delete super.entryDeleted(entry); @@ -73,7 +79,7 @@ public class SelfValidatingSortedQueueEntryList extends SortedQueueEntryList assertTreeIntegrity(getRoot()); } - public void assertTreeIntegrity(final SortedQueueEntryImpl node) + public void assertTreeIntegrity(final SortedQueueEntry node) { if(node == null) { @@ -109,7 +115,7 @@ public class SelfValidatingSortedQueueEntryList extends SortedQueueEntryList assertLeavesSameBlackPath(getRoot()); } - public int assertLeavesSameBlackPath(final SortedQueueEntryImpl node) + public int assertLeavesSameBlackPath(final SortedQueueEntry node) { if(node == null) { @@ -133,7 +139,7 @@ public class SelfValidatingSortedQueueEntryList extends SortedQueueEntryList assertChildrenOfRedAreBlack(getRoot()); } - public void assertChildrenOfRedAreBlack(final SortedQueueEntryImpl node) + public void assertChildrenOfRedAreBlack(final SortedQueueEntry node) { if(node == null) { diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTestBase.java index 5abc97cee9..45001bda50 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTestBase.java @@ -45,7 +45,6 @@ import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.SimpleAMQQueue.QueueEntryFilter; -import org.apache.qpid.server.consumer.ConsumerTarget; import org.apache.qpid.server.consumer.MockConsumer; import org.apache.qpid.server.consumer.Consumer; import org.apache.qpid.server.util.Action; @@ -56,14 +55,13 @@ import org.apache.qpid.test.utils.QpidTestCase; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -public class SimpleAMQQueueTest extends QpidTestCase +abstract class SimpleAMQQueueTestBase<E extends QueueEntryImpl<E,Q,L>, Q extends SimpleAMQQueue<E,Q,L>, L extends SimpleQueueEntryList<E,Q,L>> extends QpidTestCase { - private static final Logger _logger = Logger.getLogger(SimpleAMQQueueTest.class); + private static final Logger _logger = Logger.getLogger(SimpleAMQQueueTestBase.class); - private SimpleAMQQueue _queue; + + private Q _queue; private VirtualHost _virtualHost; private String _qname = "qname"; private String _owner = "owner"; @@ -81,7 +79,7 @@ public class SimpleAMQQueueTest extends QpidTestCase _virtualHost = BrokerTestHelper.createVirtualHost(getClass().getName()); - _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner, + _queue = (Q) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner, false, false, false, _arguments); _exchange = (DirectExchange) _virtualHost.getExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME); @@ -107,7 +105,7 @@ public class SimpleAMQQueueTest extends QpidTestCase _queue.stop(); try { - _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), null, + _queue = (Q) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), null, false, _owner, false, false, false, _arguments); assertNull("Queue was created", _queue); @@ -118,24 +116,14 @@ public class SimpleAMQQueueTest extends QpidTestCase e.getMessage().contains("name")); } - try - { - _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner, false,false, null, Collections.EMPTY_MAP); - assertNull("Queue was created", _queue); - } - catch (IllegalArgumentException e) - { - assertTrue("Exception was not about missing vhost", - e.getMessage().contains("Host")); - } - - _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), + _queue = (Q) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), "differentName", false, _owner, false, false, false, _arguments); assertNotNull("Queue was not created", _queue); } + public void testGetVirtualHost() { assertEquals("Virtual host was wrong", _virtualHost, _queue.getVirtualHost()); @@ -150,11 +138,11 @@ public class SimpleAMQQueueTest extends QpidTestCase assertTrue("Queue was not bound to key", _exchange.isBound(_routingKey,_queue)); assertEquals("Exchange binding count", 1, - _queue.getBindings().size()); + _queue.getBindings().size()); assertEquals("Wrong exchange bound", _routingKey, _queue.getBindings().get(0).getBindingKey()); assertEquals("Wrong exchange bound", _exchange, - _queue.getBindings().get(0).getExchange()); + _queue.getBindings().get(0).getExchange()); _exchange.removeBinding(_routingKey, _queue, Collections.EMPTY_MAP); assertFalse("Routing key was still bound", @@ -495,22 +483,6 @@ public class SimpleAMQQueueTest extends QpidTestCase assertNotNull(ex); } - public void testAutoDeleteQueue() throws Exception - { - _queue.stop(); - _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP); - _queue.setDeleteOnNoConsumers(true); - - ServerMessage message = createMessage(new Long(25)); - _consumer = _queue.addConsumer(_consumerTarget, null, message.getClass(), "test", - EnumSet.of(Consumer.Option.ACQUIRES, - Consumer.Option.SEES_REQUEUES)); - - _queue.enqueue(message, null); - _consumer.close(); - assertTrue("Queue was not deleted when consumer was removed", - _queue.isDeleted()); - } public void testResend() throws Exception { @@ -520,12 +492,12 @@ public class SimpleAMQQueueTest extends QpidTestCase _consumer = _queue.addConsumer(_consumerTarget, null, message.getClass(), "test", EnumSet.of(Consumer.Option.ACQUIRES, Consumer.Option.SEES_REQUEUES)); - _queue.enqueue(message, new Action<MessageInstance<? extends Consumer>>() + _queue.enqueue(message, new Action<MessageInstance<?,? extends Consumer>>() { @Override - public void performAction(final MessageInstance<? extends Consumer> object) + public void performAction(final MessageInstance<?,? extends Consumer> object) { - QueueEntry entry = (QueueEntry) object; + QueueEntryImpl entry = (QueueEntryImpl) object; entry.setRedelivered(); try { @@ -612,7 +584,7 @@ public class SimpleAMQQueueTest extends QpidTestCase // Get non-existent 0th QueueEntry & check returned list was empty // (the position parameters in this method are indexed from 1) - List<QueueEntry> entries = _queue.getMessagesRangeOnTheQueue(0, 0); + List<E> entries = _queue.getMessagesRangeOnTheQueue(0, 0); assertTrue(entries.size() == 0); // Check that when 'from' is 0 it is ignored and the range continues from 1 @@ -681,22 +653,12 @@ public class SimpleAMQQueueTest extends QpidTestCase */ public void testProcessQueueWithUniqueSelectors() throws Exception { - TestSimpleQueueEntryListFactory factory = new TestSimpleQueueEntryListFactory(); - SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "testQueue", false,"testOwner", - false, false, _virtualHost, factory, null) - { - @Override - public void deliverAsync(QueueConsumer sub) - { - // do nothing, i.e prevent deliveries by the SubFlushRunner - // when registering the new consumers - } - }; + SimpleAMQQueue testQueue = createNonAsyncDeliverQueue(); // retrieve the QueueEntryList the queue creates and insert the test // messages, thus avoiding straight-through delivery attempts during //enqueue() process. - QueueEntryList list = factory.getQueueEntryList(); + QueueEntryList list = testQueue.getEntries(); assertNotNull("QueueEntryList should have been created", list); QueueEntry msg1 = list.add(createMessage(1L)); @@ -748,6 +710,12 @@ public class SimpleAMQQueueTest extends QpidTestCase verifyReceivedMessages(Collections.singletonList((MessageInstance)msg5), sub3.getMessages()); } + private SimpleAMQQueue createNonAsyncDeliverQueue() + { + TestSimpleQueueEntryListFactory factory = new TestSimpleQueueEntryListFactory(); + return new NonAsyncDeliverQueue(factory, getVirtualHost()); + } + /** * Tests that dequeued message is not present in the list returned form * {@link SimpleAMQQueue#getMessagesOnTheQueue()} @@ -764,7 +732,7 @@ public class SimpleAMQQueueTest extends QpidTestCase dequeueMessage(_queue, dequeueMessageIndex); // get messages on the queue - List<QueueEntry> entries = _queue.getMessagesOnTheQueue(); + List<E> entries = _queue.getMessagesOnTheQueue(); // assert queue entries assertEquals(messageNumber - 1, entries.size()); @@ -801,9 +769,9 @@ public class SimpleAMQQueueTest extends QpidTestCase dequeueMessage(_queue, dequeueMessageIndex); // get messages on the queue with filter accepting all available messages - List<QueueEntry> entries = _queue.getMessagesOnTheQueue(new QueueEntryFilter() + List<E> entries = _queue.getMessagesOnTheQueue(new QueueEntryFilter<E>() { - public boolean accept(QueueEntry entry) + public boolean accept(E entry) { return true; } @@ -855,12 +823,12 @@ public class SimpleAMQQueueTest extends QpidTestCase _queue.deleteMessageFromTop(); //get queue entries - List<QueueEntry> entries = _queue.getMessagesOnTheQueue(); + List<E> entries = _queue.getMessagesOnTheQueue(); // assert queue entries assertNotNull("Null is returned from getMessagesOnTheQueue", entries); assertEquals("Expected " + (messageNumber - 2) + " number of messages but recieved " + entries.size(), - messageNumber - 2, entries.size()); + messageNumber - 2, entries.size()); assertEquals("Expected first entry with id 2", 2l, (entries.get(0).getMessage()).getMessageNumber()); } @@ -891,241 +859,13 @@ public class SimpleAMQQueueTest extends QpidTestCase } // get queue entries - List<QueueEntry> entries = _queue.getMessagesOnTheQueue(); + List<E> entries = _queue.getMessagesOnTheQueue(); // assert queue entries assertNotNull(entries); assertEquals(0, entries.size()); } - /** - * Tests whether dequeued entry is sent to subscriber in result of - * invocation of {@link SimpleAMQQueue#processQueue(QueueRunner)} - */ - public void testProcessQueueWithDequeuedEntry() - { - // total number of messages to send - int messageNumber = 4; - int dequeueMessageIndex = 1; - - // create queue with overridden method deliverAsync - SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "test", - false, "testOwner", false, false, _virtualHost, null) - { - @Override - public void deliverAsync(QueueConsumer sub) - { - // do nothing - } - }; - - // put messages - List<QueueEntry> entries = enqueueGivenNumberOfMessages(testQueue, messageNumber); - - // dequeue message - dequeueMessage(testQueue, dequeueMessageIndex); - - // latch to wait for message receipt - final CountDownLatch latch = new CountDownLatch(messageNumber -1); - - // create a consumer - MockConsumer consumer = new MockConsumer() - { - /** - * Send a message and decrement latch - * @param entry - * @param batch - */ - public void send(MessageInstance entry, boolean batch) throws AMQException - { - super.send(entry, batch); - latch.countDown(); - } - }; - - try - { - // subscribe - testQueue.addConsumer(consumer, - null, - entries.get(0).getMessage().getClass(), - "test", - EnumSet.of(Consumer.Option.ACQUIRES, - Consumer.Option.SEES_REQUEUES)); - - // process queue - testQueue.processQueue(new QueueRunner(testQueue) - { - public void run() - { - // do nothing - } - }); - } - catch (AMQException e) - { - fail("Failure to process queue:" + e.getMessage()); - } - // wait up to 1 minute for message receipt - try - { - latch.await(1, TimeUnit.MINUTES); - } - catch (InterruptedException e1) - { - Thread.currentThread().interrupt(); - } - List<MessageInstance> expected = Arrays.asList((MessageInstance)entries.get(0), entries.get(2), entries.get(3)); - verifyReceivedMessages(expected, consumer.getMessages()); - } - - /** - * Tests that entry in dequeued state are not enqueued and not delivered to consumer - */ - public void testEnqueueDequeuedEntry() - { - // create a queue where each even entry is considered a dequeued - SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "test", false, - "testOwner", false, false, _virtualHost, new QueueEntryListFactory() - { - public QueueEntryList createQueueEntryList(AMQQueue queue) - { - /** - * Override SimpleQueueEntryList to create a dequeued - * entries for messages with even id - */ - return new SimpleQueueEntryList(queue) - { - /** - * Entries with even message id are considered - * dequeued! - */ - protected SimpleQueueEntryImpl createQueueEntry(final ServerMessage message) - { - return new SimpleQueueEntryImpl(this, message) - { - - public boolean isDeleted() - { - return (message.getMessageNumber() % 2 == 0); - } - - public boolean isAvailable() - { - return !(message.getMessageNumber() % 2 == 0); - } - - @Override - public boolean acquire(QueueConsumer sub) - { - if(message.getMessageNumber() % 2 == 0) - { - return false; - } - else - { - return super.acquire(sub); - } - } - }; - } - }; - } - }, null); - // create a consumer - MockConsumer consumer = new MockConsumer(); - - // register consumer - try - { - queue.addConsumer(consumer, - null, - createMessage(-1l).getClass(), - "test", - EnumSet.of(Consumer.Option.ACQUIRES, - Consumer.Option.SEES_REQUEUES)); - } - catch (AMQException e) - { - fail("Failure to register consumer:" + e.getMessage()); - } - - // put test messages into a queue - putGivenNumberOfMessages(queue, 4); - - // assert received messages - List<MessageInstance> messages = consumer.getMessages(); - assertEquals("Only 2 messages should be returned", 2, messages.size()); - assertEquals("ID of first message should be 1", 1l, - (messages.get(0).getMessage()).getMessageNumber()); - assertEquals("ID of second message should be 3", 3l, - (messages.get(1).getMessage()).getMessageNumber()); - } - - public void testActiveConsumerCount() throws Exception - { - final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "testActiveConsumerCount", false, - "testOwner", false, false, _virtualHost, new SimpleQueueEntryList.Factory(), null); - - //verify adding an active consumer increases the count - final MockConsumer consumer1 = new MockConsumer(); - consumer1.setActive(true); - consumer1.setState(ConsumerTarget.State.ACTIVE); - assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount()); - queue.addConsumer(consumer1, - null, - createMessage(-1l).getClass(), - "test", - EnumSet.of(Consumer.Option.ACQUIRES, - Consumer.Option.SEES_REQUEUES)); - assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); - - //verify adding an inactive consumer doesn't increase the count - final MockConsumer consumer2 = new MockConsumer(); - consumer2.setActive(false); - consumer2.setState(ConsumerTarget.State.SUSPENDED); - assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); - queue.addConsumer(consumer2, - null, - createMessage(-1l).getClass(), - "test", - EnumSet.of(Consumer.Option.ACQUIRES, - Consumer.Option.SEES_REQUEUES)); - assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); - - //verify behaviour in face of expected state changes: - - //verify a consumer going suspended->active increases the count - consumer2.setState(ConsumerTarget.State.ACTIVE); - assertEquals("Unexpected active consumer count", 2, queue.getActiveConsumerCount()); - - //verify a consumer going active->suspended decreases the count - consumer2.setState(ConsumerTarget.State.SUSPENDED); - assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); - - //verify a consumer going suspended->closed doesn't change the count - consumer2.setState(ConsumerTarget.State.CLOSED); - assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); - - //verify a consumer going active->active doesn't change the count - consumer1.setState(ConsumerTarget.State.ACTIVE); - assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); - - consumer1.setState(ConsumerTarget.State.SUSPENDED); - assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount()); - - //verify a consumer going suspended->suspended doesn't change the count - consumer1.setState(ConsumerTarget.State.SUSPENDED); - assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount()); - - consumer1.setState(ConsumerTarget.State.ACTIVE); - assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); - - //verify a consumer going active->closed decreases the count - consumer1.setState(ConsumerTarget.State.CLOSED); - assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount()); - - } public void testNotificationFiredOnEnqueue() throws Exception { @@ -1170,12 +910,12 @@ public class SimpleAMQQueueTest extends QpidTestCase * @param messageNumber * number of messages to put into queue */ - private List<QueueEntry> enqueueGivenNumberOfMessages(AMQQueue queue, int messageNumber) + protected List<E> enqueueGivenNumberOfMessages(Q queue, int messageNumber) { putGivenNumberOfMessages(queue, messageNumber); // make sure that all enqueued messages are on the queue - List<QueueEntry> entries = queue.getMessagesOnTheQueue(); + List<E> entries = queue.getMessagesOnTheQueue(); assertEquals(messageNumber, entries.size()); for (int i = 0; i < messageNumber; i++) { @@ -1196,16 +936,15 @@ public class SimpleAMQQueueTest extends QpidTestCase * @param queue * @param messageNumber */ - private void putGivenNumberOfMessages(AMQQueue queue, int messageNumber) + protected <T extends SimpleAMQQueue> void putGivenNumberOfMessages(T queue, int messageNumber) { for (int i = 0; i < messageNumber; i++) { // Create message - Long messageId = new Long(i); ServerMessage message = null; try { - message = createMessage(messageId); + message = createMessage((long)i); } catch (AMQException e) { @@ -1239,7 +978,7 @@ public class SimpleAMQQueueTest extends QpidTestCase * @param dequeueMessageIndex * entry index to dequeue. */ - private QueueEntry dequeueMessage(AMQQueue queue, int dequeueMessageIndex) + protected QueueEntry dequeueMessage(AMQQueue queue, int dequeueMessageIndex) { List<QueueEntry> entries = queue.getMessagesOnTheQueue(); QueueEntry entry = entries.get(dequeueMessageIndex); @@ -1259,7 +998,7 @@ public class SimpleAMQQueueTest extends QpidTestCase return entriesList; } - private void verifyReceivedMessages(List<MessageInstance> expected, + protected void verifyReceivedMessages(List<MessageInstance> expected, List<MessageInstance> delivered) { assertEquals("Consumer did not receive the expected number of messages", @@ -1272,11 +1011,16 @@ public class SimpleAMQQueueTest extends QpidTestCase } } - public SimpleAMQQueue getQueue() + public Q getQueue() { return _queue; } + protected void setQueue(Q queue) + { + _queue = queue; + } + public MockConsumer getConsumer() { return _consumerTarget; @@ -1310,7 +1054,7 @@ public class SimpleAMQQueueTest extends QpidTestCase return message; } - private static class EntryListAddingAction implements Action<MessageInstance<? extends Consumer>> + private static class EntryListAddingAction implements Action<MessageInstance<?,? extends Consumer>> { private final ArrayList<QueueEntry> _queueEntries; @@ -1319,25 +1063,122 @@ public class SimpleAMQQueueTest extends QpidTestCase _queueEntries = queueEntries; } - public void performAction(MessageInstance<? extends Consumer> entry) + public void performAction(MessageInstance<?,? extends Consumer> entry) { _queueEntries.add((QueueEntry) entry); } } - class TestSimpleQueueEntryListFactory implements QueueEntryListFactory + + public VirtualHost getVirtualHost() { - QueueEntryList _list; + return _virtualHost; + } + + public String getQname() + { + return _qname; + } + + public String getOwner() + { + return _owner; + } + + public String getRoutingKey() + { + return _routingKey; + } + + public DirectExchange getExchange() + { + return _exchange; + } + + public MockConsumer getConsumerTarget() + { + return _consumerTarget; + } + - public QueueEntryList createQueueEntryList(AMQQueue queue) + static class TestSimpleQueueEntryListFactory implements QueueEntryListFactory<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList> + { + + @Override + public NonAsyncDeliverList createQueueEntryList(final NonAsyncDeliverQueue queue) + { + return new NonAsyncDeliverList(queue); + } + } + + private static class NonAsyncDeliverEntry extends OrderedQueueEntry<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList> + { + + public NonAsyncDeliverEntry(final NonAsyncDeliverList queueEntryList) + { + super(queueEntryList); + } + + public NonAsyncDeliverEntry(final NonAsyncDeliverList queueEntryList, + final ServerMessage message, + final long entryId) + { + super(queueEntryList, message, entryId); + } + + public NonAsyncDeliverEntry(final NonAsyncDeliverList queueEntryList, final ServerMessage message) + { + super(queueEntryList, message); + } + } + + private static class NonAsyncDeliverList extends OrderedQueueEntryList<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList> + { + + private static final HeadCreator<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList> HEAD_CREATOR = + new HeadCreator<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList>() + { + + @Override + public NonAsyncDeliverEntry createHead(final NonAsyncDeliverList list) + { + return new NonAsyncDeliverEntry(list); + } + }; + + public NonAsyncDeliverList(final NonAsyncDeliverQueue queue) + { + super(queue, HEAD_CREATOR); + } + + @Override + protected NonAsyncDeliverEntry createQueueEntry(final ServerMessage<?> message) + { + return new NonAsyncDeliverEntry(this,message); + } + } + + + private static class NonAsyncDeliverQueue extends SimpleAMQQueue<NonAsyncDeliverEntry, NonAsyncDeliverQueue, NonAsyncDeliverList> + { + public NonAsyncDeliverQueue(final TestSimpleQueueEntryListFactory factory, VirtualHost vhost) { - _list = new SimpleQueueEntryList(queue); - return _list; + super(UUIDGenerator.generateRandomUUID(), + "testQueue", + false, + "testOwner", + false, + false, + vhost, + factory, + null); } - public QueueEntryList getQueueEntryList() + @Override + public void deliverAsync(QueueConsumer sub) { - return _list; + // do nothing, i.e prevent deliveries by the SubFlushRunner + // when registering the new consumers } } } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java index 11ff7ed192..36425761be 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java @@ -21,8 +21,14 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.UUID; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -30,7 +36,20 @@ import static org.mockito.Mockito.when; public class SimpleQueueEntryImplTest extends QueueEntryImplTestBase { - private SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test")); + private OrderedQueueEntryList queueEntryList; + + @Override + public void setUp() throws Exception + { + mockLogging(); + + StandardQueue queue = new StandardQueue(UUID.randomUUID(), "SimpleQueueEntryImplTest", false, null,false, false, mock(VirtualHost.class),null); + + queueEntryList = queue.getEntries(); + + super.setUp(); + } + public QueueEntryImpl getQueueEntryImpl(int msgId) throws AMQException { diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java index 7add2d4d43..b6b3843ad2 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java @@ -21,20 +21,26 @@ package org.apache.qpid.server.queue; import java.util.Collections; import org.apache.qpid.AMQException; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Arrays; +import java.util.UUID; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class SortedQueueEntryListTest extends QueueEntryListTestBase +public class SortedQueueEntryListTest extends QueueEntryListTestBase<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> { private static SelfValidatingSortedQueueEntryList _sqel; + public final static String keys[] = { " 73", " 18", " 11", "127", "166", "163", " 69", " 60", "191", "144", " 17", "161", "145", "140", "157", " 47", "136", " 56", "176", " 81", "195", " 96", " 2", " 68", "101", "141", "159", "187", "149", " 45", @@ -62,16 +68,30 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase private final static String keysSorted[] = keys.clone(); + private SortedQueue _testQueue; + @Override protected void setUp() throws Exception { + mockLogging(); + + // Create test list + _testQueue = new SortedQueue(UUID.randomUUID(), getName(), false, null, false,false, mock(VirtualHost.class), null, "KEY", new QueueEntryListFactory<SortedQueueEntry,SortedQueue,SortedQueueEntryList>() + { + + @Override + public SortedQueueEntryList createQueueEntryList(final SortedQueue queue) + { + return new SelfValidatingSortedQueueEntryList(queue, "KEY"); + } + }); + _sqel = (SelfValidatingSortedQueueEntryList) _testQueue.getEntries(); + super.setUp(); // Create result array Arrays.sort(keysSorted); - // Create test list - _sqel = new SelfValidatingSortedQueueEntryList(_testQueue, "KEY"); // Build test list long messageId = 0L; @@ -83,14 +103,22 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase } + protected void mockLogging() + { + final LogActor logActor = mock(LogActor.class); + when(logActor.getRootMessageLogger()).thenReturn(mock(RootMessageLogger.class)); + CurrentActor.setDefault(logActor); + } + + @Override - public QueueEntryList getTestList() + public SortedQueueEntryList getTestList() { return getTestList(false); } @Override - public QueueEntryList getTestList(boolean newList) + public SortedQueueEntryList getTestList(boolean newList) { if(newList) { @@ -117,6 +145,12 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase return generateTestMessage(1, "test value"); } + @Override + protected SortedQueue getTestQueue() + { + return _testQueue; + } + private ServerMessage generateTestMessage(final long id, final String keyValue) throws AMQException { final ServerMessage message = mock(ServerMessage.class); @@ -138,7 +172,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase super.testIterator(); // Test sorted order of list - final QueueEntryIterator<?> iter = getTestList().iterator(); + final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator(); int count = 0; while(iter.advance()) { @@ -147,12 +181,12 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase } } - private Object getSortedKeyValue(QueueEntryIterator<?> iter) + private Object getSortedKeyValue(QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter) { return (iter.getNode()).getMessage().getMessageHeader().getHeader("KEY"); } - private Long getMessageId(QueueEntryIterator<?> iter) + private Long getMessageId(QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter) { return (iter.getNode()).getMessage().getMessageNumber(); } @@ -169,7 +203,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase _sqel.add(msg); } - final QueueEntryIterator<?> iter = getTestList().iterator(); + final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator(); int count=0; while(iter.advance()) { @@ -190,12 +224,13 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase _sqel.add(msg); } - final QueueEntryIterator<?> iter = getTestList().iterator(); + final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator(); int count=0; while(iter.advance()) { assertNull("Sorted queue entry value is not as expected", getSortedKeyValue(iter)); - assertEquals("Message id not as expected", Long.valueOf(count++), getMessageId(iter)); } + assertEquals("Message id not as expected", Long.valueOf(count++), getMessageId(iter)); + } } public void testAscendingSortKeys() throws Exception @@ -211,7 +246,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase _sqel.add(msg); } - final QueueEntryIterator<?> iter = getTestList().iterator(); + final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator(); int count=0; while(iter.advance()) { @@ -234,7 +269,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase _sqel.add(msg); } - final QueueEntryIterator<?> iter = getTestList().iterator(); + final QueueEntryIterator<SortedQueueEntry, SortedQueue, SortedQueueEntryList, QueueConsumer<?,SortedQueueEntry, SortedQueue, SortedQueueEntryList>> iter = getTestList().iterator(); int count=0; while(iter.advance()) { @@ -251,7 +286,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase ServerMessage msg = generateTestMessage(1, "A"); _sqel.add(msg); - SortedQueueEntryImpl entry = _sqel.next(_sqel.getHead()); + SortedQueueEntry entry = _sqel.next(_sqel.getHead()); validateEntry(entry, "A", 1); msg = generateTestMessage(2, "B"); @@ -271,7 +306,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase ServerMessage msg = generateTestMessage(1, "B"); _sqel.add(msg); - SortedQueueEntryImpl entry = _sqel.next(_sqel.getHead()); + SortedQueueEntry entry = _sqel.next(_sqel.getHead()); validateEntry(entry, "B", 1); msg = generateTestMessage(2, "A"); @@ -290,7 +325,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase ServerMessage msg = generateTestMessage(1, "A"); _sqel.add(msg); - SortedQueueEntryImpl entry = _sqel.next(_sqel.getHead()); + SortedQueueEntry entry = _sqel.next(_sqel.getHead()); validateEntry(entry, "A", 1); msg = generateTestMessage(2, "C"); @@ -322,7 +357,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase ServerMessage msg = generateTestMessage(1, "B"); _sqel.add(msg); - SortedQueueEntryImpl entry = _sqel.next(_sqel.getHead()); + SortedQueueEntry entry = _sqel.next(_sqel.getHead()); validateEntry(entry, "B", 1); msg = generateTestMessage(2, "D"); @@ -362,7 +397,7 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase validateEntry(entry, "D", 2); } - private void validateEntry(final SortedQueueEntryImpl entry, final String expectedSortKey, final long expectedMessageId) + private void validateEntry(final SortedQueueEntry entry, final String expectedSortKey, final long expectedMessageId) { assertEquals("Sorted queue entry value is not as expected", expectedSortKey, entry.getMessage().getMessageHeader().getHeader("KEY")); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryTest.java index a84dd6c249..a406c1c26f 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryTest.java @@ -20,21 +20,41 @@ package org.apache.qpid.server.queue; import java.util.Collections; +import java.util.UUID; + import org.apache.qpid.AMQException; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class SortedQueueEntryImplTest extends QueueEntryImplTestBase +public class SortedQueueEntryTest extends QueueEntryImplTestBase { public final static String keys[] = { "CCC", "AAA", "BBB" }; - private SelfValidatingSortedQueueEntryList queueEntryList = new SelfValidatingSortedQueueEntryList(new MockAMQQueue("test"),"KEY"); + private SelfValidatingSortedQueueEntryList _queueEntryList; + + @Override + public void setUp() throws Exception + { + mockLogging(); + SortedQueue queue = new SortedQueue(UUID.randomUUID(), getName(), false, null, false,false, mock(VirtualHost.class), null, "KEY", new QueueEntryListFactory<SortedQueueEntry,SortedQueue,SortedQueueEntryList>() + { + + @Override + public SortedQueueEntryList createQueueEntryList(final SortedQueue queue) + { + return new SelfValidatingSortedQueueEntryList(queue, "KEY"); + } + }); + _queueEntryList = (SelfValidatingSortedQueueEntryList) queue.getEntries(); + super.setUp(); + } public QueueEntryImpl getQueueEntryImpl(int msgId) throws AMQException { @@ -48,7 +68,7 @@ public class SortedQueueEntryImplTest extends QueueEntryImplTestBase final MessageReference reference = mock(MessageReference.class); when(reference.getMessage()).thenReturn(message); when(message.newReference()).thenReturn(reference); - return queueEntryList.add(message); + return _queueEntryList.add(message); } public void testCompareTo() diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java index ae282d5f37..c053957e2a 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java @@ -23,16 +23,21 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.Collections; import java.util.Map; +import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class SimpleQueueEntryListTest extends QueueEntryListTestBase +public class StandardQueueEntryListTest extends QueueEntryListTestBase<StandardQueueEntry, StandardQueue, StandardQueueEntryList, QueueConsumer<?,StandardQueueEntry, StandardQueue, StandardQueueEntryList>> { - private SimpleQueueEntryList _sqel; + + private StandardQueue _testQueue; + private StandardQueueEntryList _sqel; private static final String SCAVENGE_PROP = "qpid.queue.scavenge_count"; private String oldScavengeValue = null; @@ -41,7 +46,10 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase protected void setUp() { oldScavengeValue = System.setProperty(SCAVENGE_PROP, "9"); - _sqel = new SimpleQueueEntryList(_testQueue); + _testQueue = new StandardQueue(UUID.randomUUID(),getName(),false,null,false,false,mock(VirtualHost.class), + Collections.<String,Object>emptyMap()); + + _sqel = _testQueue.getEntries(); for(int i = 1; i <= 100; i++) { final ServerMessage message = mock(ServerMessage.class); @@ -69,17 +77,21 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase } @Override - public QueueEntryList getTestList() + public StandardQueueEntryList getTestList() { return getTestList(false); } @Override - public QueueEntryList getTestList(boolean newList) + public StandardQueueEntryList getTestList(boolean newList) { if(newList) { - return new SimpleQueueEntryList(_testQueue); + StandardQueue queue = + new StandardQueue(UUID.randomUUID(), getName(), false, null, false, false, mock(VirtualHost.class), + Collections.<String, Object>emptyMap()); + + return queue.getEntries(); } else { @@ -107,9 +119,15 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase return msg; } + @Override + protected StandardQueue getTestQueue() + { + return _testQueue; + } + public void testScavenge() throws Exception { - SimpleQueueEntryList sqel = new SimpleQueueEntryList(null); + OrderedQueueEntryList sqel = new StandardQueueEntryList(null); ConcurrentHashMap<Integer,QueueEntry> entriesMap = new ConcurrentHashMap<Integer,QueueEntry>(); @@ -126,7 +144,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase entriesMap.put(i,bleh); } - SimpleQueueEntryImpl head = sqel.getHead(); + OrderedQueueEntry head = sqel.getHead(); //We shall now delete some specific messages mid-queue that will lead to //requiring a scavenge once the requested threshold of 9 deletes is passed @@ -172,10 +190,10 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase return entry.isDeleted() && !wasDeleted; } - private void verifyDeletedButPresentBeforeScavenge(SimpleQueueEntryImpl head, long messageId) + private void verifyDeletedButPresentBeforeScavenge(OrderedQueueEntry head, long messageId) { //Use the head to get the initial entry in the queue - SimpleQueueEntryImpl entry = head.getNextNode(); + OrderedQueueEntry entry = head.getNextNode(); for(long i = 1; i < messageId ; i++) { @@ -186,10 +204,10 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase assertTrue("Entry should have been deleted", entry.isDeleted()); } - private void verifyAllDeletedMessagedNotPresent(SimpleQueueEntryImpl head, Map<Integer,QueueEntry> remainingMessages) + private void verifyAllDeletedMessagedNotPresent(OrderedQueueEntry head, Map<Integer,QueueEntry> remainingMessages) { //Use the head to get the initial entry in the queue - SimpleQueueEntryImpl entry = head.getNextNode(); + OrderedQueueEntry entry = head.getNextNode(); assertNotNull("Initial entry should not have been null", entry); @@ -211,8 +229,8 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase public void testGettingNextElement() { final int numberOfEntries = 5; - final SimpleQueueEntryImpl[] entries = new SimpleQueueEntryImpl[numberOfEntries]; - final SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test")); + final OrderedQueueEntry[] entries = new OrderedQueueEntry[numberOfEntries]; + final OrderedQueueEntryList queueEntryList = getTestList(true); // create test entries for(int i = 0; i < numberOfEntries; i++) @@ -228,7 +246,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase // test getNext for not acquired entries for(int i = 0; i < numberOfEntries; i++) { - final SimpleQueueEntryImpl next = entries[i].getNextValidEntry(); + final OrderedQueueEntry next = entries[i].getNextValidEntry(); if(i < numberOfEntries - 1) { @@ -248,7 +266,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase entries[2].acquire(); entries[2].delete(); - SimpleQueueEntryImpl next = entries[2].getNextValidEntry(); + OrderedQueueEntry next = entries[2].getNextValidEntry(); assertEquals("expected forth entry", entries[3], next); next = next.getNextValidEntry(); assertEquals("expected fifth entry", entries[4], next); diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java new file mode 100644 index 0000000000..081b1d30ad --- /dev/null +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java @@ -0,0 +1,363 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.queue; + + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.consumer.Consumer; +import org.apache.qpid.server.consumer.ConsumerTarget; +import org.apache.qpid.server.consumer.MockConsumer; +import org.apache.qpid.server.message.MessageInstance; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +public class StandardQueueTest extends SimpleAMQQueueTestBase<StandardQueueEntry, StandardQueue, StandardQueueEntryList> +{ + + public void testCreationFailsWithNoVhost() + { + try + { + setQueue(new StandardQueue(UUIDGenerator.generateRandomUUID(), getQname(), false, getOwner(), false,false, null, getArguments())); + assertNull("Queue was created", getQueue()); + } + catch (IllegalArgumentException e) + { + assertTrue("Exception was not about missing vhost", + e.getMessage().contains("Host")); + } + } + + + public void testAutoDeleteQueue() throws Exception + { + getQueue().stop(); + setQueue(new StandardQueue(UUIDGenerator.generateRandomUUID(), getQname(), false, null, true, false, getVirtualHost(), Collections.<String,Object>emptyMap())); + getQueue().setDeleteOnNoConsumers(true); + + ServerMessage message = createMessage(25l); + QueueConsumer consumer = + getQueue().addConsumer(getConsumerTarget(), null, message.getClass(), "test", + EnumSet.of(Consumer.Option.ACQUIRES, + Consumer.Option.SEES_REQUEUES)); + + getQueue().enqueue(message, null); + consumer.close(); + assertTrue("Queue was not deleted when consumer was removed", + getQueue().isDeleted()); + } + + public void testActiveConsumerCount() throws Exception + { + final StandardQueue queue = new StandardQueue(UUIDGenerator.generateRandomUUID(), "testActiveConsumerCount", false, + "testOwner", false, false, getVirtualHost(), null); + + //verify adding an active consumer increases the count + final MockConsumer consumer1 = new MockConsumer(); + consumer1.setActive(true); + consumer1.setState(ConsumerTarget.State.ACTIVE); + assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount()); + queue.addConsumer(consumer1, + null, + createMessage(-1l).getClass(), + "test", + EnumSet.of(Consumer.Option.ACQUIRES, + Consumer.Option.SEES_REQUEUES)); + assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); + + //verify adding an inactive consumer doesn't increase the count + final MockConsumer consumer2 = new MockConsumer(); + consumer2.setActive(false); + consumer2.setState(ConsumerTarget.State.SUSPENDED); + assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); + queue.addConsumer(consumer2, + null, + createMessage(-1l).getClass(), + "test", + EnumSet.of(Consumer.Option.ACQUIRES, + Consumer.Option.SEES_REQUEUES)); + assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); + + //verify behaviour in face of expected state changes: + + //verify a consumer going suspended->active increases the count + consumer2.setState(ConsumerTarget.State.ACTIVE); + assertEquals("Unexpected active consumer count", 2, queue.getActiveConsumerCount()); + + //verify a consumer going active->suspended decreases the count + consumer2.setState(ConsumerTarget.State.SUSPENDED); + assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); + + //verify a consumer going suspended->closed doesn't change the count + consumer2.setState(ConsumerTarget.State.CLOSED); + assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); + + //verify a consumer going active->active doesn't change the count + consumer1.setState(ConsumerTarget.State.ACTIVE); + assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); + + consumer1.setState(ConsumerTarget.State.SUSPENDED); + assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount()); + + //verify a consumer going suspended->suspended doesn't change the count + consumer1.setState(ConsumerTarget.State.SUSPENDED); + assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount()); + + consumer1.setState(ConsumerTarget.State.ACTIVE); + assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); + + //verify a consumer going active->closed decreases the count + consumer1.setState(ConsumerTarget.State.CLOSED); + assertEquals("Unexpected active consumer count", 0, queue.getActiveConsumerCount()); + + } + + + /** + * Tests that entry in dequeued state are not enqueued and not delivered to consumer + */ + public void testEnqueueDequeuedEntry() + { + // create a queue where each even entry is considered a dequeued + SimpleAMQQueue queue = new DequeuedQueue(UUIDGenerator.generateRandomUUID(), "test", false, + "testOwner", false, false, getVirtualHost(), null); + // create a consumer + MockConsumer consumer = new MockConsumer(); + + // register consumer + try + { + queue.addConsumer(consumer, + null, + createMessage(-1l).getClass(), + "test", + EnumSet.of(Consumer.Option.ACQUIRES, + Consumer.Option.SEES_REQUEUES)); + } + catch (AMQException e) + { + fail("Failure to register consumer:" + e.getMessage()); + } + + // put test messages into a queue + putGivenNumberOfMessages(queue, 4); + + // assert received messages + List<MessageInstance> messages = consumer.getMessages(); + assertEquals("Only 2 messages should be returned", 2, messages.size()); + assertEquals("ID of first message should be 1", 1l, + (messages.get(0).getMessage()).getMessageNumber()); + assertEquals("ID of second message should be 3", 3l, + (messages.get(1).getMessage()).getMessageNumber()); + } + + /** + * Tests whether dequeued entry is sent to subscriber in result of + * invocation of {@link SimpleAMQQueue#processQueue(QueueRunner)} + */ + public void testProcessQueueWithDequeuedEntry() + { + // total number of messages to send + int messageNumber = 4; + int dequeueMessageIndex = 1; + + // create queue with overridden method deliverAsync + StandardQueue testQueue = new StandardQueue(UUIDGenerator.generateRandomUUID(), "test", + false, "testOwner", false, false, getVirtualHost(), null) + { + @Override + public void deliverAsync(QueueConsumer sub) + { + // do nothing + } + }; + + // put messages + List<StandardQueueEntry> entries = enqueueGivenNumberOfMessages(testQueue, messageNumber); + + // dequeue message + dequeueMessage(testQueue, dequeueMessageIndex); + + // latch to wait for message receipt + final CountDownLatch latch = new CountDownLatch(messageNumber -1); + + // create a consumer + MockConsumer consumer = new MockConsumer() + { + /** + * Send a message and decrement latch + * @param entry + * @param batch + */ + public void send(MessageInstance entry, boolean batch) throws AMQException + { + super.send(entry, batch); + latch.countDown(); + } + }; + + try + { + // subscribe + testQueue.addConsumer(consumer, + null, + entries.get(0).getMessage().getClass(), + "test", + EnumSet.of(Consumer.Option.ACQUIRES, + Consumer.Option.SEES_REQUEUES)); + + // process queue + testQueue.processQueue(new QueueRunner(testQueue) + { + public void run() + { + // do nothing + } + }); + } + catch (AMQException e) + { + fail("Failure to process queue:" + e.getMessage()); + } + // wait up to 1 minute for message receipt + try + { + latch.await(1, TimeUnit.MINUTES); + } + catch (InterruptedException e1) + { + Thread.currentThread().interrupt(); + } + List<MessageInstance> expected = Arrays.asList((MessageInstance) entries.get(0), entries.get(2), entries.get(3)); + verifyReceivedMessages(expected, consumer.getMessages()); + } + + + private static class DequeuedQueue extends SimpleAMQQueue<DequeuedQueueEntry, DequeuedQueue, DequeuedQueueEntryList> + { + + public DequeuedQueue(final UUID id, + final String queueName, + final boolean durable, + final String owner, + final boolean autoDelete, + final boolean exclusive, + final VirtualHost virtualHost, + final Map<String, Object> arguments) + { + super(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, new DequeuedQueueEntryListFactory(), arguments); + } + } + private static class DequeuedQueueEntryListFactory implements QueueEntryListFactory<DequeuedQueueEntry, DequeuedQueue, DequeuedQueueEntryList> + { + public DequeuedQueueEntryList createQueueEntryList(DequeuedQueue queue) + { + /** + * Override SimpleQueueEntryList to create a dequeued + * entries for messages with even id + */ + return new DequeuedQueueEntryList(queue); + } + + + } + + private static class DequeuedQueueEntryList extends OrderedQueueEntryList<DequeuedQueueEntry, DequeuedQueue, DequeuedQueueEntryList> + { + private static final HeadCreator<DequeuedQueueEntry,DequeuedQueue,DequeuedQueueEntryList> HEAD_CREATOR = + new HeadCreator<DequeuedQueueEntry,DequeuedQueue,DequeuedQueueEntryList>() + { + + @Override + public DequeuedQueueEntry createHead(final DequeuedQueueEntryList list) + { + return new DequeuedQueueEntry(list); + } + }; + + public DequeuedQueueEntryList(final DequeuedQueue queue) + { + super(queue, HEAD_CREATOR); + } + + /** + * Entries with even message id are considered + * dequeued! + */ + protected DequeuedQueueEntry createQueueEntry(final ServerMessage message) + { + return new DequeuedQueueEntry(this, message); + } + + + } + + private static class DequeuedQueueEntry extends OrderedQueueEntry<DequeuedQueueEntry,DequeuedQueue,DequeuedQueueEntryList> + { + + private final ServerMessage _message; + + private DequeuedQueueEntry(final DequeuedQueueEntryList queueEntryList) + { + super(queueEntryList); + _message = null; + } + + public DequeuedQueueEntry(DequeuedQueueEntryList list, final ServerMessage message) + { + super(list, message); + _message = message; + } + + public boolean isDeleted() + { + return (_message.getMessageNumber() % 2 == 0); + } + + public boolean isAvailable() + { + return !(_message.getMessageNumber() % 2 == 0); + } + + @Override + public boolean acquire(QueueConsumer sub) + { + if(_message.getMessageNumber() % 2 == 0) + { + return false; + } + else + { + return super.acquire(sub); + } + } + } +} diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java index 11b9bbe1b4..993e9ee4a8 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/AutoCommitTransactionTest.java @@ -24,9 +24,9 @@ import org.apache.qpid.server.message.MessageInstance; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; -import org.apache.qpid.server.queue.MockQueueEntry; -import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.queue.MockMessageInstance; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TransactionLogResource; import org.apache.qpid.server.txn.MockStoreTransaction.TransactionState; import org.apache.qpid.test.utils.QpidTestCase; @@ -385,7 +385,7 @@ public class AutoCommitTransactionTest extends QpidTestCase final AMQQueue queue = createTestAMQQueue(queueDurableFlags[i]); final ServerMessage message = createTestMessage(messagePersistentFlags[i]); - queueEntries.add(new MockQueueEntry() + queueEntries.add(new MockMessageInstance() { @Override @@ -395,7 +395,7 @@ public class AutoCommitTransactionTest extends QpidTestCase } @Override - public AMQQueue getQueue() + public TransactionLogResource getOwningResource() { return queue; } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java index 80e794e0ff..bdfdb55c7e 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/txn/LocalTransactionTest.java @@ -24,9 +24,9 @@ import org.apache.qpid.server.message.MessageInstance; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; -import org.apache.qpid.server.queue.MockQueueEntry; -import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.queue.MockMessageInstance; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TransactionLogResource; import org.apache.qpid.server.txn.MockStoreTransaction.TransactionState; import org.apache.qpid.test.utils.QpidTestCase; @@ -609,7 +609,7 @@ public class LocalTransactionTest extends QpidTestCase final AMQQueue queue = createTestAMQQueue(queueDurableFlags[i]); final ServerMessage message = createTestMessage(messagePersistentFlags[i]); - queueEntries.add(new MockQueueEntry() + queueEntries.add(new MockMessageInstance() { @Override @@ -619,7 +619,7 @@ public class LocalTransactionTest extends QpidTestCase } @Override - public AMQQueue getQueue() + public TransactionLogResource getOwningResource() { return queue; } diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java index cb1fc2737d..ed1ea01108 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -44,8 +44,8 @@ import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.logging.actors.TestLogActor; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.stats.StatisticsGatherer; @@ -179,9 +179,9 @@ public class BrokerTestHelper return factory.createExchange("amp.direct", "direct", false, false); } - public static SimpleAMQQueue createQueue(String queueName, VirtualHost virtualHost) throws AMQException + public static AMQQueue createQueue(String queueName, VirtualHost virtualHost) throws AMQException { - SimpleAMQQueue queue = (SimpleAMQQueue) virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), queueName, false, null, + AMQQueue queue = virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), queueName, false, null, false, false, false, Collections.<String, Object>emptyMap()); return queue; } diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java new file mode 100644 index 0000000000..37bbd810b4 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java @@ -0,0 +1,156 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_10; + +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageDeliveryPriority; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.typedmessage.TypedBytesContentReader; +import org.apache.qpid.typedmessage.TypedBytesFormatException; + +import java.io.EOFException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +public class MessageConverter_Internal_to_v0_10 implements MessageConverter<InternalMessage, MessageTransferMessage> +{ + @Override + public Class<InternalMessage> getInputClass() + { + return InternalMessage.class; + } + + @Override + public Class<MessageTransferMessage> getOutputClass() + { + return MessageTransferMessage.class; + } + + @Override + public MessageTransferMessage convert(InternalMessage serverMsg, VirtualHost vhost) + { + return new MessageTransferMessage(convertToStoredMessage(serverMsg), null); + } + + private StoredMessage<MessageMetaData_0_10> convertToStoredMessage(final InternalMessage serverMsg) + { + final byte[] messageContent = MessageConverter_v0_10.convertToBody(serverMsg.getMessageBody()); + final MessageMetaData_0_10 messageMetaData_0_10 = convertMetaData(serverMsg, + MessageConverter_v0_10.getBodyMimeType( + serverMsg.getMessageBody()), + messageContent.length); + + return new StoredMessage<MessageMetaData_0_10>() + { + @Override + public MessageMetaData_0_10 getMetaData() + { + return messageMetaData_0_10; + } + + @Override + public long getMessageNumber() + { + return serverMsg.getMessageNumber(); + } + + @Override + public void addContent(int offsetInMessage, ByteBuffer src) + { + throw new UnsupportedOperationException(); + } + + @Override + public int getContent(int offsetInMessage, ByteBuffer dst) + { + int size = messageContent.length - offsetInMessage; + if(dst.remaining() < size) + { + size = dst.remaining(); + } + ByteBuffer buf = ByteBuffer.wrap(messageContent, offsetInMessage, size); + dst.put(buf); + return size; + } + + @Override + public ByteBuffer getContent(int offsetInMessage, int size) + { + return ByteBuffer.wrap(messageContent, offsetInMessage, size); + } + + @Override + public StoreFuture flushToStore() + { + return StoreFuture.IMMEDIATE_FUTURE; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } + + private MessageMetaData_0_10 convertMetaData(ServerMessage serverMsg, final String bodyMimeType, final int size) + { + DeliveryProperties deliveryProps = new DeliveryProperties(); + MessageProperties messageProps = new MessageProperties(); + + + + deliveryProps.setExpiration(serverMsg.getExpiration()); + deliveryProps.setPriority(MessageDeliveryPriority.get(serverMsg.getMessageHeader().getPriority())); + deliveryProps.setRoutingKey(serverMsg.getRoutingKey()); + deliveryProps.setTimestamp(serverMsg.getMessageHeader().getTimestamp()); + + messageProps.setContentEncoding(serverMsg.getMessageHeader().getEncoding()); + messageProps.setContentLength(size); + messageProps.setContentType(bodyMimeType); + if(serverMsg.getMessageHeader().getCorrelationId() != null) + { + messageProps.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId().getBytes()); + } + + Header header = new Header(deliveryProps, messageProps, null); + return new MessageMetaData_0_10(header, size, serverMsg.getArrivalTime()); + } + + + @Override + public String getType() + { + return "Internal to v0-10"; + } +} diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java index 5244a7f51b..32ecc6bd0e 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java @@ -20,7 +20,14 @@ */ package org.apache.qpid.server.protocol.v0_10; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Map; + import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.plugin.MessageConverter; import org.apache.qpid.server.store.StoreFuture; @@ -30,9 +37,13 @@ import org.apache.qpid.transport.DeliveryProperties; import org.apache.qpid.transport.Header; import org.apache.qpid.transport.MessageDeliveryPriority; import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.codec.BBEncoder; public class MessageConverter_v0_10 implements MessageConverter<ServerMessage, MessageTransferMessage> { + + public static final Charset UTF_8 = Charset.forName("UTF-8"); + @Override public Class<ServerMessage> getInputClass() { @@ -129,6 +140,79 @@ public class MessageConverter_v0_10 implements MessageConverter<ServerMessage, M return new MessageMetaData_0_10(header, size, serverMsg.getArrivalTime()); } + + public static byte[] convertToBody(Object object) + { + if(object instanceof String) + { + return ((String)object).getBytes(UTF_8); + } + else if(object instanceof byte[]) + { + return (byte[]) object; + } + else if(object instanceof Map) + { + BBEncoder encoder = new BBEncoder(1024); + encoder.writeMap((Map)object); + ByteBuffer buf = encoder.segment(); + int remaining = buf.remaining(); + byte[] data = new byte[remaining]; + buf.get(data); + return data; + + } + else if(object instanceof List) + { + BBEncoder encoder = new BBEncoder(1024); + encoder.writeList((List) object); + ByteBuffer buf = encoder.segment(); + int remaining = buf.remaining(); + byte[] data = new byte[remaining]; + buf.get(data); + return data; + } + else + { + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + try + { + ObjectOutputStream os = new ObjectOutputStream(bytesOut); + os.writeObject(object); + return bytesOut.toByteArray(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + } + + public static String getBodyMimeType(Object object) + { + if(object instanceof String) + { + return "text/plain"; + } + else if(object instanceof byte[]) + { + return "application/octet-stream"; + } + else if(object instanceof Map) + { + return "amqp/map"; + } + else if(object instanceof List) + { + return "amqp/list"; + } + else + { + return "application/java-object-stream"; + } + } + + @Override public String getType() { diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10_to_Internal.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10_to_Internal.java new file mode 100644 index 0000000000..bc5f8899f2 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10_to_Internal.java @@ -0,0 +1,271 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_10; + +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.message.internal.InternalMessageMetaData; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageDeliveryPriority; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.ReplyTo; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.typedmessage.TypedBytesContentReader; +import org.apache.qpid.typedmessage.TypedBytesFormatException; + +import java.io.EOFException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Set; + +public class MessageConverter_v0_10_to_Internal implements MessageConverter<MessageTransferMessage, InternalMessage> +{ + @Override + public Class<MessageTransferMessage> getInputClass() + { + return MessageTransferMessage.class; + } + + @Override + public Class<InternalMessage> getOutputClass() + { + return InternalMessage.class; + } + + @Override + public InternalMessage convert(MessageTransferMessage serverMessage, VirtualHost vhost) + { + final String mimeType = serverMessage.getMessageHeader().getMimeType(); + byte[] data = new byte[(int) serverMessage.getSize()]; + serverMessage.getContent(ByteBuffer.wrap(data), 0); + + Object body = convertMessageBody(mimeType, data); + MessageProperties messageProps = serverMessage.getHeader().getMessageProperties(); + AMQMessageHeader fixedHeader = new DelegatingMessageHeader(serverMessage.getMessageHeader(), messageProps == null ? null : messageProps.getReplyTo()); + return InternalMessage.convert(serverMessage.getMessageNumber(), serverMessage.isPersistent(), fixedHeader, body); + } + + private static class DelegatingMessageHeader implements AMQMessageHeader + { + private final AMQMessageHeader _delegate; + private final ReplyTo _replyTo; + + + private DelegatingMessageHeader(final AMQMessageHeader delegate, final ReplyTo replyTo) + { + _delegate = delegate; + _replyTo = replyTo; + } + + @Override + public String getCorrelationId() + { + return _delegate.getCorrelationId(); + } + + @Override + public long getExpiration() + { + return _delegate.getExpiration(); + } + + @Override + public String getUserId() + { + return _delegate.getUserId(); + } + + @Override + public String getAppId() + { + return _delegate.getAppId(); + } + + @Override + public String getMessageId() + { + return _delegate.getMessageId(); + } + + @Override + public String getMimeType() + { + return _delegate.getMimeType(); + } + + @Override + public String getEncoding() + { + return _delegate.getEncoding(); + } + + @Override + public byte getPriority() + { + return _delegate.getPriority(); + } + + @Override + public long getTimestamp() + { + return _delegate.getTimestamp(); + } + + @Override + public String getType() + { + return _delegate.getType(); + } + + @Override + public String getReplyTo() + { + return _replyTo == null + ? null + : _replyTo.getExchange() == null || _replyTo.getExchange().equals("") + ? _replyTo.getRoutingKey() + : _replyTo.getRoutingKey() == null || _replyTo.getRoutingKey().equals("") + ? _replyTo.getExchange() + : _replyTo.getExchange() + "/" + _replyTo.getRoutingKey(); + } + + @Override + public Object getHeader(final String name) + { + return _delegate.getHeader(name); + } + + @Override + public boolean containsHeaders(final Set<String> names) + { + return _delegate.containsHeaders(names); + } + + @Override + public boolean containsHeader(final String name) + { + return _delegate.containsHeader(name); + } + + @Override + public Collection<String> getHeaderNames() + { + return _delegate.getHeaderNames(); + } + } + + private static Object convertMessageBody(String mimeType, byte[] data) + { + if("text/plain".equals(mimeType) || "text/xml".equals(mimeType)) + { + String text = new String(data); + return text; + } + else if("jms/map-message".equals(mimeType)) + { + TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); + + LinkedHashMap map = new LinkedHashMap(); + final int entries = reader.readIntImpl(); + for (int i = 0; i < entries; i++) + { + try + { + String propName = reader.readStringImpl(); + Object value = reader.readObject(); + + map.put(propName, value); + } + catch (EOFException e) + { + throw new IllegalArgumentException(e); + } + catch (TypedBytesFormatException e) + { + throw new IllegalArgumentException(e); + } + + } + + return map; + + } + else if("amqp/map".equals(mimeType)) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(data)); + final Map<String,Object> map = decoder.readMap(); + + return map; + + } + else if("amqp/list".equals(mimeType)) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(data)); + return decoder.readList(); + } + else if("jms/stream-message".equals(mimeType)) + { + TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); + + List list = new ArrayList(); + while (reader.remaining() != 0) + { + try + { + list.add(reader.readObject()); + } + catch (TypedBytesFormatException e) + { + throw new RuntimeException(e); // TODO - Implement + } + catch (EOFException e) + { + throw new RuntimeException(e); // TODO - Implement + } + } + return list; + } + else + { + return data; + + } + } + + @Override + public String getType() + { + return "v0-10 to Internal"; + } +} diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java index 53022c333e..87a02b99c1 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java @@ -928,10 +928,10 @@ public class ServerSession extends Session return getId().compareTo(o.getId()); } - private class CheckCapacityAction<C extends Consumer> implements Action<MessageInstance<C>> + private class CheckCapacityAction<C extends Consumer> implements Action<MessageInstance<?,C>> { @Override - public void performAction(final MessageInstance<C> entry) + public void performAction(final MessageInstance<?,C> entry) { TransactionLogResource queue = entry.getOwningResource(); if(queue instanceof CapacityChecker) diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter index 995b0fabdc..dd115905a4 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter @@ -17,3 +17,5 @@ # under the License. # org.apache.qpid.server.protocol.v0_10.MessageConverter_v0_10 +org.apache.qpid.server.protocol.v0_10.MessageConverter_Internal_to_v0_10 +org.apache.qpid.server.protocol.v0_10.MessageConverter_v0_10_to_Internal diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java index 7e712c8e17..8becdf853b 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java @@ -1202,14 +1202,14 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F } - private class ImmediateAction<C extends Consumer> implements Action<MessageInstance<C>> + private class ImmediateAction<C extends Consumer> implements Action<MessageInstance<?,C>> { public ImmediateAction() { } - public void performAction(MessageInstance<C> entry) + public void performAction(MessageInstance<?,C> entry) { TransactionLogResource queue = entry.getOwningResource(); @@ -1274,10 +1274,10 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F } } - private final class CapacityCheckAction<C extends Consumer> implements Action<MessageInstance<C>> + private final class CapacityCheckAction<C extends Consumer> implements Action<MessageInstance<?,C>> { @Override - public void performAction(final MessageInstance<C> entry) + public void performAction(final MessageInstance<?,C> entry) { TransactionLogResource queue = entry.getOwningResource(); if(queue instanceof CapacityChecker) diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java new file mode 100644 index 0000000000..b80ad3e7b8 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java @@ -0,0 +1,268 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.codec.BBEncoder; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class MessageConverter_Internal_to_v0_8 implements MessageConverter<InternalMessage, AMQMessage> +{ + private static final int BASIC_CLASS_ID = 60; + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + + public Class<InternalMessage> getInputClass() + { + return InternalMessage.class; + } + + @Override + public Class<AMQMessage> getOutputClass() + { + return AMQMessage.class; + } + + @Override + public AMQMessage convert(InternalMessage serverMsg, VirtualHost vhost) + { + return new AMQMessage(convertToStoredMessage(serverMsg), null); + } + + private StoredMessage<MessageMetaData> convertToStoredMessage(final InternalMessage serverMsg) + { + final byte[] messageContent = convertToBody(serverMsg.getMessageBody()); + final MessageMetaData messageMetaData_0_8 = convertMetaData(serverMsg, + getBodyMimeType(serverMsg.getMessageBody()), + messageContent.length); + + return new StoredMessage<MessageMetaData>() + { + @Override + public MessageMetaData getMetaData() + { + return messageMetaData_0_8; + } + + @Override + public long getMessageNumber() + { + return serverMsg.getMessageNumber(); + } + + @Override + public void addContent(int offsetInMessage, ByteBuffer src) + { + throw new UnsupportedOperationException(); + } + + @Override + public int getContent(int offsetInMessage, ByteBuffer dst) + { + int size = messageContent.length - offsetInMessage; + if(dst.remaining() < size) + { + size = dst.remaining(); + } + ByteBuffer buf = ByteBuffer.wrap(messageContent, offsetInMessage, size); + dst.put(buf); + return size; + } + + @Override + public ByteBuffer getContent(int offsetInMessage, int size) + { + return ByteBuffer.wrap(messageContent, offsetInMessage, size); + } + + @Override + public StoreFuture flushToStore() + { + return StoreFuture.IMMEDIATE_FUTURE; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } + + private MessageMetaData convertMetaData(InternalMessage serverMsg, final String bodyMimeType, final int size) + { + + MessagePublishInfo publishInfo = new MessagePublishInfo() + { + @Override + public AMQShortString getExchange() + { + return null; + } + + @Override + public void setExchange(final AMQShortString amqShortString) + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isImmediate() + { + return false; + } + + @Override + public boolean isMandatory() + { + return false; + } + + @Override + public AMQShortString getRoutingKey() + { + return null; + } + }; + + + final BasicContentHeaderProperties props = new BasicContentHeaderProperties(); + props.setAppId(serverMsg.getMessageHeader().getAppId()); + props.setContentType(bodyMimeType); + props.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId()); + props.setDeliveryMode(serverMsg.isPersistent() ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT); + props.setExpiration(serverMsg.getExpiration()); + props.setMessageId(serverMsg.getMessageHeader().getMessageId()); + props.setPriority(serverMsg.getMessageHeader().getPriority()); + props.setReplyTo(serverMsg.getMessageHeader().getReplyTo()); + props.setTimestamp(serverMsg.getMessageHeader().getTimestamp()); + props.setUserId(serverMsg.getMessageHeader().getUserId()); + + Map<String,Object> headerProps = new LinkedHashMap<String, Object>(); + + for(String headerName : serverMsg.getMessageHeader().getHeaderNames()) + { + headerProps.put(headerName, serverMsg.getMessageHeader().getHeader(headerName)); + } + + props.setHeaders(FieldTable.convertToFieldTable(headerProps)); + + final ContentHeaderBody chb = new ContentHeaderBody(props, BASIC_CLASS_ID); + return new MessageMetaData(publishInfo, chb, serverMsg.getArrivalTime()); + } + + + @Override + public String getType() + { + return "Internal to v0-8"; + } + + + public static byte[] convertToBody(Object object) + { + if(object instanceof String) + { + return ((String)object).getBytes(UTF_8); + } + else if(object instanceof byte[]) + { + return (byte[]) object; + } + else if(object instanceof Map) + { + BBEncoder encoder = new BBEncoder(1024); + encoder.writeMap((Map)object); + ByteBuffer buf = encoder.segment(); + int remaining = buf.remaining(); + byte[] data = new byte[remaining]; + buf.get(data); + return data; + + } + else if(object instanceof List) + { + BBEncoder encoder = new BBEncoder(1024); + encoder.writeList((List) object); + ByteBuffer buf = encoder.segment(); + int remaining = buf.remaining(); + byte[] data = new byte[remaining]; + buf.get(data); + return data; + } + else + { + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + try + { + ObjectOutputStream os = new ObjectOutputStream(bytesOut); + os.writeObject(object); + return bytesOut.toByteArray(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + } + + public static String getBodyMimeType(Object object) + { + if(object instanceof String) + { + return "text/plain"; + } + else if(object instanceof byte[]) + { + return "application/octet-stream"; + } + else if(object instanceof Map) + { + return "amqp/map"; + } + else if(object instanceof List) + { + return "amqp/list"; + } + else + { + return "application/java-object-stream"; + } + } + +} diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_v0_8_to_Internal.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_v0_8_to_Internal.java new file mode 100644 index 0000000000..6076ff66c7 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_v0_8_to_Internal.java @@ -0,0 +1,148 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.typedmessage.TypedBytesContentReader; +import org.apache.qpid.typedmessage.TypedBytesFormatException; + +import java.io.EOFException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +public class MessageConverter_v0_8_to_Internal implements MessageConverter<AMQMessage, InternalMessage> +{ + @Override + public Class<AMQMessage> getInputClass() + { + return AMQMessage.class; + } + + @Override + public Class<InternalMessage> getOutputClass() + { + return InternalMessage.class; + } + + @Override + public InternalMessage convert(AMQMessage serverMessage, VirtualHost vhost) + { + final String mimeType = serverMessage.getMessageHeader().getMimeType(); + byte[] data = new byte[(int) serverMessage.getSize()]; + serverMessage.getContent(ByteBuffer.wrap(data), 0); + + Object body = convertMessageBody(mimeType, data); + + return InternalMessage.convert(serverMessage.getMessageNumber(), serverMessage.isPersistent(), serverMessage.getMessageHeader(), body); + } + + private static Object convertMessageBody(String mimeType, byte[] data) + { + if("text/plain".equals(mimeType) || "text/xml".equals(mimeType)) + { + String text = new String(data); + return text; + } + else if("jms/map-message".equals(mimeType)) + { + TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); + + LinkedHashMap map = new LinkedHashMap(); + final int entries = reader.readIntImpl(); + for (int i = 0; i < entries; i++) + { + try + { + String propName = reader.readStringImpl(); + Object value = reader.readObject(); + + map.put(propName, value); + } + catch (EOFException e) + { + throw new IllegalArgumentException(e); + } + catch (TypedBytesFormatException e) + { + throw new IllegalArgumentException(e); + } + + } + + return map; + + } + else if("amqp/map".equals(mimeType)) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(data)); + final Map<String,Object> map = decoder.readMap(); + + return map; + + } + else if("amqp/list".equals(mimeType)) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(data)); + return decoder.readList(); + } + else if("jms/stream-message".equals(mimeType)) + { + TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); + + List list = new ArrayList(); + while (reader.remaining() != 0) + { + try + { + list.add(reader.readObject()); + } + catch (TypedBytesFormatException e) + { + throw new RuntimeException(e); // TODO - Implement + } + catch (EOFException e) + { + throw new RuntimeException(e); // TODO - Implement + } + } + return list; + } + else + { + return data; + + } + } + + @Override + public String getType() + { + return "v0-8 to Internal"; + } +} diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter new file mode 100644 index 0000000000..d87bc2566f --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.protocol.v0_8.MessageConverter_Internal_to_v0_8 +org.apache.qpid.server.protocol.v0_8.MessageConverter_v0_8_to_Internal
\ No newline at end of file diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java index dded0c70fe..f47525097e 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java @@ -24,7 +24,7 @@ package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.queue.SimpleAMQQueue; +import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.util.BrokerTestHelper; @@ -36,7 +36,7 @@ import java.util.List; public class AcknowledgeTest extends QpidTestCase { private AMQChannel _channel; - private SimpleAMQQueue _queue; + private AMQQueue _queue; private MessageStore _messageStore; private String _queueName; @@ -79,7 +79,7 @@ public class AcknowledgeTest extends QpidTestCase return (InternalTestProtocolSession)_channel.getProtocolSession(); } - private SimpleAMQQueue getQueue() + private AMQQueue getQueue() { return _queue; } diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java index f6376e56c4..dc687e1075 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java @@ -26,10 +26,8 @@ import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.consumer.Consumer; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; @@ -39,7 +37,7 @@ import java.util.List; public class QueueBrowserUsesNoAckTest extends QpidTestCase { private AMQChannel _channel; - private SimpleAMQQueue _queue; + private AMQQueue _queue; private MessageStore _messageStore; private String _queueName; @@ -82,7 +80,7 @@ public class QueueBrowserUsesNoAckTest extends QpidTestCase return (InternalTestProtocolSession)_channel.getProtocolSession(); } - private SimpleAMQQueue getQueue() + private AMQQueue getQueue() { return _queue; } diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java new file mode 100644 index 0000000000..f02908391a --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java @@ -0,0 +1,140 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v1_0; + +import org.apache.qpid.amqp_1_0.messaging.SectionEncoder; +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.UnsignedByte; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; +import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; +import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties; +import org.apache.qpid.amqp_1_0.type.messaging.Data; +import org.apache.qpid.amqp_1_0.type.messaging.Header; +import org.apache.qpid.amqp_1_0.type.messaging.Properties; +import org.apache.qpid.server.message.internal.InternalMessage; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + +public class MessageConverter_Internal_to_v1_0 extends MessageConverter_to_1_0<InternalMessage> +{ + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + + public Class<InternalMessage> getInputClass() + { + return InternalMessage.class; + } + + + @Override + protected MessageMetaData_1_0 convertMetaData(final InternalMessage serverMessage, + final SectionEncoder sectionEncoder) + { + List<Section> sections = new ArrayList<Section>(3); + Header header = new Header(); + + header.setDurable(serverMessage.isPersistent()); + header.setPriority(UnsignedByte.valueOf(serverMessage.getMessageHeader().getPriority())); + if(serverMessage.getExpiration() != 0l && serverMessage.getArrivalTime() !=0l && serverMessage.getExpiration() >= serverMessage.getArrivalTime()) + { + header.setTtl(UnsignedInteger.valueOf(serverMessage.getExpiration()-serverMessage.getArrivalTime())); + } + + sections.add(header); + + Properties properties = new Properties(); + properties.setCorrelationId(serverMessage.getMessageHeader().getCorrelationId()); + properties.setCreationTime(new Date(serverMessage.getMessageHeader().getTimestamp())); + properties.setMessageId(serverMessage.getMessageHeader().getMessageId()); + final String userId = serverMessage.getMessageHeader().getUserId(); + if(userId != null) + { + properties.setUserId(new Binary(userId.getBytes(UTF_8))); + } + properties.setReplyTo(serverMessage.getMessageHeader().getReplyTo()); + + sections.add(properties); + + if(!serverMessage.getMessageHeader().getHeaderNames().isEmpty()) + { + ApplicationProperties applicationProperties = new ApplicationProperties(serverMessage.getMessageHeader().getHeaderMap() ); + sections.add(applicationProperties); + } + return new MessageMetaData_1_0(sections, sectionEncoder); + + } + + protected Section getBodySection(final InternalMessage serverMessage, final String mimeType) + { + return convertToBody(serverMessage.getMessageBody()); + } + + + @Override + public String getType() + { + return "Internal to v1-0"; + } + + + public Section convertToBody(Object object) + { + if(object instanceof String) + { + return new AmqpValue(object); + } + else if(object instanceof byte[]) + { + return new Data(new Binary((byte[])object)); + } + else if(object instanceof Map) + { + return new AmqpValue(MessageConverter_to_1_0.fixMapValues((Map)object)); + } + else if(object instanceof List) + { + return new AmqpValue(MessageConverter_to_1_0.fixListValues((List)object)); + } + else + { + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + try + { + ObjectOutputStream os = new ObjectOutputStream(bytesOut); + os.writeObject(object); + return new Data(new Binary(bytesOut.toByteArray())); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + } + +} diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java index a96d951de6..a8a203b247 100644 --- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java @@ -156,7 +156,7 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement } } - private static Map fixMapValues(final Map<String, Object> map) + static Map fixMapValues(final Map<String, Object> map) { for(Map.Entry<String,Object> entry : map.entrySet()) { @@ -165,7 +165,7 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement return map; } - private static Object fixValue(final Object value) + static Object fixValue(final Object value) { if(value instanceof byte[]) { @@ -185,7 +185,7 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement } } - private static List fixListValues(final List list) + static List fixListValues(final List list) { ListIterator iterator = list.listIterator(); while(iterator.hasNext()) @@ -198,83 +198,88 @@ public abstract class MessageConverter_to_1_0<M extends ServerMessage> implement } private StoredMessage<MessageMetaData_1_0> convertServerMessage(final MessageMetaData_1_0 metaData, - final ServerMessage serverMessage, + final M serverMessage, SectionEncoder sectionEncoder) { - final String mimeType = serverMessage.getMessageHeader().getMimeType(); - byte[] data = new byte[(int) serverMessage.getSize()]; - serverMessage.getContent(ByteBuffer.wrap(data), 0); + final String mimeType = serverMessage.getMessageHeader().getMimeType(); + Section bodySection = getBodySection(serverMessage, mimeType); - Section bodySection = convertMessageBody(mimeType, data); + final ByteBuffer allData = encodeConvertedMessage(metaData, bodySection, sectionEncoder); - final ByteBuffer allData = encodeConvertedMessage(metaData, bodySection, sectionEncoder); - - return new StoredMessage<MessageMetaData_1_0>() - { - @Override - public MessageMetaData_1_0 getMetaData() - { - return metaData; - } - - @Override - public long getMessageNumber() - { - return serverMessage.getMessageNumber(); - } - - @Override - public void addContent(int offsetInMessage, ByteBuffer src) - { - throw new UnsupportedOperationException(); - } - - @Override - public int getContent(int offsetInMessage, ByteBuffer dst) - { - ByteBuffer buf = allData.duplicate(); - buf.position(offsetInMessage); - buf = buf.slice(); - int size; - if(dst.remaining()<buf.remaining()) - { - buf.limit(dst.remaining()); - size = dst.remaining(); - } - else + return new StoredMessage<MessageMetaData_1_0>() { - size = buf.remaining(); - } - dst.put(buf); - return size; - } - - @Override - public ByteBuffer getContent(int offsetInMessage, int size) - { - ByteBuffer buf = allData.duplicate(); - buf.position(offsetInMessage); - buf = buf.slice(); - if(size < buf.remaining()) - { - buf.limit(size); - } - return buf; - } + @Override + public MessageMetaData_1_0 getMetaData() + { + return metaData; + } + + @Override + public long getMessageNumber() + { + return serverMessage.getMessageNumber(); + } + + @Override + public void addContent(int offsetInMessage, ByteBuffer src) + { + throw new UnsupportedOperationException(); + } + + @Override + public int getContent(int offsetInMessage, ByteBuffer dst) + { + ByteBuffer buf = allData.duplicate(); + buf.position(offsetInMessage); + buf = buf.slice(); + int size; + if(dst.remaining()<buf.remaining()) + { + buf.limit(dst.remaining()); + size = dst.remaining(); + } + else + { + size = buf.remaining(); + } + dst.put(buf); + return size; + } + + @Override + public ByteBuffer getContent(int offsetInMessage, int size) + { + ByteBuffer buf = allData.duplicate(); + buf.position(offsetInMessage); + buf = buf.slice(); + if(size < buf.remaining()) + { + buf.limit(size); + } + return buf; + } + + @Override + public StoreFuture flushToStore() + { + throw new UnsupportedOperationException(); + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } - @Override - public StoreFuture flushToStore() - { - throw new UnsupportedOperationException(); - } + protected Section getBodySection(final M serverMessage, final String mimeType) + { + byte[] data = new byte[(int) serverMessage.getSize()]; + serverMessage.getContent(ByteBuffer.wrap(data), 0); - @Override - public void remove() - { - throw new UnsupportedOperationException(); - } - }; - } + return convertMessageBody(mimeType, data); + } private ByteBuffer encodeConvertedMessage(MessageMetaData_1_0 metaData, Section bodySection, SectionEncoder sectionEncoder) { diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java new file mode 100644 index 0000000000..f639f98dba --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_v1_0_to_Internal.java @@ -0,0 +1,281 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v1_0; + +import org.apache.qpid.amqp_1_0.messaging.SectionDecoderImpl; +import org.apache.qpid.amqp_1_0.type.AmqpErrorException; +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry; +import org.apache.qpid.amqp_1_0.type.messaging.AmqpSequence; +import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; +import org.apache.qpid.amqp_1_0.type.messaging.Data; +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.typedmessage.TypedBytesContentReader; +import org.apache.qpid.typedmessage.TypedBytesFormatException; + +import java.io.EOFException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +public class MessageConverter_v1_0_to_Internal implements MessageConverter<Message_1_0, InternalMessage> +{ + + static final AMQPDescribedTypeRegistry TYPE_REGISTRY = AMQPDescribedTypeRegistry.newInstance(); + static + { + TYPE_REGISTRY.registerTransportLayer(); + TYPE_REGISTRY.registerMessagingLayer(); + TYPE_REGISTRY.registerTransactionLayer(); + TYPE_REGISTRY.registerSecurityLayer(); + } + + @Override + public Class<Message_1_0> getInputClass() + { + return Message_1_0.class; + } + + @Override + public Class<InternalMessage> getOutputClass() + { + return InternalMessage.class; + } + + @Override + public InternalMessage convert(Message_1_0 serverMessage, VirtualHost vhost) + { + final String mimeType = serverMessage.getMessageHeader().getMimeType(); + + + + + byte[] data = new byte[(int) serverMessage.getSize()]; + serverMessage.getStoredMessage().getContent(0,ByteBuffer.wrap(data)); + + SectionDecoderImpl sectionDecoder = new SectionDecoderImpl(TYPE_REGISTRY); + + try + { + List<Section> sections = sectionDecoder.parseAll(ByteBuffer.wrap(data)); + ListIterator<Section> iterator = sections.listIterator(); + Section previousSection = null; + while(iterator.hasNext()) + { + Section section = iterator.next(); + if(!(section instanceof AmqpValue || section instanceof Data || section instanceof AmqpSequence)) + { + iterator.remove(); + } + else + { + if(previousSection != null && (previousSection.getClass() != section.getClass() || section instanceof AmqpValue)) + { + throw new RuntimeException("Message is badly formed and has multiple body section which are not all Data or not all AmqpSequence"); + } + else + { + previousSection = section; + } + } + } + + Object bodyObject; + + if(sections.isEmpty()) + { + // should actually be illegal + bodyObject = new byte[0]; + } + else + { + Section firstBodySection = sections.get(0); + if(firstBodySection instanceof AmqpValue) + { + bodyObject = fixObject(((AmqpValue)firstBodySection).getValue()); + } + else if(firstBodySection instanceof Data) + { + int totalSize = 0; + for(Section section : sections) + { + totalSize += ((Data)section).getValue().getLength(); + } + byte[] bodyData = new byte[totalSize]; + ByteBuffer buf = ByteBuffer.wrap(bodyData); + for(Section section : sections) + { + buf.put(((Data)section).getValue().asByteBuffer()); + } + bodyObject = bodyData; + } + else + { + ArrayList totalSequence = new ArrayList(); + for(Section section : sections) + { + totalSequence.addAll(((AmqpSequence)section).getValue()); + } + bodyObject = fixObject(totalSequence); + } + } + return InternalMessage.convert(serverMessage.getMessageNumber(), serverMessage.isPersistent(), serverMessage.getMessageHeader(), bodyObject); + + } + catch (AmqpErrorException e) + { + throw new RuntimeException(e); + } + + + + + } + + private Object fixObject(final Object value) + { + if(value instanceof Binary) + { + final Binary binaryValue = (Binary) value; + byte[] data = new byte[binaryValue.getLength()]; + binaryValue.asByteBuffer().get(data); + return data; + } + else if(value instanceof List) + { + List listValue = (List) value; + List fixedValue = new ArrayList(listValue.size()); + for(Object o : listValue) + { + fixedValue.add(fixObject(o)); + } + return fixedValue; + } + else if(value instanceof Map) + { + Map<?,?> mapValue = (Map) value; + Map fixedValue = new LinkedHashMap(mapValue.size()); + for(Map.Entry<?,?> entry : mapValue.entrySet()) + { + fixedValue.put(fixObject(entry.getKey()),fixObject(entry.getValue())); + } + return fixedValue; + } + else + { + return value; + } + + } + + private static Object convertMessageBody(String mimeType, byte[] data) + { + if("text/plain".equals(mimeType) || "text/xml".equals(mimeType)) + { + String text = new String(data); + return text; + } + else if("jms/map-message".equals(mimeType)) + { + TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); + + LinkedHashMap map = new LinkedHashMap(); + final int entries = reader.readIntImpl(); + for (int i = 0; i < entries; i++) + { + try + { + String propName = reader.readStringImpl(); + Object value = reader.readObject(); + + map.put(propName, value); + } + catch (EOFException e) + { + throw new IllegalArgumentException(e); + } + catch (TypedBytesFormatException e) + { + throw new IllegalArgumentException(e); + } + + } + + return map; + + } + else if("amqp/map".equals(mimeType)) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(data)); + final Map<String,Object> map = decoder.readMap(); + + return map; + + } + else if("amqp/list".equals(mimeType)) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(data)); + return decoder.readList(); + } + else if("jms/stream-message".equals(mimeType)) + { + TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); + + List list = new ArrayList(); + while (reader.remaining() != 0) + { + try + { + list.add(reader.readObject()); + } + catch (TypedBytesFormatException e) + { + throw new RuntimeException(e); // TODO - Implement + } + catch (EOFException e) + { + throw new RuntimeException(e); // TODO - Implement + } + } + return list; + } + else + { + return data; + + } + } + + @Override + public String getType() + { + return "v0-8 to Internal"; + } +} diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java index 9e0327fe76..f796a4b2e3 100644 --- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java @@ -43,16 +43,7 @@ import org.apache.qpid.amqp_1_0.type.DeliveryState; import org.apache.qpid.amqp_1_0.type.Outcome; import org.apache.qpid.amqp_1_0.type.Symbol; import org.apache.qpid.amqp_1_0.type.UnsignedInteger; -import org.apache.qpid.amqp_1_0.type.messaging.Accepted; -import org.apache.qpid.amqp_1_0.type.messaging.ExactSubjectFilter; -import org.apache.qpid.amqp_1_0.type.messaging.Filter; -import org.apache.qpid.amqp_1_0.type.messaging.MatchingSubjectFilter; -import org.apache.qpid.amqp_1_0.type.messaging.Modified; -import org.apache.qpid.amqp_1_0.type.messaging.NoLocalFilter; -import org.apache.qpid.amqp_1_0.type.messaging.Released; -import org.apache.qpid.amqp_1_0.type.messaging.Source; -import org.apache.qpid.amqp_1_0.type.messaging.StdDistMode; -import org.apache.qpid.amqp_1_0.type.messaging.TerminusDurability; +import org.apache.qpid.amqp_1_0.type.messaging.*; import org.apache.qpid.amqp_1_0.type.transport.AmqpError; import org.apache.qpid.amqp_1_0.type.transport.Detach; import org.apache.qpid.amqp_1_0.type.transport.Error; @@ -391,15 +382,21 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS options.add(Consumer.Option.NO_LOCAL); } - - _consumer.setNoLocal(noLocal); - - try { + final String name; + if(getEndpoint().getTarget() instanceof Target) + { + Target target = (Target) getEndpoint().getTarget(); + name = target.getAddress() == null ? getEndpoint().getName() : target.getAddress(); + } + else + { + name = getEndpoint().getName(); + } _consumer = _queue.addConsumer(_target, messageFilter == null ? null : new SimpleFilterManager(messageFilter), - Message_1_0.class, getEndpoint().getName(), options); + Message_1_0.class, name, options); } catch (AMQException e) { diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter new file mode 100644 index 0000000000..aa24847805 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.protocol.v1_0.MessageConverter_Internal_to_v1_0 +org.apache.qpid.server.protocol.v1_0.MessageConverter_v1_0_to_Internal
\ No newline at end of file diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java index f1843de8ac..0c83c31ad4 100644 --- a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java @@ -61,7 +61,7 @@ public class MessageConverter_0_10_to_0_8 implements MessageConverter<MessageTra { if(deliveryProps.hasDeliveryMode()) { - props.setDeliveryMode((byte) (deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT + props.setDeliveryMode((deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT)); } diff --git a/qpid/java/broker-plugins/management-amqp/build.xml b/qpid/java/broker-plugins/management-amqp/build.xml new file mode 100644 index 0000000000..542bb952f1 --- /dev/null +++ b/qpid/java/broker-plugins/management-amqp/build.xml @@ -0,0 +1,32 @@ +<!-- + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + --> +<project name="Qpid Broker-Plugins AMQP Management" default="build"> + <property name="module.depends" value="common broker-core" /> + <property name="module.test.depends" value="qpid-test-utils broker-core/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker-core=provided"/> + + <property name="broker.plugin" value="true"/> + <property name="broker-plugins-management-amqp.libs" value="" /> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> +</project> diff --git a/qpid/java/broker-plugins/management-amqp/pom.xml b/qpid/java/broker-plugins/management-amqp/pom.xml new file mode 100644 index 0000000000..83873a61f2 --- /dev/null +++ b/qpid/java/broker-plugins/management-amqp/pom.xml @@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <artifactId>qpid-parent</artifactId> + <groupId>org.apache.qpid</groupId> + <version>1.0-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + + <artifactId>qpid-broker-plugins-management-amqp</artifactId> + <version>0.28-SNAPSHOT</version> + <name>AMQP Management Protocol Plug-in</name> + <description>AMQP Management broker plug-in</description> + + <dependencies> + <dependency> + <groupId>org.apache.qpid</groupId> + <artifactId>qpid-broker-core</artifactId> + <version>${project.version}</version> + <scope>provided</scope> + </dependency> + + </dependencies> + + <build> + </build> + +</project> diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagedEntityType.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagedEntityType.java new file mode 100644 index 0000000000..10a16faa56 --- /dev/null +++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagedEntityType.java @@ -0,0 +1,73 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.amqp; + +import java.util.Arrays; + +class ManagedEntityType +{ + private final String _name; + private final ManagedEntityType[] _parents; + private final String[] _attributes; + private final String[] _operations; + + ManagedEntityType(final String name, + final ManagedEntityType[] parents, + final String[] attributes, + final String[] operations) + { + _name = name; + _parents = parents; + _attributes = attributes; + _operations = operations; + } + + public String getName() + { + return _name; + } + + public ManagedEntityType[] getParents() + { + return _parents; + } + + public String[] getAttributes() + { + return _attributes; + } + + public String[] getOperations() + { + return _operations; + } + + @Override + public String toString() + { + return "ManagedEntityType{" + + "name='" + _name + '\'' + + ", parents=" + Arrays.toString(_parents) + + ", attributes=" + Arrays.toString(_attributes) + + ", operations=" + Arrays.toString(_operations) + + '}'; + } +} diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java new file mode 100644 index 0000000000..1c1c72dd0b --- /dev/null +++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java @@ -0,0 +1,1402 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.amqp; + +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQSecurityException; +import org.apache.qpid.server.consumer.Consumer; +import org.apache.qpid.server.consumer.ConsumerTarget; +import org.apache.qpid.server.filter.FilterManager; +import org.apache.qpid.server.filter.Filterable; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.InstanceProperties; +import org.apache.qpid.server.message.MessageDestination; +import org.apache.qpid.server.message.MessageInstance; +import org.apache.qpid.server.message.MessageSource; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.message.internal.InternalMessageHeader; +import org.apache.qpid.server.model.AmqpManagement; +import org.apache.qpid.server.model.ConfigurationChangeListener; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.plugin.SystemNodeCreator; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.protocol.MessageConverterRegistry; +import org.apache.qpid.server.security.AuthorizationHolder; +import org.apache.qpid.server.store.StorableMessageMetaData; +import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.util.Action; +import org.apache.qpid.server.util.StateChangeListener; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.nio.charset.Charset; +import java.security.AccessControlException; +import java.text.MessageFormat; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; + +class ManagementNode implements MessageSource<ManagementNodeConsumer,ManagementNode>, MessageDestination +{ + + public static final String NAME_ATTRIBUTE = "name"; + public static final String IDENTITY_ATTRIBUTE = "identity"; + public static final String TYPE_ATTRIBUTE = "type"; + public static final String OPERATION_HEADER = "operation"; + public static final String SELF_NODE_NAME = "self"; + public static final String MANAGEMENT_TYPE = "org.amqp.management"; + public static final String GET_TYPES = "GET-TYPES"; + public static final String GET_ATTRIBUTES = "GET-ATTRIBUTES"; + public static final String GET_OPERATIONS = "GET-OPERATIONS"; + public static final String QUERY = "QUERY"; + public static final String ENTITY_TYPES_HEADER = "entityTypes"; + public static final String STATUS_CODE_HEADER = "statusCode"; + public static final int STATUS_CODE_OK = 200; + public static final String ATTRIBUTES_HEADER = "attributes"; + public static final String OFFSET_HEADER = "offset"; + public static final String COUNT_HEADER = "count"; + public static final String MANAGEMENT_NODE_NAME = "$management"; + public static final String CREATE_OPERATION = "CREATE"; + public static final String READ_OPERATION = "READ"; + public static final String UPDATE_OPERATION = "UPDATE"; + public static final String DELETE_OPERATION = "DELETE"; + public static final String STATUS_DESCRIPTION_HEADER = "statusDescription"; + public static final int NOT_FOUND_STATUS_CODE = 404; + public static final int NOT_IMPLEMENTED_STATUS_CODE = 501; + public static final int STATUS_CODE_NO_CONTENT = 204; + public static final int STATUS_CODE_FORBIDDEN = 403; + public static final int STATUS_CODE_BAD_REQUEST = 400; + public static final int STATUS_CODE_INTERNAL_ERROR = 500; + + + private final VirtualHost _virtualHost; + + private final UUID _id; + + private final CopyOnWriteArrayList<ConsumerRegistrationListener<ManagementNode>> _consumerRegistrationListeners = + new CopyOnWriteArrayList<ConsumerRegistrationListener<ManagementNode>>(); + + private final SystemNodeCreator.SystemNodeRegistry _registry; + private final ConfiguredObject _managedObject; + private Map<String, ManagementNodeConsumer> _consumers = new ConcurrentHashMap<String, ManagementNodeConsumer>(); + + private Map<String,ManagedEntityType> _entityTypes = Collections.synchronizedMap(new LinkedHashMap<String, ManagedEntityType>()); + + private Map<ManagedEntityType,Map<String,ConfiguredObject>> _entities = Collections.synchronizedMap(new LinkedHashMap<ManagedEntityType,Map<String,ConfiguredObject>>()); + + + public ManagementNode(final SystemNodeCreator.SystemNodeRegistry registry, + final ConfiguredObject configuredObject) + { + _virtualHost = registry.getVirtualHost(); + _registry = registry; + final String name = configuredObject.getId() + MANAGEMENT_NODE_NAME; + _id = UUID.nameUUIDFromBytes(name.getBytes(Charset.defaultCharset())); + + + _managedObject = configuredObject; + + populateTypeMetaData(configuredObject.getClass(), false); + + configuredObject.addChangeListener(new ModelObjectListener()); + + final Class managementClass = getManagementClass(_managedObject.getClass()); + _entities.get(_entityTypes.get(managementClass.getName())).put(_managedObject.getName(), _managedObject); + + Collection<Class<? extends ConfiguredObject>> childClasses = Model.getInstance().getChildTypes(managementClass); + for(Class<? extends ConfiguredObject> childClass : childClasses) + { + if(getManagementClass(childClass) != null) + { + for(ConfiguredObject child : _managedObject.getChildren(childClass)) + { + _entities.get(_entityTypes.get(getManagementClass(childClass).getName())).put(child.getName(), child); + } + } + } + + } + + private Class getManagementClass(Class objectClass) + { + List<Class> allClasses = new ArrayList<Class>(); + allClasses.add(objectClass); + allClasses.addAll(Arrays.asList(objectClass.getInterfaces())); + allClasses.add(objectClass.getSuperclass()); + for(Class clazz : allClasses) + { + AmqpManagement annotation = (AmqpManagement) clazz.getAnnotation(AmqpManagement.class); + if(annotation != null) + { + return clazz; + } + } + return null; + } + + private boolean populateTypeMetaData(final Class<? extends ConfiguredObject> objectClass, boolean allowCreate) + { + Class clazz = getManagementClass(objectClass); + if( clazz != null) + { + AmqpManagement annotation = (AmqpManagement) clazz.getAnnotation(AmqpManagement.class); + populateTypeMetaData(clazz, annotation); + return true; + } + else + { + return false; + } + } + + private ManagedEntityType populateTypeMetaData(Class clazz, + final AmqpManagement entityType) + { + + ManagedEntityType managedEntityType = _entityTypes.get(clazz.getName()); + + if(managedEntityType == null) + { + List<String> opsList = new ArrayList<String>(Arrays.asList(entityType.operations())); + if(entityType.creatable()) + { + boolean isCreatableChild = false; + for(Class<? extends ConfiguredObject> parentConfig : Model.getInstance().getParentTypes(clazz)) + { + isCreatableChild = parentConfig.isAssignableFrom(_managedObject.getClass()); + if(isCreatableChild) + { + opsList.add(CREATE_OPERATION); + break; + } + } + } + opsList.addAll(Arrays.asList(READ_OPERATION, UPDATE_OPERATION, DELETE_OPERATION)); + + Set<ManagedEntityType> parentSet = new HashSet<ManagedEntityType>(); + + List<Class> allClasses = new ArrayList<Class>(Arrays.asList(clazz.getInterfaces())); + if(clazz.getSuperclass() != null) + { + allClasses.add(clazz.getSuperclass()); + } + + for(Class parentClazz : allClasses) + { + if(parentClazz.getAnnotation(AmqpManagement.class) != null) + { + ManagedEntityType parentType = populateTypeMetaData(parentClazz, + (AmqpManagement) parentClazz.getAnnotation( + AmqpManagement.class) + ); + parentSet.add(parentType); + parentSet.addAll(Arrays.asList(parentType.getParents())); + + } + } + managedEntityType = new ManagedEntityType(clazz.getName(), parentSet.toArray(new ManagedEntityType[parentSet.size()]), entityType.attributes(), opsList.toArray(new String[opsList.size()])); + _entityTypes.put(clazz.getName(),managedEntityType); + _entities.put(managedEntityType, Collections.synchronizedMap(new LinkedHashMap<String, ConfiguredObject>())); + + if(ConfiguredObject.class.isAssignableFrom(clazz)) + { + Collection<Class<? extends ConfiguredObject>> childTypes = Model.getInstance().getChildTypes(clazz); + for(Class<? extends ConfiguredObject> childClass : childTypes) + { + populateTypeMetaData(childClass, true); + } + } + + } + + return managedEntityType; + + } + + @Override + public <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message, + final InstanceProperties instanceProperties, + final ServerTransaction txn, + final Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction) + { + + @SuppressWarnings("unchecked") + MessageConverter<M, InternalMessage> converter = + MessageConverterRegistry.getConverter((Class<M>)message.getClass(), InternalMessage.class); + + final InternalMessage msg = converter.<M>convert(message, _virtualHost); + + if(validateMessage(msg)) + { + txn.addPostTransactionAction(new ServerTransaction.Action() + { + @Override + public void postCommit() + { + enqueue(msg, instanceProperties, postEnqueueAction); + } + + @Override + public void onRollback() + { + + } + }); + + return 1; + } + else + { + return 0; + } + } + + private boolean validateMessage(final ServerMessage message) + { + AMQMessageHeader header = message.getMessageHeader(); + return containsStringHeader(header, TYPE_ATTRIBUTE) && containsStringHeader(header, OPERATION_HEADER) + && (containsStringHeader(header, NAME_ATTRIBUTE) || containsStringHeader(header, IDENTITY_ATTRIBUTE)); + } + + private boolean containsStringHeader(final AMQMessageHeader header, String name) + { + return header.containsHeader(name) && header.getHeader(name) instanceof String; + } + + synchronized void enqueue(InternalMessage message, InstanceProperties properties, Action<? super MessageInstance<?, ? extends Consumer>> postEnqueueAction) + { + if(postEnqueueAction != null) + { + postEnqueueAction.performAction(new ConsumedMessageInstance(message, properties)); + } + + + + String name = (String) message.getMessageHeader().getHeader(NAME_ATTRIBUTE); + String id = (String) message.getMessageHeader().getHeader(IDENTITY_ATTRIBUTE); + String type = (String) message.getMessageHeader().getHeader(TYPE_ATTRIBUTE); + String operation = (String) message.getMessageHeader().getHeader(OPERATION_HEADER); + + InternalMessage response; + + if(SELF_NODE_NAME.equals(name) && type.equals(MANAGEMENT_TYPE)) + { + response = performManagementOperation(message); + } + else if(CREATE_OPERATION.equals(operation)) + { + response = performCreateOperation(message, type); + } + else + { + + ConfiguredObject entity = findSubject(name, id, type); + + if(entity != null) + { + response = performOperation(message, entity); + } + else + { + if(id != null) + { + response = createFailureResponse(message, + NOT_FOUND_STATUS_CODE, + "No entity with id {0} of type {1} found", id, type); + } + else + { + response = createFailureResponse(message, + NOT_FOUND_STATUS_CODE, + "No entity with name {0} of type {1} found", name, type); + } + } + } + + + ManagementNodeConsumer consumer = _consumers.get(message.getMessageHeader().getReplyTo()); + if(consumer != null) + { + // TODO - check same owner + consumer.send(response); + } + // TODO - route to a queue + + } + + private InternalMessage performCreateOperation(final InternalMessage message, final String type) + { + InternalMessage response; + ManagedEntityType entityType = _entityTypes.get(type); + if(type != null) + { + if(Arrays.asList(entityType.getOperations()).contains(CREATE_OPERATION)) + { + Object messageBody = message.getMessageBody(); + if(messageBody instanceof Map) + { + try + { + + Class<? extends ConfiguredObject> clazz = + (Class<? extends ConfiguredObject>) Class.forName(type); + try + { + ConfiguredObject child = _managedObject.createChild(clazz, (Map) messageBody); + if(child == null) + { + child = _entities.get(entityType).get(message.getMessageHeader().getHeader(NAME_ATTRIBUTE)); + } + response = performReadOperation(message, child); + } + catch(RuntimeException e) + { + if (e instanceof AccessControlException || e.getCause() instanceof AMQSecurityException) + { + response = createFailureResponse(message, STATUS_CODE_FORBIDDEN, e.getMessage()); + } + else + { + throw e; + } + } + } + catch (ClassNotFoundException e) + { + response = createFailureResponse(message, + STATUS_CODE_INTERNAL_ERROR, "Unable to instantiate an instance of {0} ", type); + } + } + else + { + response = createFailureResponse(message, + STATUS_CODE_BAD_REQUEST, + "The message body in the request was not of the correct type"); + } + } + else + { + response = createFailureResponse(message, + STATUS_CODE_FORBIDDEN, + "Cannot CREATE entities of type {0}", type); + } + } + else + { + response = createFailureResponse(message, + NOT_FOUND_STATUS_CODE, + "Unknown type {0}",type); + } + return response; + } + + private InternalMessage performOperation(final InternalMessage requestMessage, final ConfiguredObject entity) + { + String operation = (String) requestMessage.getMessageHeader().getHeader(OPERATION_HEADER); + + if(READ_OPERATION.equals(operation)) + { + return performReadOperation(requestMessage, entity); + } + else if(DELETE_OPERATION.equals(operation)) + { + return performDeleteOperation(requestMessage, entity); + } + else if(UPDATE_OPERATION.equals(operation)) + { + return performUpdateOperation(requestMessage, entity); + } + else + { + return createFailureResponse(requestMessage, NOT_IMPLEMENTED_STATUS_CODE, "Unable to perform the {0} operation",operation); + } + } + + private InternalMessage performReadOperation(final InternalMessage requestMessage, final ConfiguredObject entity) + { + final InternalMessageHeader requestHeader = requestMessage.getMessageHeader(); + final MutableMessageHeader responseHeader = new MutableMessageHeader(); + responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null + ? requestHeader.getMessageId() + : requestHeader.getCorrelationId()); + responseHeader.setMessageId(UUID.randomUUID().toString()); + responseHeader.setHeader(NAME_ATTRIBUTE, entity.getName()); + responseHeader.setHeader(IDENTITY_ATTRIBUTE, entity.getId().toString()); + responseHeader.setHeader(STATUS_CODE_HEADER,STATUS_CODE_OK); + final String type = getManagementClass(entity.getClass()).getName(); + responseHeader.setHeader(TYPE_ATTRIBUTE, type); + + Map<String,Object> responseBody = new LinkedHashMap<String, Object>(); + final ManagedEntityType entityType = _entityTypes.get(type); + for(String attribute : entityType.getAttributes()) + { + responseBody.put(attribute, fixValue(entity.getAttribute(attribute))); + } + + return InternalMessage.createMapMessage(_virtualHost.getMessageStore(),responseHeader, responseBody); + } + + + private InternalMessage performDeleteOperation(final InternalMessage requestMessage, final ConfiguredObject entity) + { + final InternalMessageHeader requestHeader = requestMessage.getMessageHeader(); + final MutableMessageHeader responseHeader = new MutableMessageHeader(); + responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null + ? requestHeader.getMessageId() + : requestHeader.getCorrelationId()); + responseHeader.setMessageId(UUID.randomUUID().toString()); + responseHeader.setHeader(NAME_ATTRIBUTE, entity.getName()); + responseHeader.setHeader(IDENTITY_ATTRIBUTE, entity.getId().toString()); + final String type = getManagementClass(entity.getClass()).getName(); + responseHeader.setHeader(TYPE_ATTRIBUTE, type); + try + { + entity.setDesiredState(entity.getActualState(),State.DELETED); + responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_NO_CONTENT); + } + catch(RuntimeException e) + { + if (e instanceof AccessControlException || e.getCause() instanceof AMQSecurityException) + { + responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_FORBIDDEN); + } + else + { + throw e; + } + + } + + return InternalMessage.createMapMessage(_virtualHost.getMessageStore(),responseHeader, Collections.emptyMap()); + } + + + private InternalMessage performUpdateOperation(final InternalMessage requestMessage, final ConfiguredObject entity) + { + final InternalMessageHeader requestHeader = requestMessage.getMessageHeader(); + final MutableMessageHeader responseHeader = new MutableMessageHeader(); + responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null + ? requestHeader.getMessageId() + : requestHeader.getCorrelationId()); + responseHeader.setMessageId(UUID.randomUUID().toString()); + responseHeader.setHeader(NAME_ATTRIBUTE, entity.getName()); + responseHeader.setHeader(IDENTITY_ATTRIBUTE, entity.getId().toString()); + final String type = getManagementClass(entity.getClass()).getName(); + responseHeader.setHeader(TYPE_ATTRIBUTE, type); + + Object messageBody = requestMessage.getMessageBody(); + if(messageBody instanceof Map) + { + try + { + entity.setAttributes((Map)messageBody); + return performReadOperation(requestMessage, entity); + } + catch(RuntimeException e) + { + if (e instanceof AccessControlException || e.getCause() instanceof AMQSecurityException) + { + return createFailureResponse(requestMessage, STATUS_CODE_FORBIDDEN, e.getMessage()); + } + else + { + throw e; + } + } + } + else + { + return createFailureResponse(requestMessage, + STATUS_CODE_BAD_REQUEST, + "The message body in the request was not of the correct type"); + } + + + } + + private ConfiguredObject findSubject(final String name, final String id, final String type) + { + ConfiguredObject subject; + ManagedEntityType met = _entityTypes.get(type); + if(met == null) + { + return null; + } + + subject = findSubject(name, id, met); + if(subject == null) + { + ArrayList<ManagedEntityType> allTypes = new ArrayList<ManagedEntityType>(_entityTypes.values()); + for(ManagedEntityType entityType : allTypes) + { + if(Arrays.asList(entityType.getParents()).contains(met)) + { + subject = findSubject(name, id, entityType); + if(subject != null) + { + return subject; + } + } + } + } + return subject; + } + + private ConfiguredObject findSubject(final String name, final String id, final ManagedEntityType entityType) + { + + Map<String, ConfiguredObject> objects = _entities.get(entityType); + if(name != null) + { + ConfiguredObject subject = objects.get(name); + if(subject != null) + { + return subject; + } + } + else + { + final Collection<ConfiguredObject> values = new ArrayList<ConfiguredObject>(objects.values()); + for(ConfiguredObject o : values) + { + if(o.getId().toString().equals(id)) + { + return o; + } + } + } + return null; + } + + private InternalMessage createFailureResponse(final InternalMessage requestMessage, + final int statusCode, + final String stateDescription, + String... params) + { + final InternalMessageHeader requestHeader = requestMessage.getMessageHeader(); + final MutableMessageHeader responseHeader = new MutableMessageHeader(); + responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null + ? requestHeader.getMessageId() + : requestHeader.getCorrelationId()); + responseHeader.setMessageId(UUID.randomUUID().toString()); + for(String header : requestHeader.getHeaderNames()) + { + responseHeader.setHeader(header, requestHeader.getHeader(header)); + } + responseHeader.setHeader(STATUS_CODE_HEADER, statusCode); + responseHeader.setHeader(STATUS_DESCRIPTION_HEADER, MessageFormat.format(stateDescription, params)); + return InternalMessage.createBytesMessage(_virtualHost.getMessageStore(), responseHeader, new byte[0]); + + } + + private InternalMessage performManagementOperation(final InternalMessage msg) + { + final InternalMessage responseMessage; + final InternalMessageHeader requestHeader = msg.getMessageHeader(); + final MutableMessageHeader responseHeader = new MutableMessageHeader(); + responseHeader.setCorrelationId(requestHeader.getCorrelationId() == null + ? requestHeader.getMessageId() + : requestHeader.getCorrelationId()); + responseHeader.setMessageId(UUID.randomUUID().toString()); + + + String operation = (String) requestHeader.getHeader(OPERATION_HEADER); + if(GET_TYPES.equals(operation)) + { + responseMessage = performGetTypes(requestHeader, responseHeader); + } + else if(GET_ATTRIBUTES.equals(operation)) + { + responseMessage = performGetAttributes(requestHeader, responseHeader); + } + else if(GET_OPERATIONS.equals(operation)) + { + responseMessage = performGetOperations(requestHeader, responseHeader); + } + else if(QUERY.equals(operation)) + { + responseMessage = performQuery(requestHeader, responseHeader); + } + else + { + responseMessage = InternalMessage.createBytesMessage(_virtualHost.getMessageStore(), requestHeader, new byte[0]); + } + return responseMessage; + } + + private InternalMessage performGetTypes(final InternalMessageHeader requestHeader, + final MutableMessageHeader responseHeader) + { + final InternalMessage responseMessage; + List<String> restriction; + if(requestHeader.containsHeader(ENTITY_TYPES_HEADER)) + { + restriction = (List<String>) requestHeader.getHeader(ENTITY_TYPES_HEADER); + } + else + { + restriction = null; + } + + responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_OK); + Map<String,Object> responseMap = new LinkedHashMap<String, Object>(); + Map<String,ManagedEntityType> entityMapCopy; + synchronized (_entityTypes) + { + entityMapCopy = new LinkedHashMap<String, ManagedEntityType>(_entityTypes); + } + + for(ManagedEntityType type : entityMapCopy.values()) + { + if(restriction == null || meetsIndirectRestriction(type,restriction)) + { + final ManagedEntityType[] parents = type.getParents(); + List<String> parentNames = new ArrayList<String>(); + if(parents != null) + { + for(ManagedEntityType parent : parents) + { + parentNames.add(parent.getName()); + } + } + responseMap.put(type.getName(), parentNames); + } + } + responseMessage = InternalMessage.createMapMessage(_virtualHost.getMessageStore(), responseHeader, responseMap); + return responseMessage; + } + + private InternalMessage performGetAttributes(final InternalMessageHeader requestHeader, + final MutableMessageHeader responseHeader) + { + final InternalMessage responseMessage; + List<String> restriction; + if(requestHeader.containsHeader(ENTITY_TYPES_HEADER)) + { + restriction = (List<String>) requestHeader.getHeader(ENTITY_TYPES_HEADER); + } + else + { + restriction = null; + } + + responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_OK); + Map<String,Object> responseMap = new LinkedHashMap<String, Object>(); + Map<String,ManagedEntityType> entityMapCopy; + synchronized (_entityTypes) + { + entityMapCopy = new LinkedHashMap<String, ManagedEntityType>(_entityTypes); + } + + for(ManagedEntityType type : entityMapCopy.values()) + { + if(restriction == null || restriction.contains(type.getName())) + { + responseMap.put(type.getName(), Arrays.asList(type.getAttributes())); + } + } + responseMessage = InternalMessage.createMapMessage(_virtualHost.getMessageStore(), responseHeader, responseMap); + return responseMessage; + } + + + private InternalMessage performGetOperations(final InternalMessageHeader requestHeader, + final MutableMessageHeader responseHeader) + { + final InternalMessage responseMessage; + List<String> restriction; + if(requestHeader.containsHeader(ENTITY_TYPES_HEADER)) + { + restriction = (List<String>) requestHeader.getHeader(ENTITY_TYPES_HEADER); + } + else + { + restriction = null; + } + + responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_OK); + Map<String,Object> responseMap = new LinkedHashMap<String, Object>(); + Map<String,ManagedEntityType> entityMapCopy; + synchronized (_entityTypes) + { + entityMapCopy = new LinkedHashMap<String, ManagedEntityType>(_entityTypes); + } + + for(ManagedEntityType type : entityMapCopy.values()) + { + if(restriction == null || restriction.contains(type.getName())) + { + responseMap.put(type.getName(), Arrays.asList(type.getOperations())); + } + } + responseMessage = InternalMessage.createMapMessage(_virtualHost.getMessageStore(), responseHeader, responseMap); + return responseMessage; + } + + private InternalMessage performQuery(final InternalMessageHeader requestHeader, + final MutableMessageHeader responseHeader) + { + final InternalMessage responseMessage; + List<String> restriction; + List<String> attributes; + int offset; + int count; + + if(requestHeader.containsHeader(ENTITY_TYPES_HEADER)) + { + restriction = (List<String>) requestHeader.getHeader(ENTITY_TYPES_HEADER); + responseHeader.setHeader(ENTITY_TYPES_HEADER, restriction); + } + else + { + restriction = new ArrayList<String>(_entityTypes.keySet()); + } + + + if(requestHeader.containsHeader(ATTRIBUTES_HEADER)) + { + attributes = (List<String>) requestHeader.getHeader(ATTRIBUTES_HEADER); + } + else + { + LinkedHashMap<String,Void> attributeSet = new LinkedHashMap<String, Void>(); + for(String entityType : restriction) + { + ManagedEntityType type = _entityTypes.get(entityType); + if(type != null) + { + for(String attributeName : type.getAttributes()) + { + attributeSet.put(attributeName, null); + } + } + } + attributes = new ArrayList<String>(attributeSet.keySet()); + + } + + if(requestHeader.containsHeader(OFFSET_HEADER)) + { + offset = ((Number) requestHeader.getHeader(OFFSET_HEADER)).intValue(); + responseHeader.setHeader(OFFSET_HEADER,offset); + } + else + { + offset = 0; + } + + if(requestHeader.containsHeader(COUNT_HEADER)) + { + count = ((Number) requestHeader.getHeader(COUNT_HEADER)).intValue(); + } + else + { + count = Integer.MAX_VALUE; + } + + responseHeader.setHeader(ATTRIBUTES_HEADER, attributes); + + responseHeader.setHeader(STATUS_CODE_HEADER, STATUS_CODE_OK); + List<List<Object>> responseList = new ArrayList<List<Object>>(); + + int rowNo = 0; + for(String type : restriction) + { + ManagedEntityType entityType = _entityTypes.get(type); + if(entityType != null) + { + Map<String, ConfiguredObject> entityMap = _entities.get(entityType); + if(entityMap != null) + { + List<ConfiguredObject> entities; + synchronized(entityMap) + { + entities = new ArrayList<ConfiguredObject>(entityMap.values()); + } + for(ConfiguredObject entity : entities) + { + if(rowNo++ >= offset) + { + Object[] attrValue = new Object[attributes.size()]; + int col = 0; + for(String attr : attributes) + { + Object value; + if(TYPE_ATTRIBUTE.equals(attr)) + { + value = entityType.getName(); + } + else + { + value = fixValue(entity.getAttribute(attr)); + } + attrValue[col++] = value; + } + responseList.add(Arrays.asList(attrValue)); + } + if(responseList.size()==count) + { + break; + } + } + } + } + + if(responseList.size()==count) + { + break; + } + } + responseHeader.setHeader(COUNT_HEADER, count); + responseMessage = InternalMessage.createListMessage(_virtualHost.getMessageStore(), + responseHeader, + responseList); + return responseMessage; + } + + private Object fixValue(final Object value) + { + Object fixedValue; + if(value instanceof Enum) + { + fixedValue = value.toString(); + } + else if(value instanceof Map) + { + Map<Object, Object> oldValue = (Map<Object, Object>) value; + Map<Object, Object> newValue = new LinkedHashMap<Object, Object>(); + for(Map.Entry<Object, Object> entry : oldValue.entrySet()) + { + newValue.put(fixValue(entry.getKey()),fixValue(entry.getValue())); + } + fixedValue = newValue; + } + else if(value instanceof Collection) + { + Collection oldValue = (Collection) value; + List newValue = new ArrayList(oldValue.size()); + for(Object o : oldValue) + { + newValue.add(fixValue(o)); + } + fixedValue = newValue; + } + else if(value != null && value.getClass().isArray() && !(value instanceof byte[])) + { + fixedValue = fixValue(Arrays.asList((Object[])value)); + } + else + { + fixedValue = value; + } + return fixedValue; + + } + + + private boolean meetsIndirectRestriction(final ManagedEntityType type, final List<String> restriction) + { + if(restriction.contains(type.getName())) + { + return true; + } + if(type.getParents() != null) + { + for(ManagedEntityType parent : type.getParents()) + { + if(meetsIndirectRestriction(parent, restriction)) + { + return true; + } + } + } + return false; + } + + @Override + public synchronized <T extends ConsumerTarget> ManagementNodeConsumer addConsumer(final T target, + final FilterManager filters, + final Class<? extends ServerMessage> messageClass, + final String consumerName, + final EnumSet<Consumer.Option> options) throws AMQException + { + + final ManagementNodeConsumer managementNodeConsumer = new ManagementNodeConsumer(consumerName,this, target); + target.consumerAdded(managementNodeConsumer); + _consumers.put(consumerName, managementNodeConsumer); + for(ConsumerRegistrationListener<ManagementNode> listener : _consumerRegistrationListeners) + { + listener.consumerAdded(this, managementNodeConsumer); + } + return managementNodeConsumer; + } + + @Override + public synchronized Collection<ManagementNodeConsumer> getConsumers() + { + return new ArrayList<ManagementNodeConsumer>(_consumers.values()); + } + + @Override + public void addConsumerRegistrationListener(final ConsumerRegistrationListener<ManagementNode> listener) + { + _consumerRegistrationListeners.add(listener); + } + + @Override + public void removeConsumerRegistrationListener(final ConsumerRegistrationListener listener) + { + _consumerRegistrationListeners.remove(listener); + } + + @Override + public AuthorizationHolder getAuthorizationHolder() + { + return null; + } + + @Override + public void setAuthorizationHolder(final AuthorizationHolder principalHolder) + { + + } + + @Override + public void setExclusiveOwningSession(final AMQSessionModel owner) + { + + } + + @Override + public AMQSessionModel getExclusiveOwningSession() + { + return null; + } + + @Override + public boolean isExclusive() + { + return false; + } + + @Override + public String getName() + { + return MANAGEMENT_NODE_NAME; + } + + @Override + public UUID getId() + { + return _id; + } + + @Override + public boolean isDurable() + { + return false; + } + + private class ConsumedMessageInstance implements MessageInstance<ConsumedMessageInstance,Consumer> + { + private final ServerMessage _message; + private final InstanceProperties _properties; + + public ConsumedMessageInstance(final ServerMessage message, + final InstanceProperties properties) + { + _message = message; + _properties = properties; + } + + @Override + public int getDeliveryCount() + { + return 0; + } + + @Override + public void incrementDeliveryCount() + { + + } + + @Override + public void decrementDeliveryCount() + { + + } + + @Override + public void addStateChangeListener(final StateChangeListener<? super ConsumedMessageInstance, State> listener) + { + + } + + @Override + public boolean removeStateChangeListener(final StateChangeListener<? super ConsumedMessageInstance, State> listener) + { + return false; + } + + + @Override + public boolean acquiredByConsumer() + { + return false; + } + + @Override + public boolean isAcquiredBy(final Consumer consumer) + { + return false; + } + + @Override + public void setRedelivered() + { + + } + + @Override + public boolean isRedelivered() + { + return false; + } + + @Override + public Consumer getDeliveredConsumer() + { + return null; + } + + @Override + public void reject() + { + + } + + @Override + public boolean isRejectedBy(final Consumer consumer) + { + return false; + } + + @Override + public boolean getDeliveredToConsumer() + { + return true; + } + + @Override + public boolean expired() throws AMQException + { + return false; + } + + @Override + public boolean acquire(final Consumer sub) + { + return false; + } + + @Override + public int getMaximumDeliveryCount() + { + return 0; + } + + @Override + public int routeToAlternate(final Action<? super MessageInstance<?, ? extends Consumer>> action, + final ServerTransaction txn) + { + return 0; + } + + + @Override + public Filterable asFilterable() + { + return null; + } + + @Override + public boolean isAvailable() + { + return false; + } + + @Override + public boolean acquire() + { + return false; + } + + @Override + public boolean isAcquired() + { + return false; + } + + @Override + public void release() + { + + } + + @Override + public boolean resend() throws AMQException + { + return false; + } + + @Override + public void delete() + { + + } + + @Override + public boolean isDeleted() + { + return false; + } + + @Override + public ServerMessage getMessage() + { + return _message; + } + + @Override + public InstanceProperties getInstanceProperties() + { + return _properties; + } + + @Override + public TransactionLogResource getOwningResource() + { + return ManagementNode.this; + } + } + + private class ModelObjectListener implements ConfigurationChangeListener + { + @Override + public void stateChanged(final ConfiguredObject object, final State oldState, final State newState) + { + if(newState == State.DELETED) + { + _registry.removeSystemNode(ManagementNode.this); + } + } + + @Override + public void childAdded(final ConfiguredObject object, final ConfiguredObject child) + { + final ManagedEntityType entityType = _entityTypes.get(getManagementClass(child.getClass()).getName()); + if(entityType != null) + { + _entities.get(entityType).put(child.getName(), child); + } + } + + @Override + public void childRemoved(final ConfiguredObject object, final ConfiguredObject child) + { + final ManagedEntityType entityType = _entityTypes.get(getManagementClass(child.getClass()).getName()); + if(entityType != null) + { + _entities.get(entityType).remove(child.getName()); + } + } + + @Override + public void attributeSet(final ConfiguredObject object, + final String attributeName, + final Object oldAttributeValue, + final Object newAttributeValue) + { + + } + } + + private static class MutableMessageHeader implements AMQMessageHeader + { + private final LinkedHashMap<String, Object> _headers = new LinkedHashMap<String, Object>(); + private String _correlationId; + private long _expiration; + private String _userId; + private String _appId; + private String _messageId; + private String _mimeType; + private String _encoding; + private byte _priority; + private long _timestamp; + private String _type; + private String _replyTo; + + public void setCorrelationId(final String correlationId) + { + _correlationId = correlationId; + } + + public void setExpiration(final long expiration) + { + _expiration = expiration; + } + + public void setUserId(final String userId) + { + _userId = userId; + } + + public void setAppId(final String appId) + { + _appId = appId; + } + + public void setMessageId(final String messageId) + { + _messageId = messageId; + } + + public void setMimeType(final String mimeType) + { + _mimeType = mimeType; + } + + public void setEncoding(final String encoding) + { + _encoding = encoding; + } + + public void setPriority(final byte priority) + { + _priority = priority; + } + + public void setTimestamp(final long timestamp) + { + _timestamp = timestamp; + } + + public void setType(final String type) + { + _type = type; + } + + public void setReplyTo(final String replyTo) + { + _replyTo = replyTo; + } + + public String getCorrelationId() + { + return _correlationId; + } + + public long getExpiration() + { + return _expiration; + } + + public String getUserId() + { + return _userId; + } + + public String getAppId() + { + return _appId; + } + + public String getMessageId() + { + return _messageId; + } + + public String getMimeType() + { + return _mimeType; + } + + public String getEncoding() + { + return _encoding; + } + + public byte getPriority() + { + return _priority; + } + + public long getTimestamp() + { + return _timestamp; + } + + public String getType() + { + return _type; + } + + public String getReplyTo() + { + return _replyTo; + } + + @Override + public Object getHeader(final String name) + { + return _headers.get(name); + } + + @Override + public boolean containsHeaders(final Set<String> names) + { + return _headers.keySet().containsAll(names); + } + + @Override + public boolean containsHeader(final String name) + { + return _headers.containsKey(name); + } + + @Override + public Collection<String> getHeaderNames() + { + return Collections.unmodifiableCollection(_headers.keySet()); + } + + public void setHeader(String header, Object value) + { + _headers.put(header,value); + } + + } +} diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java new file mode 100644 index 0000000000..98bb20d364 --- /dev/null +++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java @@ -0,0 +1,242 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.amqp; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.consumer.Consumer; +import org.apache.qpid.server.consumer.ConsumerTarget; +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.util.StateChangeListener; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +class ManagementNodeConsumer implements Consumer +{ + private final long _id = Consumer.SUB_ID_GENERATOR.getAndIncrement(); + private final ManagementNode _managementNode; + private final List<ManagementResponse> _queue = Collections.synchronizedList(new ArrayList<ManagementResponse>()); + private final ConsumerTarget _target; + private final Lock _stateChangeLock = new ReentrantLock(); + private final String _name; + private final StateChangeListener<ConsumerTarget, ConsumerTarget.State> _targetChangeListener = new TargetChangeListener(); + + + public ManagementNodeConsumer(final String consumerName, final ManagementNode managementNode, ConsumerTarget target) + { + _name = consumerName; + _managementNode = managementNode; + _target = target; + target.setStateListener(_targetChangeListener); + } + + @Override + public void externalStateChange() + { + + } + + @Override + public long getBytesOut() + { + return 0; + } + + @Override + public long getMessagesOut() + { + return 0; + } + + @Override + public long getUnacknowledgedBytes() + { + return 0; + } + + @Override + public long getUnacknowledgedMessages() + { + return 0; + } + + @Override + public AMQSessionModel getSessionModel() + { + return _target.getSessionModel(); + } + + @Override + public void setNoLocal(final boolean noLocal) + { + } + + @Override + public long getId() + { + return _id; + } + + @Override + public boolean isSuspended() + { + return false; + } + + @Override + public boolean isClosed() + { + return false; + } + + @Override + public boolean acquires() + { + return true; + } + + @Override + public boolean seesRequeues() + { + return false; + } + + @Override + public void close() throws AMQException + { + + } + + @Override + public boolean trySendLock() + { + return _stateChangeLock.tryLock(); + } + + @Override + public void getSendLock() + { + _stateChangeLock.lock(); + } + + @Override + public void releaseSendLock() + { + _stateChangeLock.unlock(); + } + + + @Override + public boolean isActive() + { + return false; + } + + @Override + public String getName() + { + return _name; + } + + @Override + public void flush() throws AMQException + { + + } + + ManagementNode getManagementNode() + { + return _managementNode; + } + + void send(final InternalMessage response) + { + getSendLock(); + try + { + final ManagementResponse responseEntry = new ManagementResponse(this, response); + if(_queue.isEmpty() && _target.allocateCredit(response)) + { + _target.send(responseEntry,false); + } + else + { + _queue.add(responseEntry); + } + } + catch (AMQException e) + { + e.printStackTrace(); + } + finally + { + releaseSendLock(); + } + } + + private class TargetChangeListener implements StateChangeListener<ConsumerTarget, ConsumerTarget.State> + { + @Override + public void stateChanged(final ConsumerTarget object, + final ConsumerTarget.State oldState, + final ConsumerTarget.State newState) + { + if(newState == ConsumerTarget.State.ACTIVE) + { + deliverMessages(); + } + } + } + + private void deliverMessages() + { + getSendLock(); + try + { + while(!_queue.isEmpty()) + { + + final ManagementResponse managementResponse = _queue.get(0); + if(!_target.isSuspended() && _target.allocateCredit(managementResponse.getMessage())) + { + _queue.remove(0); + _target.send(managementResponse,false); + } + else + { + break; + } + } + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + finally + { + releaseSendLock(); + } + } +} diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeCreator.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeCreator.java new file mode 100644 index 0000000000..cdb71f4859 --- /dev/null +++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeCreator.java @@ -0,0 +1,39 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.amqp; + +import org.apache.qpid.server.plugin.SystemNodeCreator; + +public class ManagementNodeCreator implements SystemNodeCreator +{ + @Override + public void register(final SystemNodeRegistry registry) + { + ManagementNode managementNode = new ManagementNode(registry,registry.getVirtualHostModel()); + registry.registerSystemNode(managementNode); + } + + @Override + public String getType() + { + return "AMQP-VIRTUALHOST-MANAGEMENT"; + } +} diff --git a/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java new file mode 100644 index 0000000000..e25f327420 --- /dev/null +++ b/qpid/java/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java @@ -0,0 +1,220 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.amqp; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.consumer.Consumer; +import org.apache.qpid.server.filter.Filterable; +import org.apache.qpid.server.message.InstanceProperties; +import org.apache.qpid.server.message.MessageInstance; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.message.internal.InternalMessage; +import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.server.txn.ServerTransaction; +import org.apache.qpid.server.util.Action; +import org.apache.qpid.server.util.StateChangeListener; + +class ManagementResponse implements MessageInstance<ManagementResponse,ManagementNodeConsumer> +{ + private final ManagementNodeConsumer _consumer; + private int _deliveryCount; + private boolean _isRedelivered; + private boolean _isDelivered; + private boolean _isDeleted; + private InternalMessage _message; + + ManagementResponse(final ManagementNodeConsumer consumer, final InternalMessage message) + { + _consumer = consumer; + _message = message; + } + + @Override + public int getDeliveryCount() + { + return 0; + } + + @Override + public void incrementDeliveryCount() + { + _deliveryCount++; + } + + @Override + public void decrementDeliveryCount() + { + _deliveryCount--; + } + + @Override + public void addStateChangeListener(final StateChangeListener<? super ManagementResponse, State> listener) + { + + } + + @Override + public boolean removeStateChangeListener(final StateChangeListener<? super ManagementResponse, State> listener) + { + return false; + } + + + @Override + public boolean acquiredByConsumer() + { + return !isDeleted(); + } + + @Override + public boolean isAcquiredBy(final ManagementNodeConsumer consumer) + { + return consumer == _consumer && !isDeleted(); + } + + @Override + public void setRedelivered() + { + _isRedelivered = true; + } + + @Override + public boolean isRedelivered() + { + return _isRedelivered; + } + + @Override + public ManagementNodeConsumer getDeliveredConsumer() + { + return isDeleted() ? null : _consumer; + } + + @Override + public void reject() + { + delete(); + } + + @Override + public boolean isRejectedBy(final ManagementNodeConsumer consumer) + { + return false; + } + + @Override + public boolean getDeliveredToConsumer() + { + return _isDelivered; + } + + @Override + public boolean expired() throws AMQException + { + return false; + } + + @Override + public boolean acquire(final ManagementNodeConsumer sub) + { + return false; + } + + @Override + public int getMaximumDeliveryCount() + { + return 0; + } + + @Override + public int routeToAlternate(final Action<? super MessageInstance<?, ? extends Consumer>> action, + final ServerTransaction txn) + { + return 0; + } + + + @Override + public Filterable asFilterable() + { + return null; + } + + @Override + public boolean isAvailable() + { + return false; + } + + @Override + public boolean acquire() + { + return false; + } + + @Override + public boolean isAcquired() + { + return !isDeleted(); + } + + @Override + public void release() + { + delete(); + } + + @Override + public boolean resend() throws AMQException + { + return false; + } + + @Override + public void delete() + { + // TODO + } + + @Override + public boolean isDeleted() + { + return _isDeleted; + } + + @Override + public ServerMessage getMessage() + { + return _message; + } + + @Override + public InstanceProperties getInstanceProperties() + { + return InstanceProperties.EMPTY; + } + + @Override + public TransactionLogResource getOwningResource() + { + return _consumer.getManagementNode(); + } +} diff --git a/qpid/java/broker-plugins/management-amqp/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.SystemNodeCreator b/qpid/java/broker-plugins/management-amqp/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.SystemNodeCreator new file mode 100644 index 0000000000..767f93782b --- /dev/null +++ b/qpid/java/broker-plugins/management-amqp/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.SystemNodeCreator @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.management.amqp.ManagementNodeCreator diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java index 4d85d52997..0329379713 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java @@ -19,9 +19,6 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html index 9a24e23407..410a5d23ca 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addQueue.html @@ -35,16 +35,16 @@ <tr> <td valign="top"><strong>Queue Type: </strong></td> <td> - <input type="radio" id="formAddQueueTypeStandard" name="type" value="standard" checked="checked" dojoType="dijit.form.RadioButton" /> + <input type="radio" id="formAddQueueTypeStandard" name="queueType" value="standard" checked="checked" dojoType="dijit.form.RadioButton" /> <label for="formAddQueueTypeStandard">Standard</label> - <input type="radio" id="formAddQueueTypePriority" name="type" value="priority" dojoType="dijit.form.RadioButton" /> + <input type="radio" id="formAddQueueTypePriority" name="queueType" value="priority" dojoType="dijit.form.RadioButton" /> <label for="formAddQueueTypePriority">Priority</label> - <input type="radio" id="formAddQueueTypeLVQ" name="type" value="lvq" dojoType="dijit.form.RadioButton" /> + <input type="radio" id="formAddQueueTypeLVQ" name="queueType" value="lvq" dojoType="dijit.form.RadioButton" /> <label for="formAddQueueTypeLVQ">LVQ</label> - <input type="radio" id="formAddQueueTypeSorted" name="type" value="sorted" dojoType="dijit.form.RadioButton" /> + <input type="radio" id="formAddQueueTypeSorted" name="queueType" value="sorted" dojoType="dijit.form.RadioButton" /> <label for="formAddQueueTypeSorted">Sorted</label> </td> </tr> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js index 54cfe225c8..606f95e349 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js @@ -277,7 +277,7 @@ define(["dojo/_base/xhr", "exclusive", "owner", "lifetimePolicy", - "type", + "queueType", "typeQualifier", "alertRepeatGap", "alertRepeatGapUnits", @@ -359,14 +359,14 @@ define(["dojo/_base/xhr", bytesDepth = formatter.formatBytes( this.queueData["unacknowledgedBytes"] ); this.unacknowledgedBytes.innerHTML = "(" + bytesDepth.value; this.unacknowledgedBytesUnits.innerHTML = bytesDepth.units + ")"; - this.type.innerHTML = entities.encode(this.queueData[ "type" ]); - if (this.queueData.type == "standard") + this.queueType.innerHTML = entities.encode(this.queueData[ "queueType" ]); + if (this.queueData.queueType == "standard") { this.typeQualifier.style.display = "none"; } else { - this.typeQualifier.innerHTML = entities.encode("(" + queueTypeKeyNames[this.queueData.type] + ": " + this.queueData[queueTypeKeys[this.queueData.type]] + ")"); + this.typeQualifier.innerHTML = entities.encode("(" + queueTypeKeyNames[this.queueData.queueType] + ": " + this.queueData[queueTypeKeys[this.queueData.queueType]] + ")"); } if(this.queueData["messageGroupKey"]) diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js index e8b8dd1721..64e821b2dd 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js @@ -96,7 +96,7 @@ define(["dojo/_base/xhr", } } else if (!typeSpecificFields.hasOwnProperty(propName) || - formValues.type === typeSpecificFields[ propName ]) { + formValues.queueType === typeSpecificFields[ propName ]) { if(formValues[ propName ] !== "") { if (fieldConverters.hasOwnProperty(propName)) { @@ -130,7 +130,7 @@ define(["dojo/_base/xhr", theForm = registry.byId("formAddQueue"); array.forEach(theForm.getDescendants(), function(widget) { - if(widget.name === "type") { + if(widget.name === "queueType") { widget.on("change", function(isChecked) { var objId = widget.id + ":fields"; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html index 89b7327957..252deb3100 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html @@ -47,7 +47,7 @@ <div style="clear:both"> <div class="formLabel-labelCell" style="float:left; width: 150px;">Type:</div> <div style="float:left;"> - <span class="type"></span> + <span class="queueType"></span> <span class="typeQualifier"></span> </div> </div> diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java index 49cb6aa8cb..d74aa41244 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/QueueMBean.java @@ -183,7 +183,7 @@ public class QueueMBean extends AMQManagedObject implements ManagedQueue, QueueN @Override public String getQueueType() { - return (String) _queue.getAttribute(Queue.TYPE); + return (String) _queue.getAttribute(Queue.QUEUE_TYPE); } public boolean isDurable() diff --git a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java index 3711a90f3b..f94c206512 100644 --- a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java +++ b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/QueueMBeanTest.java @@ -127,7 +127,7 @@ public class QueueMBeanTest extends QpidTestCase public void testQueueType() throws Exception { - assertAttribute("queueType", QUEUE_TYPE, Queue.TYPE); + assertAttribute("queueType", QUEUE_TYPE, Queue.QUEUE_TYPE); } public void testMaximumDeliveryCount() throws Exception diff --git a/qpid/java/build.deps b/qpid/java/build.deps index 4dc5b0ca46..0aa35954bf 100644 --- a/qpid/java/build.deps +++ b/qpid/java/build.deps @@ -103,6 +103,7 @@ perftests.test.libs=${test.libs} qpid-test-utils.libs = ${test.libs} ${geronimo-jms} broker-plugins-access-control.test.libs=${test.libs} +broker-plugins-management-amqp.test.libs=${test.libs} broker-plugins-management-http.test.libs=${test.libs} broker-plugins-management-jmx.test.libs=${test.libs} broker-plugins-jdbc-store.test.libs=${test.libs} diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java index b408ad8ad1..b5a4166b55 100644 --- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java +++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java @@ -64,7 +64,7 @@ public class FieldTableKeyEnumeratorTest extends TestCase } - public void testPropertEnu() + public void testPropertyEnum() { try { diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java index 60dac24cfc..fe8c94cee1 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java @@ -30,8 +30,8 @@ import java.io.IOException; public class BasicContentHeaderProperties { //persistent & non-persistent constants, values as per JMS DeliveryMode - public static final int NON_PERSISTENT = 1; - public static final int PERSISTENT = 2; + public static final byte NON_PERSISTENT = 1; + public static final byte PERSISTENT = 2; private static final Logger _logger = LoggerFactory.getLogger(BasicContentHeaderProperties.class); diff --git a/qpid/java/ivy.nexus.xml b/qpid/java/ivy.nexus.xml index 55b2d2d729..8683062288 100644 --- a/qpid/java/ivy.nexus.xml +++ b/qpid/java/ivy.nexus.xml @@ -51,6 +51,12 @@ <artifact name="qpid-broker-plugins-access-control" type="jar.asc" ext="jar.asc"/> <artifact name="qpid-broker-plugins-access-control" type="source" ext="jar" e:classifier="sources"/> <artifact name="qpid-broker-plugins-access-control" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-management-amqp" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-management-amqp" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-management-amqp" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-management-amqp" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-management-amqp" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-management-amqp" type="source.asc" ext="jar.asc" e:classifier="sources"/> <artifact name="qpid-broker-plugins-management-http" type="pom" ext="pom"/> <artifact name="qpid-broker-plugins-management-http" type="pom.asc" ext="pom.asc"/> <artifact name="qpid-broker-plugins-management-http" type="jar" ext="jar"/> diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml index 3eb4cfb8c0..3a5c9fd2e8 100644 --- a/qpid/java/pom.xml +++ b/qpid/java/pom.xml @@ -173,6 +173,7 @@ <module>broker-plugins/derby-store</module> <module>broker-plugins/jdbc-provider-bone</module> <module>broker-plugins/jdbc-store</module> + <module>broker-plugins/management-amqp</module> <module>broker-plugins/management-http</module> <module>broker-plugins/management-jmx</module> <module>broker-plugins/memory-store</module> diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java index f92a133919..de36c6e413 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java @@ -47,11 +47,10 @@ import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.plugin.ExchangeType; -import org.apache.qpid.server.queue.AMQPriorityQueue; +import org.apache.qpid.server.queue.PriorityQueue; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.ConflationQueue; -import org.apache.qpid.server.queue.SimpleAMQQueue; +import org.apache.qpid.server.queue.StandardQueue; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.BrokerTestHelper; @@ -573,9 +572,9 @@ public class MessageStoreTest extends QpidTestCase if (usePriority) { - assertEquals("Queue is no longer a Priority Queue", AMQPriorityQueue.class, queue.getClass()); + assertEquals("Queue is no longer a Priority Queue", PriorityQueue.class, queue.getClass()); assertEquals("Priority Queue does not have set priorities", - DEFAULT_PRIORTY_LEVEL, ((AMQPriorityQueue) queue).getPriorities()); + DEFAULT_PRIORTY_LEVEL, ((PriorityQueue) queue).getPriorities()); } else if (lastValueQueue) { @@ -584,7 +583,7 @@ public class MessageStoreTest extends QpidTestCase } else { - assertEquals("Queue is not 'simple'", SimpleAMQQueue.class, queue.getClass()); + assertEquals("Queue is not 'simple'", StandardQueue.class, queue.getClass()); } assertEquals("Queue owner is not as expected", queueOwner, queue.getOwner()); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java index 2d6943f643..3c15a45203 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java @@ -26,11 +26,9 @@ import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.management.common.mbeans.ManagedBroker; import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.NotificationCheckTest; import org.apache.qpid.server.queue.QueueArgumentsConverter; -import org.apache.qpid.server.queue.SimpleAMQQueue; -import org.apache.qpid.server.queue.SimpleAMQQueueTest; +import org.apache.qpid.server.queue.StandardQueue; import org.apache.qpid.test.client.destination.AddressBasedDestinationTest; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; @@ -661,7 +659,7 @@ public class QueueManagementTest extends QpidBrokerTestCase final Object messageGroupKey = "test"; final Map<String, Object> arguments = new HashMap<String, Object>(2); arguments.put(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY, messageGroupKey); - arguments.put(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP, SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE); + arguments.put(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP, StandardQueue.SHARED_MSG_GROUP_ARG_VALUE); managedBroker.createNewQueue(queueName, null, true, arguments); final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java index 56aec08d09..9028130c18 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java @@ -97,7 +97,7 @@ public class Asserts assertEquals("Unexpected value of queue attribute " + Queue.STATE, State.ACTIVE.name(), queueData.get(Queue.STATE)); assertEquals("Unexpected value of queue attribute " + Queue.LIFETIME_POLICY, LifetimePolicy.PERMANENT.name(), queueData.get(Queue.LIFETIME_POLICY)); - assertEquals("Unexpected value of queue attribute " + Queue.TYPE, queueType, queueData.get(Queue.TYPE)); + assertEquals("Unexpected value of queue attribute " + Queue.QUEUE_TYPE, queueType, queueData.get(Queue.QUEUE_TYPE)); if (expectedAttributes == null) { assertEquals("Unexpected value of queue attribute " + Queue.EXCLUSIVE, Boolean.FALSE, queueData.get(Queue.EXCLUSIVE)); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java index 969f222316..96ca0c2def 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java @@ -37,7 +37,6 @@ import org.apache.qpid.server.model.Exchange; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; import org.apache.qpid.test.utils.TestFileUtils; import org.apache.qpid.util.FileUtils; @@ -527,7 +526,7 @@ public class VirtualHostRestTest extends QpidRestTestCase queueData.put(Queue.DURABLE, Boolean.TRUE); if (queueType != null) { - queueData.put(Queue.TYPE, queueType); + queueData.put(Queue.QUEUE_TYPE, queueType); } if (attributes != null) { |