merge up to r1765852 from trunk
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBCacheSizeSetter.java b/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBCacheSizeSetter.java
index 394d498..3c25474 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBCacheSizeSetter.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBCacheSizeSetter.java
@@ -28,14 +28,14 @@
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.NoopConfigurationChangeListener;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
import org.apache.qpid.server.virtualhost.berkeleydb.BDBVirtualHost;
-public class BDBCacheSizeSetter extends NoopConfigurationChangeListener
+public class BDBCacheSizeSetter extends AbstractConfigurationChangeListener
{
private static final Logger LOGGER = LoggerFactory.getLogger(BDBCacheSizeSetter.class);
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java
index 957fee6..ed0d367 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java
@@ -45,6 +45,7 @@
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.RemoteHostAddress;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.server.model.port.AmqpPort;
@@ -53,8 +54,10 @@
import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.transfer.TransferQueue;
import org.apache.qpid.server.transport.AMQPConnection;
import org.apache.qpid.server.txn.DtxRegistry;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.HouseKeepingTask;
import org.apache.qpid.server.virtualhost.NodeAutoCreationPolicy;
import org.apache.qpid.server.virtualhost.VirtualHostPrincipal;
@@ -511,6 +514,12 @@
}
@Override
+ public TransferQueue getTransferQueue()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public Principal getPrincipal()
{
return _principal;
@@ -541,6 +550,13 @@
}
@Override
+ public boolean makeConnection(final RemoteHostAddress<?> address, final Action<Boolean> onConnectionLoss)
+ {
+ throwUnsupportedForReplica();
+ return false;
+ }
+
+ @Override
public UserPreferences createUserPreferences(final ConfiguredObject<?> object)
{
throwUnsupportedForReplica();
diff --git a/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java b/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
index be5ef9a..48b14e0 100644
--- a/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
+++ b/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
@@ -45,6 +45,7 @@
import org.slf4j.LoggerFactory;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.RemoteReplicationNode;
@@ -269,7 +270,7 @@
final AtomicReference<RemoteReplicationNode<?>> lastSeenReplica = new AtomicReference<>();
final CountDownLatch remoteNodeLatch = new CountDownLatch(2);
- node1.addChangeListener(new NoopConfigurationChangeListener()
+ node1.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child)
@@ -557,7 +558,7 @@
Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, nodePortNumber);
BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(node1Attributes);
final CountDownLatch stopLatch = new CountDownLatch(1);
- ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
+ ConfigurationChangeListener listener = new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
@@ -578,7 +579,7 @@
final CountDownLatch stateChangeLatch = new CountDownLatch(1);
final CountDownLatch roleChangeLatch = new CountDownLatch(1);
- node.addChangeListener(new NoopConfigurationChangeListener()
+ node.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
@@ -637,7 +638,7 @@
BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(nodeAttributes);
final CountDownLatch stopLatch = new CountDownLatch(1);
- ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
+ ConfigurationChangeListener listener = new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
@@ -666,7 +667,7 @@
final CountDownLatch stateChangeLatch = new CountDownLatch(1);
final CountDownLatch roleChangeLatch = new CountDownLatch(1);
- node.addChangeListener(new NoopConfigurationChangeListener()
+ node.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
@@ -719,7 +720,7 @@
final AtomicInteger permittedNodesChangeCounter = new AtomicInteger();
final CountDownLatch _permittedNodesLatch = new CountDownLatch(1);
- node2.addChangeListener(new NoopConfigurationChangeListener()
+ node2.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
@@ -776,7 +777,7 @@
BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes);
final CountDownLatch stopLatch = new CountDownLatch(1);
- ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
+ ConfigurationChangeListener listener = new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
diff --git a/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java b/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java
deleted file mode 100644
index d157204..0000000
--- a/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/NoopConfigurationChangeListener.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.store.berkeleydb;
-
-import org.apache.qpid.server.model.ConfigurationChangeListener;
-import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.State;
-
-public class NoopConfigurationChangeListener implements ConfigurationChangeListener
-{
-
- public NoopConfigurationChangeListener() {
- }
-
- @Override
- public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
- {
- }
-
- @Override
- public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child)
- {
- }
-
- @Override
- public void childRemoved(ConfiguredObject<?> object, ConfiguredObject<?> child)
- {
- }
-
- @Override
- public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue,
- Object newAttributeValue)
- {
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
-}
diff --git a/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java b/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
index 2d94df1..207b720 100644
--- a/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
+++ b/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
@@ -20,7 +20,11 @@
*/
package org.apache.qpid.server.virtualhostnode.berkeleydb;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.argThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import java.util.Collections;
import java.util.EnumSet;
@@ -28,17 +32,18 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import org.hamcrest.Description;
+import org.mockito.ArgumentMatcher;
+
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogMessage;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.messages.HighAvailabilityMessages;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.SystemConfig;
-import org.apache.qpid.server.store.berkeleydb.NoopConfigurationChangeListener;
import org.apache.qpid.test.utils.PortHelper;
import org.apache.qpid.test.utils.QpidTestCase;
-import org.hamcrest.Description;
-import org.mockito.ArgumentMatcher;
/**
* Class to test that specific VHN operations result in the expected Operational Log message(s) being performed.
@@ -264,7 +269,7 @@
BDBHAVirtualHostNodeImpl node1 = (BDBHAVirtualHostNodeImpl)_helper.createHaVHN(node1Attributes);
final CountDownLatch remoteNodeAdded = new CountDownLatch(1);
- node1.addChangeListener(new NoopConfigurationChangeListener()
+ node1.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void childAdded(ConfiguredObject<?> object, ConfiguredObject<?> child)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java b/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java
index b936b52..b21f948 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/consumer/AbstractConsumerTarget.java
@@ -38,6 +38,7 @@
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.messages.SubscriptionMessages;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.model.Consumer;
import org.apache.qpid.server.queue.SuspendedConsumerLoggingTicker;
import org.apache.qpid.server.transport.AMQPConnection;
@@ -57,10 +58,10 @@
private final boolean _isMultiQueue;
private final SuspendedConsumerLoggingTicker _suspendedConsumerLoggingTicker;
private ConcurrentLinkedQueue<ConsumerMessageInstancePair> _queue = new ConcurrentLinkedQueue();
- private final List<ConsumerImpl> _consumers = new CopyOnWriteArrayList<>();
+ private final List<MessageInstanceConsumer> _consumers = new CopyOnWriteArrayList<>();
private final boolean _isPullOnly;
- private Iterator<ConsumerImpl> _pullIterator;
+ private Iterator<MessageInstanceConsumer> _pullIterator;
protected AbstractConsumerTarget(final State initialState,
@@ -123,13 +124,13 @@
protected abstract void processClosed();
@Override
- public void consumerAdded(final ConsumerImpl sub)
+ public void consumerAdded(final MessageInstanceConsumer sub)
{
_consumers.add(sub);
}
@Override
- public void consumerRemoved(final ConsumerImpl sub)
+ public void consumerRemoved(final MessageInstanceConsumer sub)
{
_consumers.remove(sub);
if(_consumers.isEmpty())
@@ -138,7 +139,7 @@
}
}
- public List<ConsumerImpl> getConsumers()
+ public List<MessageInstanceConsumer> getConsumers()
{
return _consumers;
}
@@ -246,6 +247,11 @@
_stateChangeListeners.remove(listener);
}
+ public boolean isPullOnly()
+ {
+ return _isPullOnly;
+ }
+
public final boolean trySendLock()
{
return _stateChangeLock.tryLock();
@@ -262,13 +268,7 @@
}
@Override
- public boolean isPullOnly()
- {
- return _isPullOnly;
- }
-
- @Override
- public final long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+ public final long send(final MessageInstanceConsumer consumer, MessageInstance entry, boolean batch)
{
AMQPConnection<?> amqpConnection = getSessionModel().getAMQPConnection();
amqpConnection.reserveOutboundMessageSpace(entry.getMessage().getSize());
@@ -277,7 +277,7 @@
return entry.getMessage().getSize();
}
- protected abstract void doSend(final ConsumerImpl consumer, MessageInstance entry, boolean batch);
+ protected abstract void doSend(final MessageInstanceConsumer consumer, MessageInstance entry, boolean batch);
@Override
public boolean hasMessagesToSend()
@@ -289,7 +289,7 @@
{
if(hasCredit())
{
- for (ConsumerImpl consumer : _consumers)
+ for (MessageInstanceConsumer consumer : _consumers)
{
if (consumer.hasAvailableMessages())
{
@@ -311,7 +311,7 @@
}
if(_pullIterator.hasNext())
{
- ConsumerImpl consumer = _pullIterator.next();
+ MessageInstanceConsumer consumer = _pullIterator.next();
consumer.pullMessage();
}
}
@@ -321,7 +321,7 @@
try
{
- ConsumerImpl consumer = consumerMessage.getConsumer();
+ MessageInstanceConsumer consumer = consumerMessage.getConsumer();
MessageInstance entry = consumerMessage.getEntry();
boolean batch = consumerMessage.isBatch();
doSend(consumer, entry, batch);
@@ -375,7 +375,7 @@
releaseSendLock();
}
- for (ConsumerImpl consumer : _consumers)
+ for (MessageInstanceConsumer consumer : _consumers)
{
consumer.close();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerImpl.java b/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerImpl.java
deleted file mode 100644
index cf91f75..0000000
--- a/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerImpl.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
- */
-package org.apache.qpid.server.consumer;
-
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.apache.qpid.server.message.MessageSource;
-import org.apache.qpid.server.protocol.AMQSessionModel;
-
-public interface ConsumerImpl
-{
- AtomicLong CONSUMER_NUMBER_GENERATOR = new AtomicLong(0);
-
- void externalStateChange();
-
- ConsumerTarget getTarget();
-
- boolean hasAvailableMessages();
-
- void pullMessage();
-
- enum Option
- {
- ACQUIRES,
- SEES_REQUEUES,
- TRANSIENT,
- EXCLUSIVE,
- NO_LOCAL,
- DURABLE
- }
-
- long getBytesOut();
-
- long getMessagesOut();
-
- long getUnacknowledgedBytes();
-
- long getUnacknowledgedMessages();
-
- AMQSessionModel getSessionModel();
-
- MessageSource getMessageSource();
-
- long getConsumerNumber();
-
- boolean isSuspended();
-
- boolean isClosed();
-
- boolean acquires();
-
- boolean seesRequeues();
-
- void close();
-
- boolean trySendLock();
-
-
- void getSendLock();
-
- void releaseSendLock();
-
- boolean isActive();
-
- String getName();
-
- void flush();
-}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerMessageInstancePair.java b/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerMessageInstancePair.java
index 9b5f9c9..ad85529 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerMessageInstancePair.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerMessageInstancePair.java
@@ -20,16 +20,17 @@
package org.apache.qpid.server.consumer;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.MessageReference;
public class ConsumerMessageInstancePair
{
- private final ConsumerImpl _consumer;
+ private final MessageInstanceConsumer _consumer;
private final MessageInstance _entry;
private final boolean _batch;
private final MessageReference _reference;
- public ConsumerMessageInstancePair(final ConsumerImpl consumer, final MessageInstance entry, final boolean batch)
+ public ConsumerMessageInstancePair(final MessageInstanceConsumer consumer, final MessageInstance entry, final boolean batch)
{
_consumer = consumer;
_entry = entry;
@@ -38,7 +39,7 @@
}
- public ConsumerImpl getConsumer()
+ public MessageInstanceConsumer getConsumer()
{
return _consumer;
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java b/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java
index 7b9ac65..9d76a39 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/consumer/ConsumerTarget.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.consumer;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.util.StateChangeListener;
@@ -50,9 +51,9 @@
State getState();
- void consumerAdded(ConsumerImpl sub);
+ void consumerAdded(MessageInstanceConsumer consumer);
- void consumerRemoved(ConsumerImpl sub);
+ void consumerRemoved(MessageInstanceConsumer consumer);
void notifyCurrentState();
@@ -64,7 +65,7 @@
AMQSessionModel getSessionModel();
- long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch);
+ long send(final MessageInstanceConsumer consumer, MessageInstance entry, boolean batch);
boolean hasMessagesToSend();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index 879ea17..8169b94 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -50,8 +50,8 @@
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.logging.subjects.ExchangeLogSubject;
+import org.apache.qpid.server.message.BaseMessageInstance;
import org.apache.qpid.server.message.InstanceProperties;
-import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.AbstractConfiguredObject;
@@ -446,7 +446,7 @@
final String routingAddress,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final Action<? super MessageInstance> postEnqueueAction)
+ final Action<? super BaseMessageInstance> postEnqueueAction)
{
if (_virtualHost.getState() != State.ACTIVE)
{
diff --git a/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultDestination.java b/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultDestination.java
index 9e8ba67..71e1ec9 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultDestination.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultDestination.java
@@ -22,9 +22,9 @@
import java.util.Map;
import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.server.message.BaseMessageInstance;
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.ServerMessage;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Exchange;
@@ -96,13 +96,13 @@
String routingAddress,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final Action<? super MessageInstance> postEnqueueAction)
+ final Action<? super BaseMessageInstance> postEnqueueAction)
{
if(routingAddress == null || routingAddress.trim().equals(""))
{
return 0;
}
- final MessageDestination dest = _virtualHost.getAttainedMessageDestination(routingAddress);
+ MessageDestination dest = _virtualHost.getAttainedMessageDestination(routingAddress);
if(dest == null)
{
routingAddress = _virtualHost.getLocalAddress(routingAddress);
@@ -117,10 +117,10 @@
}
else if(!routingAddress.contains("/"))
{
- Exchange<?> exchange = _virtualHost.getAttainedChildFromAddress(Exchange.class, routingAddress);
- if(exchange != null)
+ dest = _virtualHost.getAttainedMessageDestination(routingAddress);
+ if(dest != null)
{
- return exchange.send(message, "", instanceProperties, txn, postEnqueueAction);
+ return dest.send(message, dest instanceof Exchange ? "" : routingAddress, instanceProperties, txn, postEnqueueAction);
}
}
return 0;
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/federation/OutboundProtocolEngine.java
similarity index 67%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/federation/OutboundProtocolEngine.java
index d2aff53..0397040 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/federation/OutboundProtocolEngine.java
@@ -18,8 +18,15 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.federation;
-public interface QueueEntryListBase extends QueueEntryList
+import org.apache.qpid.server.transport.ProtocolEngine;
+import org.apache.qpid.server.transport.SchedulableConnection;
+import org.apache.qpid.server.util.Action;
+
+public interface OutboundProtocolEngine extends ProtocolEngine
{
+ void setConnection(SchedulableConnection connection);
+
+ void setOnClosedTask(Action<Boolean> onConnectionLoss);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/federation/RemoteHostAddressImpl.java b/broker-core/src/main/java/org/apache/qpid/server/federation/RemoteHostAddressImpl.java
new file mode 100644
index 0000000..a437d73
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/federation/RemoteHostAddressImpl.java
@@ -0,0 +1,179 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.apache.qpid.configuration.CommonProperties;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.KeyStore;
+import org.apache.qpid.server.model.ManagedAttributeField;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.RemoteHost;
+import org.apache.qpid.server.model.RemoteHostAddress;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+import org.apache.qpid.server.model.Transport;
+import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.server.util.ParameterizedTypes;
+
+@ManagedObject( category = false, type = RemoteHostAddress.REMOTE_HOST_ADDRESS_TYPE )
+class RemoteHostAddressImpl extends AbstractConfiguredObject<RemoteHostAddressImpl> implements RemoteHostAddress<RemoteHostAddressImpl>
+{
+ @ManagedAttributeField
+ private String _address;
+ @ManagedAttributeField
+ private int _port;
+ @ManagedAttributeField
+ private String _hostName;
+ @ManagedAttributeField
+ private Protocol _protocol;
+ @ManagedAttributeField
+ private Transport _transport;
+ @ManagedAttributeField
+ private KeyStore _keyStore;
+ @ManagedAttributeField
+ private Collection<TrustStore> _trustStores;
+ @ManagedAttributeField
+ private int _desiredHeartbeatInterval;
+
+ private List<String> _tlsProtocolBlackList;
+ private List<String> _tlsProtocolWhiteList;
+
+ private List<String> _tlsCipherSuiteWhiteList;
+ private List<String> _tlsCipherSuiteBlackList;
+
+
+ @ManagedObjectFactoryConstructor
+ public RemoteHostAddressImpl(Map<String, Object> attributes, RemoteHost<?> remoteHost)
+ {
+ super(parentsMap(remoteHost), attributes);
+ }
+
+
+ @Override
+ protected void onOpen()
+ {
+ super.onOpen();
+ _tlsProtocolWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_WHITE_LIST);
+ _tlsProtocolBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_PROTOCOL_BLACK_LIST);
+ _tlsCipherSuiteWhiteList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_WHITE_LIST);
+ _tlsCipherSuiteBlackList = getContextValue(List.class, ParameterizedTypes.LIST_OF_STRINGS, CommonProperties.QPID_SECURITY_TLS_CIPHER_SUITE_BLACK_LIST);
+ }
+
+
+ @Override
+ public String getAddress()
+ {
+ return _address;
+ }
+
+ @Override
+ public int getPort()
+ {
+ return _port;
+ }
+
+ @Override
+ public String getHostName()
+ {
+ return _hostName;
+ }
+
+ @Override
+ public Protocol getProtocol()
+ {
+ return _protocol;
+ }
+
+ @Override
+ public Transport getTransport()
+ {
+ return _transport;
+ }
+
+ @Override
+ public KeyStore getKeyStore()
+ {
+ return _keyStore;
+ }
+
+ @Override
+ public Collection<TrustStore> getTrustStores()
+ {
+ return _trustStores;
+ }
+
+ @Override
+ public int getDesiredHeartbeatInterval()
+ {
+ return _desiredHeartbeatInterval;
+ }
+
+ @Override
+ public List<String> getTlsProtocolWhiteList()
+ {
+ return _tlsProtocolWhiteList;
+ }
+
+ @Override
+ public List<String> getTlsProtocolBlackList()
+ {
+ return _tlsProtocolBlackList;
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteWhiteList()
+ {
+ return _tlsCipherSuiteWhiteList;
+ }
+
+ @Override
+ public List<String> getTlsCipherSuiteBlackList()
+ {
+ return _tlsCipherSuiteBlackList;
+ }
+
+ @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE )
+ protected ListenableFuture<Void> activate()
+ {
+ try
+ {
+ setState(State.ACTIVE);
+ }
+ catch (RuntimeException e)
+ {
+ setState(State.ERRORED);
+ throw new IllegalConfigurationException("Unable to active remote host address '" + getName() + "'", e);
+ }
+ return Futures.immediateFuture(null);
+ }
+
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/federation/RemoteHostImpl.java b/broker-core/src/main/java/org/apache/qpid/server/federation/RemoteHostImpl.java
new file mode 100644
index 0000000..cd369b9
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/federation/RemoteHostImpl.java
@@ -0,0 +1,233 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import java.security.AccessControlContext;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ManagedAttributeField;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.RemoteHost;
+import org.apache.qpid.server.model.RemoteHostAddress;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.virtualhost.HouseKeepingTask;
+
+@ManagedObject( category = false, type = RemoteHost.REMOTE_HOST_TYPE )
+class RemoteHostImpl extends AbstractConfiguredObject<RemoteHostImpl> implements RemoteHost<RemoteHostImpl>
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(RemoteHostImpl.class);
+
+ private final VirtualHost<?> _virtualHost;
+ @ManagedAttributeField
+ private int _retryPeriod;
+
+ @ManagedAttributeField
+ private boolean _redirectFollowed;
+
+ @ManagedAttributeField
+ private Collection<String> _routableAddresses;
+
+ private final AccessControlContext _createConnectionContext;
+ private final CreateConnectionTask _createConnectionTask;
+
+ enum ConnectionState
+ {
+ DISCONNECTED,
+ CONNECTING,
+ CONNECTED,
+ STOPPED
+ }
+
+ private ConnectionState _connectionState = ConnectionState.STOPPED;
+
+ @ManagedObjectFactoryConstructor
+ public RemoteHostImpl(Map<String, Object> attributes, VirtualHost<?> virtualHost)
+ {
+ super(parentsMap(virtualHost), attributes);
+ _virtualHost = virtualHost;
+ _createConnectionContext =
+ getSystemTaskControllerContext("Create connection " + getName(), _virtualHost.getPrincipal());
+ _createConnectionTask = new CreateConnectionTask();
+ }
+
+ @Override
+ public int getRetryPeriod()
+ {
+ return _retryPeriod;
+ }
+
+ @Override
+ public boolean isRedirectFollowed()
+ {
+ return _redirectFollowed;
+ }
+
+ @Override
+ public Collection<String> getRoutableAddresses()
+ {
+ return _routableAddresses;
+ }
+
+ @StateTransition(currentState = {State.UNINITIALIZED, State.ERRORED, State.STOPPED}, desiredState = State.ACTIVE)
+ private ListenableFuture<Void> onActivate()
+ {
+ setState(State.ACTIVE);
+ _failoverIterator = null;
+ if (_virtualHost.getState() == State.ACTIVE)
+ {
+ _createConnectionTask.scheduleNow();
+ }
+ else if (_virtualHost.getDesiredState() == State.ACTIVE)
+ {
+ _virtualHost.addChangeListener(new AbstractConfigurationChangeListener()
+ {
+ @Override
+ public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
+ {
+ if (newState == State.ACTIVE)
+ {
+
+ _createConnectionTask.scheduleNow();
+
+ _virtualHost.removeChangeListener(this);
+ }
+ else if (object.getDesiredState() != State.ACTIVE)
+ {
+ _virtualHost.removeChangeListener(this);
+ }
+ }
+ });
+ }
+ return Futures.immediateFuture(null);
+ }
+
+ private Iterator<RemoteHostAddress> _failoverIterator;
+
+
+ private void setConnectionState(ConnectionState connectionState)
+ {
+ _connectionState = connectionState;
+ }
+
+ private synchronized void makeConnection()
+ {
+ LOGGER.debug("makeConnection called with state: {}, connectionState: {}", getState(), _connectionState);
+ if(getState() == State.ACTIVE && !EnumSet.of(ConnectionState.CONNECTED, ConnectionState.CONNECTING).contains(_connectionState))
+ {
+ if (_failoverIterator == null || !_failoverIterator.hasNext())
+ {
+ _failoverIterator = getChildren(RemoteHostAddress.class).iterator();
+ }
+ if (_failoverIterator.hasNext())
+ {
+ RemoteHostAddress<?> address = _failoverIterator.next();
+ setConnectionState(ConnectionState.CONNECTING);
+ boolean connected = _virtualHost.makeConnection(address, new Action<Boolean>()
+ {
+
+ @Override
+ public void performAction(final Boolean wasConnected)
+ {
+ setConnectionState(ConnectionState.DISCONNECTED);
+ if (wasConnected)
+ {
+ _failoverIterator = null;
+ _createConnectionTask.scheduleNow();
+ }
+ else if (_failoverIterator.hasNext())
+ {
+ _createConnectionTask.scheduleNow();
+ }
+ else
+ {
+ _createConnectionTask.schedule(1000L * _retryPeriod);
+ }
+ }
+ });
+
+ if (connected)
+ {
+ setConnectionState(ConnectionState.CONNECTED);
+ }
+ else
+ {
+ setConnectionState(ConnectionState.DISCONNECTED);
+ if (_failoverIterator.hasNext())
+ {
+ _createConnectionTask.scheduleNow();
+ }
+ else
+ {
+ _createConnectionTask.schedule(1000L * _retryPeriod);
+ }
+ }
+ }
+ }
+
+ }
+
+ private class CreateConnectionTask extends HouseKeepingTask
+ {
+
+ private final AtomicBoolean _scheduled = new AtomicBoolean();
+
+ public CreateConnectionTask()
+ {
+ super("Create connection: " + RemoteHostImpl.this.getName(), _virtualHost, _createConnectionContext);
+ }
+
+ @Override
+ public void execute()
+ {
+ _scheduled.set(false);
+ makeConnection();
+ }
+
+ public void schedule(long delay)
+ {
+ if(_scheduled.compareAndSet(false, true))
+ {
+ _virtualHost.scheduleTask(delay, this);
+ }
+ }
+
+ public void scheduleNow()
+ {
+ schedule(0L);
+ }
+ }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/federation/UsernamePasswordCredentialImpl.java b/broker-core/src/main/java/org/apache/qpid/server/federation/UsernamePasswordCredentialImpl.java
new file mode 100644
index 0000000..ecf1f67
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/federation/UsernamePasswordCredentialImpl.java
@@ -0,0 +1,88 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.security.sasl.SaslClient;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.apache.qpid.server.federation.sasl.ScramSHA1SaslClient;
+import org.apache.qpid.server.federation.sasl.ScramSHA256SaslClient;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ManagedAttributeField;
+import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
+import org.apache.qpid.server.model.RemoteHost;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+import org.apache.qpid.server.model.UsernamePasswordCredential;
+
+class UsernamePasswordCredentialImpl extends AbstractConfiguredObject<UsernamePasswordCredentialImpl>
+ implements UsernamePasswordCredential<UsernamePasswordCredentialImpl>
+{
+ @ManagedAttributeField
+ private String _username;
+ @ManagedAttributeField
+ private String _password;
+
+ @ManagedObjectFactoryConstructor
+ UsernamePasswordCredentialImpl(Map<String, Object> attributes, RemoteHost<?> host)
+ {
+ super(parentsMap(host), attributes);
+ }
+
+ @Override
+ public SaslClient getSaslClient(final List<String> mechanisms)
+ {
+ if(mechanisms.contains(ScramSHA256SaslClient.MECHANISM))
+ {
+ return new ScramSHA256SaslClient(this);
+ }
+ else if(mechanisms.contains(ScramSHA1SaslClient.MECHANISM))
+ {
+ return new ScramSHA1SaslClient(this);
+ }
+ return null;
+ }
+
+ @Override
+ public String getUsername()
+ {
+ return _username;
+ }
+
+ @Override
+ public String getPassword()
+ {
+ return _password;
+ }
+
+ @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE )
+ protected ListenableFuture<Void> activate()
+ {
+ setState(State.ACTIVE);
+ return Futures.immediateFuture(null);
+ }
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/federation/sasl/AbstractScramSaslClient.java b/broker-core/src/main/java/org/apache/qpid/server/federation/sasl/AbstractScramSaslClient.java
new file mode 100644
index 0000000..ac7d9ef
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/federation/sasl/AbstractScramSaslClient.java
@@ -0,0 +1,323 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation.sasl;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.UUID;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+import javax.xml.bind.DatatypeConverter;
+
+import org.apache.qpid.server.model.UsernamePasswordCredential;
+
+public abstract class AbstractScramSaslClient implements SaslClient
+{
+
+ private static final byte[] INT_1 = new byte[]{0, 0, 0, 1};
+ private static final String GS2_HEADER = "n,,";
+ private static final Charset ASCII = Charset.forName("ASCII");
+
+ private final String _digestName;
+ private final String _hmacName;
+
+ private String _username;
+ private final String _clientNonce = UUID.randomUUID().toString();
+ private String _serverNonce;
+ private byte[] _salt;
+ private int _iterationCount;
+ private String _clientFirstMessageBare;
+ private byte[] _serverSignature;
+
+ enum State
+ {
+ INITIAL,
+ CLIENT_FIRST_SENT,
+ CLIENT_PROOF_SENT,
+ COMPLETE
+ }
+
+ public final String _mechanism;
+
+ private final UsernamePasswordCredential<?> _credentials;
+
+ private State _state = State.INITIAL;
+
+ public AbstractScramSaslClient(final UsernamePasswordCredential credentials,
+ final String mechanism,
+ final String digestName,
+ final String hmacName)
+ {
+ _mechanism = mechanism;
+ _digestName = digestName;
+ _hmacName = hmacName;
+ _credentials = credentials;
+
+ }
+
+ @Override
+ public String getMechanismName()
+ {
+ return _mechanism;
+ }
+
+ @Override
+ public boolean hasInitialResponse()
+ {
+ return true;
+ }
+
+ @Override
+ public byte[] evaluateChallenge(final byte[] challenge) throws SaslException
+ {
+ byte[] response;
+ switch(_state)
+ {
+ case INITIAL:
+ response = initialResponse();
+ _state = State.CLIENT_FIRST_SENT;
+ break;
+ case CLIENT_FIRST_SENT:
+ response = calculateClientProof(challenge);
+ _state = State.CLIENT_PROOF_SENT;
+ break;
+ case CLIENT_PROOF_SENT:
+ evaluateOutcome(challenge);
+ response = new byte[0];
+ _state = State.COMPLETE;
+ break;
+ default:
+ throw new SaslException("No challenge expected in state " + _state);
+ }
+ return response;
+ }
+
+ private void evaluateOutcome(final byte[] challenge) throws SaslException
+ {
+ String serverFinalMessage = new String(challenge, ASCII);
+ String[] parts = serverFinalMessage.split(",");
+ if(!parts[0].startsWith("v="))
+ {
+ throw new SaslException("Server final message did not contain verifier");
+ }
+ byte[] serverSignature = DatatypeConverter.parseBase64Binary(parts[0].substring(2));
+ if(!Arrays.equals(_serverSignature, serverSignature))
+ {
+ throw new SaslException("Server signature did not match");
+ }
+ }
+
+ private byte[] calculateClientProof(final byte[] challenge) throws SaslException
+ {
+ try
+ {
+ String serverFirstMessage = new String(challenge, ASCII);
+ String[] parts = serverFirstMessage.split(",");
+ if(parts.length < 3)
+ {
+ throw new SaslException("Server challenge '" + serverFirstMessage + "' cannot be parsed");
+ }
+ else if(parts[0].startsWith("m="))
+ {
+ throw new SaslException("Server requires mandatory extension which is not supported: " + parts[0]);
+ }
+ else if(!parts[0].startsWith("r="))
+ {
+ throw new SaslException("Server challenge '" + serverFirstMessage + "' cannot be parsed, cannot find nonce");
+ }
+ String nonce = parts[0].substring(2);
+ if(!nonce.startsWith(_clientNonce))
+ {
+ throw new SaslException("Server challenge did not use correct client nonce");
+ }
+ _serverNonce = nonce;
+ if(!parts[1].startsWith("s="))
+ {
+ throw new SaslException("Server challenge '" + serverFirstMessage + "' cannot be parsed, cannot find salt");
+ }
+ String base64Salt = parts[1].substring(2);
+ _salt = DatatypeConverter.parseBase64Binary(base64Salt);
+ if(!parts[2].startsWith("i="))
+ {
+ throw new SaslException("Server challenge '" + serverFirstMessage + "' cannot be parsed, cannot find iteration count");
+ }
+ String iterCountString = parts[2].substring(2);
+ _iterationCount = Integer.parseInt(iterCountString);
+ if(_iterationCount <= 0)
+ {
+ throw new SaslException("Iteration count " + _iterationCount + " is not a positive integer");
+ }
+ byte[] passwordBytes = saslPrep(_credentials.getPassword()).getBytes("UTF-8");
+
+ byte[] saltedPassword = generateSaltedPassword(passwordBytes);
+
+
+ String clientFinalMessageWithoutProof =
+ "c=" + DatatypeConverter.printBase64Binary(GS2_HEADER.getBytes(ASCII))
+ + ",r=" + _serverNonce;
+
+ String authMessage = _clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof;
+
+ byte[] clientKey = computeHmac(saltedPassword, "Client Key");
+ byte[] storedKey = MessageDigest.getInstance(_digestName).digest(clientKey);
+
+ byte[] clientSignature = computeHmac(storedKey, authMessage);
+
+ byte[] clientProof = clientKey.clone();
+ for(int i = 0 ; i < clientProof.length; i++)
+ {
+ clientProof[i] ^= clientSignature[i];
+ }
+ byte[] serverKey = computeHmac(saltedPassword, "Server Key");
+ _serverSignature = computeHmac(serverKey, authMessage);
+
+ String finalMessageWithProof = clientFinalMessageWithoutProof
+ + ",p=" + DatatypeConverter.printBase64Binary(clientProof);
+ return finalMessageWithProof.getBytes();
+ }
+ catch (IllegalArgumentException | NoSuchAlgorithmException | IOException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ }
+
+ private byte[] computeHmac(final byte[] key, final String string)
+ throws SaslException, UnsupportedEncodingException
+ {
+ Mac mac = createHmac(key);
+ mac.update(string.getBytes(ASCII));
+ return mac.doFinal();
+ }
+
+ private byte[] generateSaltedPassword(final byte[] passwordBytes) throws SaslException
+ {
+ Mac mac = createHmac(passwordBytes);
+
+ mac.update(_salt);
+ mac.update(INT_1);
+ byte[] result = mac.doFinal();
+
+ byte[] previous = null;
+ for(int i = 1; i < _iterationCount; i++)
+ {
+ mac.update(previous != null? previous: result);
+ previous = mac.doFinal();
+ for(int x = 0; x < result.length; x++)
+ {
+ result[x] ^= previous[x];
+ }
+ }
+
+ return result;
+ }
+
+ private Mac createHmac(final byte[] keyBytes)
+ throws SaslException
+ {
+ try
+ {
+ SecretKeySpec key = new SecretKeySpec(keyBytes, _hmacName);
+ Mac mac = Mac.getInstance(_hmacName);
+ mac.init(key);
+ return mac;
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ }
+
+
+ private byte[] initialResponse() throws SaslException
+ {
+ try
+ {
+ StringBuffer buf = new StringBuffer("n=");
+ _username = _credentials.getUsername();
+ buf.append(saslPrep(_username));
+ buf.append(",r=");
+ buf.append(_clientNonce);
+ _clientFirstMessageBare = buf.toString();
+ return (GS2_HEADER + _clientFirstMessageBare).getBytes(ASCII);
+ }
+ catch (IOException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ }
+
+ private String saslPrep(String name) throws SaslException
+ {
+ // TODO - a real implementation of SaslPrep
+
+ if(!ASCII.newEncoder().canEncode(name))
+ {
+ throw new SaslException("Can only encode names and passwords which are restricted to ASCII characters");
+ }
+
+ name = name.replace("=", "=3D");
+ name = name.replace(",", "=2C");
+ return name;
+ }
+
+ @Override
+ public boolean isComplete()
+ {
+ return _state == State.COMPLETE;
+ }
+
+ @Override
+ public byte[] unwrap(final byte[] incoming, final int offset, final int len) throws SaslException
+ {
+ throw new IllegalStateException("No security layer supported");
+ }
+
+ @Override
+ public byte[] wrap(final byte[] outgoing, final int offset, final int len) throws SaslException
+ {
+ throw new IllegalStateException("No security layer supported");
+ }
+
+ @Override
+ public Object getNegotiatedProperty(final String propName)
+ {
+ return null;
+ }
+
+ @Override
+ public void dispose() throws SaslException
+ {
+
+ }
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/federation/sasl/ScramSHA1SaslClient.java
similarity index 67%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/federation/sasl/ScramSHA1SaslClient.java
index d2aff53..8a2297d 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/federation/sasl/ScramSHA1SaslClient.java
@@ -18,8 +18,17 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.federation.sasl;
-public interface QueueEntryListBase extends QueueEntryList
+import org.apache.qpid.server.model.UsernamePasswordCredential;
+
+public class ScramSHA1SaslClient extends AbstractScramSaslClient
{
+
+ public static final String MECHANISM = "SCRAM-SHA-1";
+
+ public ScramSHA1SaslClient(final UsernamePasswordCredential<?> credentials)
+ {
+ super(credentials, MECHANISM, "SHA-1", "HmacSHA1");
+ }
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/federation/sasl/ScramSHA256SaslClient.java
similarity index 66%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/federation/sasl/ScramSHA256SaslClient.java
index d2aff53..40b4872 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/federation/sasl/ScramSHA256SaslClient.java
@@ -18,8 +18,17 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.federation.sasl;
-public interface QueueEntryListBase extends QueueEntryList
+import org.apache.qpid.server.model.UsernamePasswordCredential;
+
+public class ScramSHA256SaslClient extends AbstractScramSaslClient
{
+
+ public static final String MECHANISM = "SCRAM-SHA-256";
+
+ public ScramSHA256SaslClient(final UsernamePasswordCredential<?> credentials)
+ {
+ super(credentials, MECHANISM, "SHA-256", "HmacSHA256");
+ }
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java b/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java
index ba724d8..b570a6a 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/filter/FilterSupport.java
@@ -31,10 +31,9 @@
import org.apache.qpid.filter.SelectorParsingException;
import org.apache.qpid.filter.selector.ParseException;
import org.apache.qpid.filter.selector.TokenMgrError;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.plugin.PluggableService;
+import org.apache.qpid.server.queue.QueueConsumer;
public class FilterSupport
{
@@ -119,9 +118,9 @@
@PluggableService
public static final class NoLocalFilter implements MessageFilter
{
- private final MessageSource _queue;
+ private final Queue<?> _queue;
- private NoLocalFilter(MessageSource queue)
+ private NoLocalFilter(Queue<?> queue)
{
_queue = queue;
}
@@ -135,8 +134,8 @@
public boolean matches(Filterable message)
{
- final Collection<? extends ConsumerImpl> consumers = _queue.getConsumers();
- for(ConsumerImpl c : consumers)
+ final Collection<QueueConsumer<?>> consumers = _queue.getConsumers();
+ for(QueueConsumer<?> c : consumers)
{
if(c.getSessionModel().getConnectionReference() == message.getConnectionReference())
{
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java b/broker-core/src/main/java/org/apache/qpid/server/message/AcquiringMessageInstanceConsumer.java
similarity index 68%
copy from broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
copy to broker-core/src/main/java/org/apache/qpid/server/message/AcquiringMessageInstanceConsumer.java
index 7ca5c6d..1249127 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/AcquiringMessageInstanceConsumer.java
@@ -20,9 +20,17 @@
*/
package org.apache.qpid.server.message;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.queue.QueueEntry;
-public interface MessageSourceConsumer<X extends MessageSourceConsumer<X>> extends ConsumerImpl, Consumer<MessageSourceConsumer<X>>
+public interface AcquiringMessageInstanceConsumer<X extends AcquiringMessageInstanceConsumer<X, T>, T> extends MessageInstanceConsumer
{
+ MessageInstance.StealableConsumerAcquiredState<X> getOwningState();
+
+ T getTarget();
+
+ void acquisitionRemoved(QueueEntry queueEntry);
+
+ long getConsumerNumber();
+
+ boolean resend(QueueEntry queueEntry);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java b/broker-core/src/main/java/org/apache/qpid/server/message/BaseMessageInstance.java
similarity index 70%
copy from broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
copy to broker-core/src/main/java/org/apache/qpid/server/message/BaseMessageInstance.java
index 7ca5c6d..f9a9e74 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/BaseMessageInstance.java
@@ -20,9 +20,20 @@
*/
package org.apache.qpid.server.message;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.store.MessageEnqueueRecord;
+import org.apache.qpid.server.store.TransactionLogResource;
-public interface MessageSourceConsumer<X extends MessageSourceConsumer<X>> extends ConsumerImpl, Consumer<MessageSourceConsumer<X>>
+public interface BaseMessageInstance
{
+ boolean getDeliveredToConsumer();
+
+ ServerMessage getMessage();
+
+ TransactionLogResource getOwningResource();
+
+ MessageEnqueueRecord getEnqueueRecord();
+
+ boolean acquire();
+
+ void delete();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/message/ConsumerOption.java
similarity index 83%
rename from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
rename to broker-core/src/main/java/org/apache/qpid/server/message/ConsumerOption.java
index d2aff53..7bbcf15 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/ConsumerOption.java
@@ -18,8 +18,14 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.message;
-public interface QueueEntryListBase extends QueueEntryList
+public enum ConsumerOption
{
+ ACQUIRES,
+ SEES_REQUEUES,
+ TRANSIENT,
+ EXCLUSIVE,
+ NO_LOCAL,
+ DURABLE
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java b/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java
index 91035be..9034fc4 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/MessageDestination.java
@@ -53,5 +53,5 @@
final String routingAddress,
InstanceProperties instanceProperties,
ServerTransaction txn,
- Action<? super MessageInstance> postEnqueueAction);
+ Action<? super BaseMessageInstance> postEnqueueAction);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageInfoImpl.java b/broker-core/src/main/java/org/apache/qpid/server/message/MessageInfoImpl.java
index 3750711..2cafde9 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageInfoImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/MessageInfoImpl.java
@@ -55,7 +55,7 @@
final AMQMessageHeader messageHeader = message.getMessageHeader();
_deliveredTo = instance.getDeliveredConsumer() == null ? null : String.valueOf(instance.getDeliveredConsumer()
- .getConsumerNumber());
+ .getIdentifier());
_arrivalTime = message.getArrivalTime() == 0L ? null : new Date(message.getArrivalTime());
_persistent = message.isPersistent();
_messageId = messageHeader.getMessageId();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java b/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java
index ed6724e..cec2f83 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstance.java
@@ -21,15 +21,12 @@
package org.apache.qpid.server.message;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.filter.Filterable;
-import org.apache.qpid.server.store.MessageEnqueueRecord;
-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;
-public interface MessageInstance
+public interface MessageInstance extends BaseMessageInstance
{
@@ -50,39 +47,37 @@
boolean acquiredByConsumer();
- boolean isAcquiredBy(ConsumerImpl consumer);
+ boolean isAcquiredBy(MessageInstanceConsumer consumer);
- boolean removeAcquisitionFromConsumer(ConsumerImpl consumer);
+ boolean removeAcquisitionFromConsumer(MessageInstanceConsumer consumer);
void setRedelivered();
boolean isRedelivered();
- ConsumerImpl getDeliveredConsumer();
+ MessageInstanceConsumer getDeliveredConsumer();
void reject();
- boolean isRejectedBy(ConsumerImpl consumer);
-
- boolean getDeliveredToConsumer();
+ boolean isRejectedBy(MessageInstanceConsumer consumer);
boolean expired();
- boolean acquire(ConsumerImpl sub);
+ boolean acquire(MessageInstanceConsumer sub);
- boolean makeAcquisitionUnstealable(final ConsumerImpl consumer);
+ boolean makeAcquisitionUnstealable(final MessageInstanceConsumer consumer);
boolean makeAcquisitionStealable();
int getMaximumDeliveryCount();
- int routeToAlternate(Action<? super MessageInstance> action, ServerTransaction txn);
+ int routeToAlternate(Action<? super BaseMessageInstance> action, ServerTransaction txn);
Filterable asFilterable();
- ConsumerImpl getAcquiringConsumer();
+ MessageInstanceConsumer getAcquiringConsumer();
- MessageEnqueueRecord getEnqueueRecord();
+ InstanceProperties getInstanceProperties();
enum State
{
@@ -171,7 +166,7 @@
}
}
- abstract class ConsumerAcquiredState<C extends ConsumerImpl> extends EntryState
+ abstract class ConsumerAcquiredState<C extends AcquiringMessageInstanceConsumer<C,?>> extends EntryState
{
public abstract C getConsumer();
@@ -188,7 +183,7 @@
}
}
- final class StealableConsumerAcquiredState<C extends ConsumerImpl> extends ConsumerAcquiredState
+ final class StealableConsumerAcquiredState<C extends AcquiringMessageInstanceConsumer<C,?>> extends ConsumerAcquiredState
{
private final C _consumer;
private final UnstealableConsumerAcquiredState<C> _unstealableState;
@@ -211,7 +206,7 @@
}
}
- final class UnstealableConsumerAcquiredState<C extends ConsumerImpl> extends ConsumerAcquiredState
+ final class UnstealableConsumerAcquiredState<C extends AcquiringMessageInstanceConsumer<C,?>> extends ConsumerAcquiredState
{
private final StealableConsumerAcquiredState<C> _stealableState;
@@ -240,25 +235,15 @@
boolean isAvailable();
- boolean acquire();
-
boolean isAcquired();
void release();
- void release(ConsumerImpl release);
+ void release(MessageInstanceConsumer release);
boolean resend();
- void delete();
-
boolean isDeleted();
boolean isHeld();
-
- ServerMessage getMessage();
-
- InstanceProperties getInstanceProperties();
-
- TransactionLogResource getOwningResource();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java b/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstanceConsumer.java
similarity index 75%
rename from broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
rename to broker-core/src/main/java/org/apache/qpid/server/message/MessageInstanceConsumer.java
index 7ca5c6d..4d645d4 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/MessageInstanceConsumer.java
@@ -20,9 +20,24 @@
*/
package org.apache.qpid.server.message;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.model.Consumer;
-
-public interface MessageSourceConsumer<X extends MessageSourceConsumer<X>> extends ConsumerImpl, Consumer<MessageSourceConsumer<X>>
+public interface MessageInstanceConsumer
{
+
+ boolean isClosed();
+
+ boolean acquires();
+
+ String getName();
+
+ void close();
+
+ void flush();
+
+ void externalStateChange();
+
+ Object getIdentifier();
+
+ boolean hasAvailableMessages();
+
+ void pullMessage();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java b/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java
index 3812474..f1c79d4 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/message/MessageSource.java
@@ -23,23 +23,22 @@
import java.util.Collection;
import java.util.EnumSet;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.protocol.AMQSessionModel;
import org.apache.qpid.server.store.TransactionLogResource;
-public interface MessageSource extends TransactionLogResource, MessageNode
+public interface MessageSource<X extends MessageInstanceConsumer> extends TransactionLogResource, MessageNode
{
- ConsumerImpl addConsumer(ConsumerTarget target, FilterManager filters,
- Class<? extends ServerMessage> messageClass,
- String consumerName,
- EnumSet<ConsumerImpl.Option> options,
- Integer priority)
- throws ExistingExclusiveConsumer, ExistingConsumerPreventsExclusive,
- ConsumerAccessRefused;
+ X addConsumer(ConsumerTarget target,
+ FilterManager filters,
+ Class<? extends ServerMessage> messageClass,
+ String consumerName,
+ EnumSet<ConsumerOption> options,
+ Integer priority)
+ throws ExistingExclusiveConsumer, ExistingConsumerPreventsExclusive, ConsumerAccessRefused;
- Collection<? extends ConsumerImpl> getConsumers();
+ Collection<X> getConsumers();
boolean verifySessionAccess(AMQSessionModel<?> session);
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/NoopConfigurationChangeListener.java b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfigurationChangeListener.java
similarity index 93%
rename from broker-core/src/main/java/org/apache/qpid/server/model/NoopConfigurationChangeListener.java
rename to broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfigurationChangeListener.java
index 4c22583..a722edb 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/NoopConfigurationChangeListener.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfigurationChangeListener.java
@@ -20,7 +20,7 @@
*/
package org.apache.qpid.server.model;
-public class NoopConfigurationChangeListener implements ConfigurationChangeListener
+public abstract class AbstractConfigurationChangeListener implements ConfigurationChangeListener
{
@Override
public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
index 2b16dd8..7e219f3 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
@@ -2596,11 +2596,11 @@
public ListenableFuture<Void> setAttributesAsync(final Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException
{
final Map<String,Object> updateAttributes = new HashMap<>(attributes);
- Object desiredState = updateAttributes.remove(ConfiguredObject.DESIRED_STATE);
- runTask(new Task<Void, RuntimeException>()
+ final Object desiredState = updateAttributes.remove(ConfiguredObject.DESIRED_STATE);
+ return doOnConfigThread(new Task<ListenableFuture<Void>, RuntimeException>()
{
@Override
- public Void execute()
+ public ListenableFuture<Void> execute()
{
authoriseSetAttributes(createProxyForValidation(attributes), attributes.keySet());
if (!isSystemProcess())
@@ -2609,7 +2609,29 @@
}
changeAttributes(updateAttributes);
- return null;
+ if(desiredState != null)
+ {
+ State state;
+ if(desiredState instanceof State)
+ {
+ state = (State)desiredState;
+ }
+ else if(desiredState instanceof String)
+ {
+ state = State.valueOf((String)desiredState);
+ }
+ else
+ {
+ throw new IllegalArgumentException("Cannot convert an object of type " + desiredState.getClass().getName() + " to a State");
+ }
+ return setDesiredState(state);
+ }
+ else
+ {
+ return Futures.immediateFuture(null);
+ }
+
+
}
@Override
@@ -2630,27 +2652,6 @@
return "attributes number=" + attributes.size();
}
});
- if(desiredState != null)
- {
- State state;
- if(desiredState instanceof State)
- {
- state = (State)desiredState;
- }
- else if(desiredState instanceof String)
- {
- state = State.valueOf((String)desiredState);
- }
- else
- {
- throw new IllegalArgumentException("Cannot convert an object of type " + desiredState.getClass().getName() + " to a State");
- }
- return setDesiredState(state);
- }
- else
- {
- return Futures.immediateFuture(null);
- }
}
public void forceUpdateAllSecureAttributes()
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
index 8411476..f84f9c7 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
@@ -469,11 +469,13 @@
return preferenceStoreFactory.createInstance(this, attributes);
}
+ @Override
protected final Principal getSystemPrincipal()
{
return _systemPrincipal;
}
+ @Override
public Runnable getOnContainerResolveTask()
{
return _onContainerResolveTask;
@@ -485,11 +487,13 @@
_onContainerResolveTask = onContainerResolveTask;
}
+ @Override
public Runnable getOnContainerCloseTask()
{
return _onContainerCloseTask;
}
+ @Override
public void setOnContainerCloseTask(final Runnable onContainerCloseTask)
{
_onContainerCloseTask = onContainerCloseTask;
@@ -497,6 +501,7 @@
private class ShutdownService implements Runnable
{
+ @Override
public void run()
{
Subject.doAs(getSystemTaskSubject("Shutdown"),
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/model/AnonymousCredential.java
similarity index 76%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/model/AnonymousCredential.java
index d2aff53..2955103 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AnonymousCredential.java
@@ -18,8 +18,12 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.model;
-public interface QueueEntryListBase extends QueueEntryList
+@ManagedObject(category = false, type = AnonymousCredential.ANONYMOUS)
+public interface AnonymousCredential<X extends AnonymousCredential<X>> extends Credential<X>
{
+ String ANONYMOUS = "Anonymous";
+
+
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java
index 452e260..226ba15 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java
@@ -1105,17 +1105,11 @@
}
- private final class AccessControlProviderListener implements ConfigurationChangeListener
+ private final class AccessControlProviderListener extends AbstractConfigurationChangeListener
{
private final Set<ConfiguredObject<?>> _bulkChanges = new HashSet<>();
@Override
- public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
- {
-
- }
-
- @Override
public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
{
if(object.getCategoryClass() == Broker.class && child.getCategoryClass() == AccessControlProvider.class)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java
index bc57081..c347723 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java
@@ -96,6 +96,11 @@
addRelationship(VirtualHost.class, VirtualHostAccessControlProvider.class);
addRelationship(VirtualHost.class, Exchange.class);
addRelationship(VirtualHost.class, Queue.class);
+ addRelationship(VirtualHost.class, RemoteHost.class);
+
+
+ addRelationship(RemoteHost.class, RemoteHostAddress.class);
+ addRelationship(RemoteHost.class, Credential.class);
addRelationship(VirtualHostLogger.class, VirtualHostLogInclusionRule.class);
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
index 8a54297..1866d5d 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
@@ -40,7 +40,8 @@
/**
* An object that can be "managed" (eg via the web interface) and usually read from configuration.
*/
-public interface ConfiguredObject<X extends ConfiguredObject<X>> extends ContextProvider, TaskExecutorProvider, PermissionedObject
+public interface ConfiguredObject<X extends ConfiguredObject<X>> extends ContextProvider, TaskExecutorProvider,
+ PermissionedObject
{
String OVER_SIZED_ATTRIBUTE_ALTERNATIVE_TEXT = "Value is too long to display";
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java b/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
index 3244cdd..a1df8b4 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Consumer.java
@@ -20,10 +20,12 @@
*/
package org.apache.qpid.server.model;
-import org.apache.qpid.server.consumer.ConsumerImpl;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.qpid.server.protocol.AMQSessionModel;
@ManagedObject
-public interface Consumer<X extends Consumer<X>> extends ConfiguredObject<X>, ConsumerImpl
+public interface Consumer<X extends Consumer<X>> extends ConfiguredObject<X>
{
String DISTRIBUTION_MODE = "distributionMode";
String EXCLUSIVE = "exclusive";
@@ -36,7 +38,7 @@
String SUSPEND_NOTIFICATION_PERIOD = "consumer.suspendNotificationPeriod";
@ManagedContextDefault( name = SUSPEND_NOTIFICATION_PERIOD)
- long SUSPEND_NOTIFICATION_PERIOD_DEFAULT = 10000;
+ long SUSPEND_NOTIFICATION_PERIOD_DEFAULT = 10000;AtomicLong CONSUMER_NUMBER_GENERATOR = new AtomicLong(0);
@ManagedAttribute
String getDistributionMode();
@@ -70,4 +72,21 @@
@ManagedStatistic(statisticType = StatisticType.POINT_IN_TIME, units = StatisticUnit.MESSAGES, label = "Prefetch")
long getUnacknowledgedMessages();
+
+ AMQSessionModel getSessionModel();
+
+ long getConsumerNumber();
+
+ boolean isSuspended();
+
+ boolean seesRequeues();
+
+ boolean trySendLock();
+
+
+ void getSendLock();
+
+ void releaseSendLock();
+
+ boolean isActive();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/model/Credential.java
similarity index 74%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/model/Credential.java
index d2aff53..0b9d405 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Credential.java
@@ -18,8 +18,15 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.model;
-public interface QueueEntryListBase extends QueueEntryList
+import java.util.List;
+
+import javax.security.sasl.SaslClient;
+
+@ManagedObject(creatable = false)
+public interface Credential<X extends Credential<X>> extends ConfiguredObject<X>
{
+
+ SaslClient getSaslClient(List<String> mechanisms);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java b/broker-core/src/main/java/org/apache/qpid/server/model/ExternalCredential.java
similarity index 74%
copy from broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
copy to broker-core/src/main/java/org/apache/qpid/server/model/ExternalCredential.java
index 7ca5c6d..bf4dbff 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ExternalCredential.java
@@ -18,11 +18,14 @@
* under the License.
*
*/
-package org.apache.qpid.server.message;
+package org.apache.qpid.server.model;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.model.Consumer;
-
-public interface MessageSourceConsumer<X extends MessageSourceConsumer<X>> extends ConsumerImpl, Consumer<MessageSourceConsumer<X>>
+@ManagedObject(category = false, type = ExternalCredential.EXTERNAL)
+public interface ExternalCredential<X extends ExternalCredential<X>> extends Credential<X>
{
+ String EXTERNAL = "External";
+
+ @ManagedAttribute
+ String getUsername();
+
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java b/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
index e1651e9..83e6c72 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
@@ -34,11 +34,11 @@
import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.CapacityChecker;
-import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.NotificationCheck;
import org.apache.qpid.server.queue.QueueConsumer;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.queue.QueueEntryVisitor;
+import org.apache.qpid.server.queue.RecoverableBaseQueue;
import org.apache.qpid.server.store.MessageDurability;
import org.apache.qpid.server.store.MessageEnqueueRecord;
import org.apache.qpid.server.util.Deletable;
@@ -46,8 +46,8 @@
@ManagedObject( defaultType = "standard", description = Queue.CLASS_DESCRIPTION )
public interface Queue<X extends Queue<X>> extends ConfiguredObject<X>,
Comparable<X>, ExchangeReferrer,
- BaseQueue,
- MessageSource,
+ RecoverableBaseQueue,
+ MessageSource<QueueConsumer<?>>,
CapacityChecker,
MessageDestination,
Deletable<X>
@@ -237,7 +237,7 @@
Collection<? extends Binding<?>> getBindings();
- Collection<? extends Consumer<?>> getConsumers();
+ Collection<QueueConsumer<?>> getConsumers();
//operations
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/model/RemoteHost.java
similarity index 62%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/model/RemoteHost.java
index d2aff53..a376837 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/RemoteHost.java
@@ -18,8 +18,23 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.model;
-public interface QueueEntryListBase extends QueueEntryList
+import java.util.Collection;
+
+@ManagedObject(defaultType = RemoteHost.REMOTE_HOST_TYPE)
+public interface RemoteHost<X extends RemoteHost<X>> extends ConfiguredObject<X>
{
+
+ String REMOTE_HOST_TYPE = "Standard";
+
+ @ManagedAttribute(defaultValue = "10")
+ int getRetryPeriod();
+
+ @ManagedAttribute(defaultValue = "true")
+ boolean isRedirectFollowed();
+
+ @ManagedAttribute(defaultValue = "[]")
+ Collection<String> getRoutableAddresses();
+
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/RemoteHostAddress.java b/broker-core/src/main/java/org/apache/qpid/server/model/RemoteHostAddress.java
new file mode 100644
index 0000000..c017e81
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/RemoteHostAddress.java
@@ -0,0 +1,69 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.util.Collection;
+import java.util.List;
+
+@ManagedObject( defaultType = RemoteHostAddress.REMOTE_HOST_ADDRESS_TYPE)
+public interface RemoteHostAddress<X extends RemoteHostAddress<X>> extends ConfiguredObject<X>
+{
+
+ String REMOTE_HOST_ADDRESS_TYPE = "Standard";
+
+ @ManagedAttribute(mandatory = true)
+ String getAddress();
+
+ @ManagedAttribute(mandatory = true)
+ int getPort();
+
+ @ManagedAttribute
+ String getHostName();
+
+ @ManagedAttribute
+ Protocol getProtocol();
+
+ @ManagedAttribute( defaultValue = "TCP" )
+ Transport getTransport();
+
+ @ManagedAttribute
+ KeyStore getKeyStore();
+
+ @ManagedAttribute
+ Collection<TrustStore> getTrustStores();
+
+ @ManagedAttribute(defaultValue = "0")
+ int getDesiredHeartbeatInterval();
+
+
+ @DerivedAttribute
+ List<String> getTlsProtocolWhiteList();
+
+ @DerivedAttribute
+ List<String> getTlsProtocolBlackList();
+
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteWhiteList();
+
+ @DerivedAttribute
+ List<String> getTlsCipherSuiteBlackList();
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/model/UsernamePasswordCredential.java
similarity index 67%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/model/UsernamePasswordCredential.java
index d2aff53..dbb59da 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/UsernamePasswordCredential.java
@@ -18,8 +18,16 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.model;
-public interface QueueEntryListBase extends QueueEntryList
+@ManagedObject(category = false, type = UsernamePasswordCredential.USERNAME_PASSWORD)
+public interface UsernamePasswordCredential<X extends UsernamePasswordCredential<X>> extends Credential<X>
{
+ String USERNAME_PASSWORD = "UsernamePassword";
+
+ @ManagedAttribute
+ String getUsername();
+
+ @ManagedAttribute(secure = true)
+ String getPassword();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
index 720f96a..b0996f9 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
@@ -37,7 +37,9 @@
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.preferences.UserPreferencesCreator;
+import org.apache.qpid.server.transfer.TransferQueue;
import org.apache.qpid.server.transport.AMQPConnection;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.HouseKeepingTask;
import org.apache.qpid.server.virtualhost.NodeAutoCreationPolicy;
@@ -261,8 +263,12 @@
String getLocalAddress(String routingAddress);
+ TransferQueue getTransferQueue();
+
void setFirstOpening(boolean firstOpening);
+ boolean makeConnection(RemoteHostAddress<?> address, final Action<Boolean> onConnectionLoss);
+
interface Transaction
{
void dequeue(QueueEntry entry);
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/plugin/OutboundProtocolEngineCreator.java
similarity index 61%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/plugin/OutboundProtocolEngineCreator.java
index d2aff53..8cd11e8 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/plugin/OutboundProtocolEngineCreator.java
@@ -1,4 +1,4 @@
-/*
+package org.apache.qpid.server.plugin;/*
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -18,8 +18,17 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
-public interface QueueEntryListBase extends QueueEntryList
+import org.apache.qpid.server.federation.OutboundProtocolEngine;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.RemoteHostAddress;
+import org.apache.qpid.server.model.VirtualHost;
+
+public interface OutboundProtocolEngineCreator extends Pluggable
{
+ Protocol getVersion();
+ OutboundProtocolEngine newProtocolEngine(RemoteHostAddress<?> address,
+ VirtualHost<?> virtualHost);
+
}
+
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
index 49e2fab..9ce9eb2 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
@@ -72,7 +72,6 @@
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.updater.Task;
import org.apache.qpid.server.connection.SessionPrincipal;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.filter.JMSSelectorFilter;
@@ -82,6 +81,8 @@
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.messages.QueueMessages;
import org.apache.qpid.server.logging.subjects.QueueLogSubject;
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageDeletedException;
import org.apache.qpid.server.message.MessageInfo;
@@ -726,7 +727,7 @@
final FilterManager filters,
final Class<? extends ServerMessage> messageClass,
final String consumerName,
- final EnumSet<ConsumerImpl.Option> optionSet,
+ final EnumSet<ConsumerOption> optionSet,
final Integer priority)
throws ExistingExclusiveConsumer, ExistingConsumerPreventsExclusive,
ConsumerAccessRefused
@@ -779,7 +780,7 @@
FilterManager filters,
final Class<? extends ServerMessage> messageClass,
final String consumerName,
- EnumSet<ConsumerImpl.Option> optionSet,
+ EnumSet<ConsumerOption> optionSet,
final Integer priority)
throws ExistingExclusiveConsumer, ConsumerAccessRefused,
ExistingConsumerPreventsExclusive
@@ -789,6 +790,136 @@
throw new ExistingExclusiveConsumer();
}
+ if(_noLocal && !optionSet.contains(ConsumerOption.NO_LOCAL))
+ {
+ optionSet = EnumSet.copyOf(optionSet);
+ optionSet.add(ConsumerOption.NO_LOCAL);
+ }
+
+ if(_ensureNondestructiveConsumers)
+ {
+ optionSet = EnumSet.copyOf(optionSet);
+ optionSet.removeAll(EnumSet.of(ConsumerOption.SEES_REQUEUES, ConsumerOption.ACQUIRES));
+ }
+
+
+
+ boolean exclusive = optionSet.contains(ConsumerOption.EXCLUSIVE);
+ boolean isTransient = optionSet.contains(ConsumerOption.TRANSIENT);
+
+
+
+ if(exclusive && getConsumerCount() != 0)
+ {
+ throw new ExistingConsumerPreventsExclusive();
+ }
+
+ if(!_defaultFiltersMap.isEmpty())
+ {
+ if(filters == null)
+ {
+ filters = new FilterManager();
+ }
+ for (Map.Entry<String,Callable<MessageFilter>> filter : _defaultFiltersMap.entrySet())
+ {
+ if(!filters.hasFilter(filter.getKey()))
+ {
+ MessageFilter f;
+ try
+ {
+ f = filter.getValue().call();
+ }
+ catch (Exception e)
+ {
+ if (e instanceof RuntimeException)
+ {
+ throw (RuntimeException) e;
+ }
+ else
+ {
+ // Should never happen
+ throw new ServerScopedRuntimeException(e);
+ }
+ }
+ filters.add(filter.getKey(), f);
+ }
+ }
+ }
+
+
+ QueueConsumerImpl consumer = new QueueConsumerImpl(this,
+ target,
+ consumerName,
+ filters,
+ messageClass,
+ optionSet,
+ priority);
+
+ checkExclusivity(target);
+
+
+ consumer.open();
+
+ target.consumerAdded(consumer);
+
+
+ if (exclusive && !isTransient)
+ {
+ _exclusiveSubscriber = consumer;
+ }
+
+ if(consumer.isActive())
+ {
+ _activeSubscriberCount.incrementAndGet();
+ }
+
+ consumer.setStateListener(this);
+ QueueContext queueContext;
+ if(filters == null || !filters.startAtTail())
+ {
+ queueContext = new QueueContext(getEntries().getHead());
+ }
+ else
+ {
+ queueContext = new QueueContext(getEntries().getTail());
+ }
+ consumer.setQueueContext(queueContext);
+
+ if (!isDeleted())
+ {
+ if(consumer.isPullOnly())
+ {
+ _hasPullOnlyConsumers = true;
+ }
+ _consumerList.add(consumer);
+
+ if (isDeleted())
+ {
+ consumer.queueDeleted();
+ }
+ }
+ else
+ {
+ // TODO
+ }
+
+ childAdded(consumer);
+ consumer.addChangeListener(_deletedChildListener);
+
+ if(consumer.isPullOnly())
+ {
+ consumer.getSessionModel().getAMQPConnection().notifyWork();
+ }
+ else
+ {
+ deliverAsync();
+ }
+
+ return consumer;
+ }
+
+ private void checkExclusivity(final ConsumerTarget target) throws ConsumerAccessRefused
+ {
Object exclusiveOwner = _exclusiveOwner;
switch(_exclusive)
{
@@ -858,123 +989,7 @@
default:
throw new ServerScopedRuntimeException("Unknown exclusivity policy " + _exclusive);
}
-
- boolean exclusive = optionSet.contains(ConsumerImpl.Option.EXCLUSIVE);
- boolean isTransient = optionSet.contains(ConsumerImpl.Option.TRANSIENT);
-
- if(_noLocal && !optionSet.contains(ConsumerImpl.Option.NO_LOCAL))
- {
- optionSet = EnumSet.copyOf(optionSet);
- optionSet.add(ConsumerImpl.Option.NO_LOCAL);
- }
-
- if(exclusive && getConsumerCount() != 0)
- {
- throw new ExistingConsumerPreventsExclusive();
- }
- if(!_defaultFiltersMap.isEmpty())
- {
- if(filters == null)
- {
- filters = new FilterManager();
- }
- for (Map.Entry<String,Callable<MessageFilter>> filter : _defaultFiltersMap.entrySet())
- {
- if(!filters.hasFilter(filter.getKey()))
- {
- MessageFilter f;
- try
- {
- f = filter.getValue().call();
- }
- catch (Exception e)
- {
- if (e instanceof RuntimeException)
- {
- throw (RuntimeException) e;
- }
- else
- {
- // Should never happen
- throw new ServerScopedRuntimeException(e);
- }
- }
- filters.add(filter.getKey(), f);
- }
- }
- }
-
- if(_ensureNondestructiveConsumers)
- {
- optionSet = EnumSet.copyOf(optionSet);
- optionSet.removeAll(EnumSet.of(ConsumerImpl.Option.SEES_REQUEUES, ConsumerImpl.Option.ACQUIRES));
- }
-
- QueueConsumerImpl consumer = new QueueConsumerImpl(this,
- target,
- consumerName,
- filters,
- messageClass,
- optionSet,
- priority);
-
_exclusiveOwner = exclusiveOwner;
- target.consumerAdded(consumer);
-
-
- if (exclusive && !isTransient)
- {
- _exclusiveSubscriber = consumer;
- }
-
- if(consumer.isActive())
- {
- _activeSubscriberCount.incrementAndGet();
- }
-
- consumer.setStateListener(this);
- QueueContext queueContext;
- if(filters == null || !filters.startAtTail())
- {
- queueContext = new QueueContext(getEntries().getHead());
- }
- else
- {
- queueContext = new QueueContext(getEntries().getTail());
- }
- consumer.setQueueContext(queueContext);
-
- if (!isDeleted())
- {
- if(consumer.isPullOnly())
- {
- _hasPullOnlyConsumers = true;
- }
- _consumerList.add(consumer);
-
- if (isDeleted())
- {
- consumer.queueDeleted();
- }
- }
- else
- {
- // TODO
- }
-
- childAdded(consumer);
- consumer.addChangeListener(_deletedChildListener);
-
- if(consumer.isPullOnly())
- {
- consumer.getSessionModel().getAMQPConnection().notifyWork();
- }
- else
- {
- deliverAsync();
- }
-
- return consumer;
}
@Override
@@ -1137,7 +1152,7 @@
// ------ Enqueue / Dequeue
- public final void enqueue(ServerMessage message, Action<? super MessageInstance> action, MessageEnqueueRecord enqueueRecord)
+ public final void enqueue(ServerMessage message, Action<? super BaseMessageInstance> action, MessageEnqueueRecord enqueueRecord)
{
incrementQueueCount();
incrementQueueSize(message);
@@ -2089,6 +2104,57 @@
txn.commit();
}
+ int routeToAlternate(final QueueEntry queueEntry, final Action<? super BaseMessageInstance> action, ServerTransaction txn)
+ {
+ if (!queueEntry.isAcquired())
+ {
+ throw new IllegalStateException("Illegal queue entry state. " + this + " is not acquired.");
+ }
+
+ Exchange<?> alternateExchange = getAlternateExchange();
+ boolean autocommit = txn == null;
+ int enqueues;
+
+ if(autocommit)
+ {
+ txn = new LocalTransaction(getVirtualHost().getMessageStore());
+ }
+
+ if (alternateExchange != null)
+ {
+ enqueues = alternateExchange.send(queueEntry.getMessage(),
+ queueEntry.getMessage().getInitialRoutingAddress(),
+ queueEntry.getInstanceProperties(),
+ txn,
+ action);
+ }
+ else
+ {
+ enqueues = 0;
+ }
+
+ txn.dequeue(queueEntry.getEnqueueRecord(), new ServerTransaction.Action()
+ {
+ public void postCommit()
+ {
+ queueEntry.delete();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+
+ if(autocommit)
+ {
+ txn.commit();
+ }
+
+ return enqueues;
+ }
+
+
private void performQueueDeleteTasks()
{
for (Action<? super X> task : _deleteTaskList)
@@ -3095,7 +3161,7 @@
final String routingAddress,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final Action<? super MessageInstance> postEnqueueAction)
+ final Action<? super BaseMessageInstance> postEnqueueAction)
{
if (_virtualHost.getState() != State.ACTIVE)
{
@@ -3226,7 +3292,7 @@
case CONTAINER:
case CONNECTION:
AMQSessionModel session = null;
- for(ConsumerImpl c : getConsumers())
+ for(QueueConsumer c : getConsumers())
{
if(session == null)
{
@@ -3252,7 +3318,7 @@
case CONTAINER:
case PRINCIPAL:
AMQPConnection con = null;
- for(ConsumerImpl c : getConsumers())
+ for(QueueConsumer c : getConsumers())
{
if(con == null)
{
@@ -3280,7 +3346,7 @@
case NONE:
case PRINCIPAL:
String containerID = null;
- for(ConsumerImpl c : getConsumers())
+ for(QueueConsumer c : getConsumers())
{
if(containerID == null)
{
@@ -3311,7 +3377,7 @@
case NONE:
case CONTAINER:
Principal principal = null;
- for(ConsumerImpl c : getConsumers())
+ for(QueueConsumer c : getConsumers())
{
if(principal == null)
{
@@ -3565,7 +3631,7 @@
authorise(token, PUBLISH_ACTION, arguments);
}
- private class DeletedChildListener implements ConfigurationChangeListener
+ private class DeletedChildListener extends AbstractConfigurationChangeListener
{
@Override
public void stateChanged(final ConfiguredObject object, final State oldState, final State newState)
@@ -3575,39 +3641,6 @@
AbstractQueue.this.childRemoved(object);
}
}
-
- @Override
- public void childAdded(final ConfiguredObject object, final ConfiguredObject child)
- {
-
- }
-
- @Override
- public void childRemoved(final ConfiguredObject object, final ConfiguredObject child)
- {
-
- }
-
- @Override
- public void attributeSet(final ConfiguredObject object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
-
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
}
private static class EnqueueRequest
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java b/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
index dc2f45a..174a77b 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java
@@ -21,7 +21,7 @@
package org.apache.qpid.server.queue;
-import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.BaseMessageInstance;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.store.MessageEnqueueRecord;
import org.apache.qpid.server.store.TransactionLogResource;
@@ -29,7 +29,7 @@
public interface BaseQueue extends TransactionLogResource
{
- void enqueue(ServerMessage message, Action<? super MessageInstance> action, MessageEnqueueRecord record);
+ void enqueue(ServerMessage message, Action<? super BaseMessageInstance> action, MessageEnqueueRecord record);
boolean isDurable();
boolean isDeleted();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java b/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java
index e19af3d..be951f8 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/DefinedGroupMessageGroupManager.java
@@ -20,22 +20,21 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.message.MessageInstance;
-import org.apache.qpid.server.message.MessageInstance.ConsumerAcquiredState;
-import org.apache.qpid.server.message.MessageInstance.EntryState;
-import org.apache.qpid.server.util.StateChangeListener;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.qpid.server.message.AMQMessageHeader;
-import org.apache.qpid.server.message.ServerMessage;
-
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.TreeSet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstance.ConsumerAcquiredState;
+import org.apache.qpid.server.message.MessageInstance.EntryState;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.util.StateChangeListener;
+
public class DefinedGroupMessageGroupManager implements MessageGroupManager
{
private static final Logger _logger = LoggerFactory.getLogger(DefinedGroupMessageGroupManager.class);
@@ -183,7 +182,7 @@
}
}
- ConsumerImpl assignedSub = group.getConsumer();
+ QueueConsumer<?> assignedSub = group.getConsumer();
if(assignedSub == sub)
{
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/LastValueQueueList.java b/broker-core/src/main/java/org/apache/qpid/server/queue/LastValueQueueList.java
index c2ad41e..98c6598 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/LastValueQueueList.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/LastValueQueueList.java
@@ -30,7 +30,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.consumer.ConsumerImpl;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.store.MessageEnqueueRecord;
import org.apache.qpid.server.txn.AutoCommitTransaction;
@@ -220,7 +220,7 @@
}
@Override
- public void release(ConsumerImpl consumer)
+ public void release(MessageInstanceConsumer consumer)
{
super.release(consumer);
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedBaseQueueEntryList.java b/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedBaseQueueEntryList.java
new file mode 100644
index 0000000..ad0ed0b
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedBaseQueueEntryList.java
@@ -0,0 +1,212 @@
+/*
+*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT 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 java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.store.MessageEnqueueRecord;
+
+public abstract class OrderedBaseQueueEntryList<T extends RecoverableBaseQueue> implements QueueEntryList
+{
+
+ private final OrderedQueueEntry _head;
+
+ private volatile OrderedQueueEntry _tail;
+
+ static final AtomicReferenceFieldUpdater<OrderedBaseQueueEntryList, OrderedQueueEntry>
+ _tailUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (OrderedBaseQueueEntryList.class, OrderedQueueEntry.class, "_tail");
+
+
+ private final T _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<QueueEntry> _unscavengedHWM = new AtomicReference<QueueEntry>();
+
+
+ public OrderedBaseQueueEntryList(T queue, HeadCreator headCreator)
+ {
+ _queue = queue;
+ _head = headCreator.createHead(this);
+ _tail = _head;
+ }
+
+ void scavenge()
+ {
+ QueueEntry hwm = _unscavengedHWM.getAndSet(null);
+ QueueEntry next = _head.getNextValidEntry();
+
+ if(hwm != null)
+ {
+ while (next != null && hwm.compareTo(next)>0)
+ {
+ next = next.getNextValidEntry();
+ }
+ }
+ }
+
+
+ public T getQueue()
+ {
+ return _queue;
+ }
+
+
+ public QueueEntry add(ServerMessage message, final MessageEnqueueRecord enqueueRecord)
+ {
+ OrderedQueueEntry node = createQueueEntry(message, enqueueRecord);
+ 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 OrderedQueueEntry createQueueEntry(ServerMessage<?> message,
+ final MessageEnqueueRecord enqueueRecord);
+
+ @Override
+ public QueueEntry next(QueueEntry node)
+ {
+ return node.getNextValidEntry();
+ }
+
+ public static interface HeadCreator
+ {
+ OrderedQueueEntry createHead(QueueEntryList list);
+ }
+
+ public static class QueueEntryIteratorImpl implements QueueEntryIterator
+ {
+ private QueueEntry _lastNode;
+
+ QueueEntryIteratorImpl(QueueEntry startNode)
+ {
+ _lastNode = startNode;
+ }
+
+ public boolean atTail()
+ {
+ return _lastNode.getNextValidEntry() == null;
+ }
+
+ public QueueEntry getNode()
+ {
+ return _lastNode;
+ }
+
+ public boolean advance()
+ {
+ QueueEntry nextValidNode = _lastNode.getNextValidEntry();
+
+ if(nextValidNode != null)
+ {
+ _lastNode = nextValidNode;
+ }
+
+ return nextValidNode != null;
+ }
+ }
+
+ public QueueEntryIterator iterator()
+ {
+ return new QueueEntryIteratorImpl(_head);
+ }
+
+
+ public QueueEntry getHead()
+ {
+ return _head;
+ }
+
+ @Override
+ public QueueEntry getTail()
+ {
+ return _tail;
+ }
+
+ public void entryDeleted(QueueEntry queueEntry)
+ {
+ QueueEntry next = _head.getNextNode();
+ QueueEntry newNext = _head.getNextValidEntry();
+
+ // the head of the queue has not been deleted, hence the deletion must have been mid queue.
+ if (next == newNext)
+ {
+ QueueEntry 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
+ {
+ QueueEntry unscavengedHWM = _unscavengedHWM.get();
+ if(unscavengedHWM != null && (next == null || unscavengedHWM.compareTo(next) < 0))
+ {
+ _unscavengedHWM.compareAndSet(unscavengedHWM, null);
+ }
+ }
+ }
+
+ public int getPriorities()
+ {
+ return 0;
+ }
+
+ @Override
+ public QueueEntry getOldestEntry()
+ {
+ return next(getHead());
+ }
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java b/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java
index d45dceb..9cc5496 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntry.java
@@ -34,12 +34,12 @@
private volatile OrderedQueueEntry _next;
- public OrderedQueueEntry(OrderedQueueEntryList queueEntryList)
+ public OrderedQueueEntry(OrderedBaseQueueEntryList queueEntryList)
{
super(queueEntryList);
}
- public OrderedQueueEntry(OrderedQueueEntryList queueEntryList,
+ public OrderedQueueEntry(OrderedBaseQueueEntryList queueEntryList,
ServerMessage message,
final MessageEnqueueRecord messageEnqueueRecord)
{
@@ -63,7 +63,7 @@
final OrderedQueueEntry newNext = next.getNextNode();
if(newNext != null)
{
- OrderedQueueEntryList._nextUpdater.compareAndSet(this,next, newNext);
+ OrderedBaseQueueEntryList._nextUpdater.compareAndSet(this, next, newNext);
next = getNextNode();
}
else
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java b/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java
index 1283530..9fb3321 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/OrderedQueueEntryList.java
@@ -1,213 +1,80 @@
/*
-*
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you under the Apache License, Version 2.0 (the
-* "License"); you may not use this file except in compliance
-* with the License. You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing,
-* software distributed under the License is distributed on an
-* "AS IS" BASIS, WITHOUT 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 java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
-
-import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
+import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.Queue;
-import org.apache.qpid.server.store.MessageEnqueueRecord;
+import org.apache.qpid.server.txn.LocalTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
-public abstract class OrderedQueueEntryList implements QueueEntryList
+public abstract class OrderedQueueEntryList extends OrderedBaseQueueEntryList<AbstractQueue<?>>
{
-
- private final OrderedQueueEntry _head;
-
- private volatile OrderedQueueEntry _tail;
-
- static final AtomicReferenceFieldUpdater<OrderedQueueEntryList, OrderedQueueEntry>
- _tailUpdater =
- AtomicReferenceFieldUpdater.newUpdater
- (OrderedQueueEntryList.class, OrderedQueueEntry.class, "_tail");
-
-
- private final Queue<?> _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<QueueEntry> _unscavengedHWM = new AtomicReference<QueueEntry>();
-
-
- public OrderedQueueEntryList(Queue<?> queue, HeadCreator headCreator)
+ public OrderedQueueEntryList(final AbstractQueue<?> queue,
+ final HeadCreator headCreator)
{
- _queue = queue;
- _head = headCreator.createHead(this);
- _tail = _head;
- }
-
- void scavenge()
- {
- QueueEntry hwm = _unscavengedHWM.getAndSet(null);
- QueueEntry next = _head.getNextValidEntry();
-
- if(hwm != null)
- {
- while (next != null && hwm.compareTo(next)>0)
- {
- next = next.getNextValidEntry();
- }
- }
- }
-
-
- public Queue<?> getQueue()
- {
- return _queue;
- }
-
-
- public QueueEntry add(ServerMessage message, final MessageEnqueueRecord enqueueRecord)
- {
- OrderedQueueEntry node = createQueueEntry(message, enqueueRecord);
- 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 OrderedQueueEntry createQueueEntry(ServerMessage<?> message,
- final MessageEnqueueRecord enqueueRecord);
-
- @Override
- public QueueEntry next(QueueEntry node)
- {
- return node.getNextValidEntry();
- }
-
- public static interface HeadCreator
- {
- OrderedQueueEntry createHead(QueueEntryList list);
- }
-
- public static class QueueEntryIteratorImpl implements QueueEntryIterator
- {
- private QueueEntry _lastNode;
-
- QueueEntryIteratorImpl(QueueEntry startNode)
- {
- _lastNode = startNode;
- }
-
- public boolean atTail()
- {
- return _lastNode.getNextValidEntry() == null;
- }
-
- public QueueEntry getNode()
- {
- return _lastNode;
- }
-
- public boolean advance()
- {
- QueueEntry nextValidNode = _lastNode.getNextValidEntry();
-
- if(nextValidNode != null)
- {
- _lastNode = nextValidNode;
- }
-
- return nextValidNode != null;
- }
- }
-
- public QueueEntryIterator iterator()
- {
- return new QueueEntryIteratorImpl(_head);
- }
-
-
- public QueueEntry getHead()
- {
- return _head;
+ super(queue, headCreator);
}
@Override
- public QueueEntry getTail()
+ public void onAcquiredByConsumer(final QueueEntry queueEntry, final MessageInstanceConsumer consumer)
{
- return _tail;
- }
-
- public void entryDeleted(QueueEntry queueEntry)
- {
- QueueEntry next = _head.getNextNode();
- QueueEntry newNext = _head.getNextValidEntry();
-
- // the head of the queue has not been deleted, hence the deletion must have been mid queue.
- if (next == newNext)
- {
- QueueEntry 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
- {
- QueueEntry unscavengedHWM = _unscavengedHWM.get();
- if(unscavengedHWM != null && (next == null || unscavengedHWM.compareTo(next) < 0))
- {
- _unscavengedHWM.compareAndSet(unscavengedHWM, null);
- }
- }
- }
-
- public int getPriorities()
- {
- return 0;
+ getQueue().incrementUnackedMsgCount(queueEntry);
}
@Override
- public QueueEntry getOldestEntry()
+ public void onNoLongerAcquiredByConsumer(final QueueEntry queueEntry)
{
- return next(getHead());
+ getQueue().decrementUnackedMsgCount(queueEntry);
}
+ @Override
+ public void requeue(final QueueEntry queueEntry)
+ {
+ getQueue().requeue(queueEntry);
+ }
+
+ @Override
+ public boolean isHeld(final QueueEntry queueEntry, final long evaluationTime)
+ {
+ return getQueue().isHeld(queueEntry, evaluationTime);
+ }
+
+ @Override
+ public void dequeue(final QueueEntry queueEntry)
+ {
+ getQueue().dequeue(queueEntry);
+ }
+
+ @Override
+ public int routeToAlternate(final QueueEntry queueEntry, final Action<? super BaseMessageInstance> action, ServerTransaction txn)
+ {
+ return getQueue().routeToAlternate(queueEntry, action, txn);
+ }
+
+ @Override
+ public int getMaximumDeliveryAttempts()
+ {
+ return getQueue().getMaximumDeliveryAttempts();
+ }
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
index 771097a..d8d959e 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumer.java
@@ -20,11 +20,13 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.message.AcquiringMessageInstanceConsumer;
import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.model.Consumer;
import org.apache.qpid.server.model.Queue;
-public interface QueueConsumer<X extends QueueConsumer<X>> extends Consumer<X>
+public interface QueueConsumer<X extends QueueConsumer<X>> extends Consumer<X>, AcquiringMessageInstanceConsumer<X, ConsumerTarget>
{
void flushBatched();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java
index 804bde1..d13f1a3 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueConsumerImpl.java
@@ -46,9 +46,9 @@
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.messages.SubscriptionMessages;
import org.apache.qpid.server.logging.subjects.QueueLogSubject;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageReference;
-import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.Consumer;
@@ -124,7 +124,7 @@
final String consumerName,
final FilterManager filters,
final Class<? extends ServerMessage> messageClass,
- EnumSet<Option> optionSet,
+ EnumSet<ConsumerOption> optionSet,
final Integer priority)
{
super(parentsMap(queue, target.getSessionModel().getModelObject()),
@@ -133,18 +133,16 @@
_sessionReference = target.getSessionModel().getConnectionReference();
_consumerNumber = CONSUMER_NUMBER_GENERATOR.getAndIncrement();
_filters = filters;
- _acquires = optionSet.contains(Option.ACQUIRES);
- _seesRequeues = optionSet.contains(Option.SEES_REQUEUES);
- _isTransient = optionSet.contains(Option.TRANSIENT);
+ _acquires = optionSet.contains(ConsumerOption.ACQUIRES);
+ _seesRequeues = optionSet.contains(ConsumerOption.SEES_REQUEUES);
+ _isTransient = optionSet.contains(ConsumerOption.TRANSIENT);
_target = target;
_queue = queue;
// Access control
authorise(Operation.CREATE);
- open();
- setupLogging();
_listener = new StateChangeListener<ConsumerTarget, ConsumerTarget.State>()
{
@@ -168,20 +166,29 @@
getEventLogger().message(getLogSubject(), SubscriptionMessages.STATE(period));
}
};
+
+
+ }
+
+ @Override
+ protected void onOpen()
+ {
+ super.onOpen();
+ setupLogging();
}
private static Map<String, Object> createAttributeMap(String name,
FilterManager filters,
- EnumSet<Option> optionSet,
+ EnumSet<ConsumerOption> optionSet,
Integer priority)
{
Map<String,Object> attributes = new HashMap<String, Object>();
attributes.put(ID, UUID.randomUUID());
attributes.put(NAME, name);
- attributes.put(EXCLUSIVE, optionSet.contains(Option.EXCLUSIVE));
- attributes.put(NO_LOCAL, optionSet.contains(Option.NO_LOCAL));
- attributes.put(DISTRIBUTION_MODE, optionSet.contains(Option.ACQUIRES) ? "MOVE" : "COPY");
- attributes.put(DURABLE,optionSet.contains(Option.DURABLE));
+ attributes.put(EXCLUSIVE, optionSet.contains(ConsumerOption.EXCLUSIVE));
+ attributes.put(NO_LOCAL, optionSet.contains(ConsumerOption.NO_LOCAL));
+ attributes.put(DISTRIBUTION_MODE, optionSet.contains(ConsumerOption.ACQUIRES) ? "MOVE" : "COPY");
+ attributes.put(DURABLE,optionSet.contains(ConsumerOption.DURABLE));
attributes.put(LIFETIME_POLICY, LifetimePolicy.DELETE_ON_SESSION_END);
if(priority != null)
{
@@ -297,9 +304,9 @@
}
@Override
- public MessageSource getMessageSource()
+ public Object getIdentifier()
{
- return _queue;
+ return getConsumerNumber();
}
@Override
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
index b723f05..8270e34 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntry.java
@@ -20,20 +20,20 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.qpid.server.message.AcquiringMessageInstanceConsumer;
import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageReference;
-import org.apache.qpid.server.model.Queue;
public interface QueueEntry extends MessageInstance, Comparable<QueueEntry>
{
- Queue<?> getQueue();
+ RecoverableBaseQueue getQueue();
long getSize();
boolean acquireOrSteal(final Runnable delayedAcquisitionTask);
- QueueConsumer getDeliveredConsumer();
+ AcquiringMessageInstanceConsumer<?,?> getDeliveredConsumer();
boolean isQueueDeleted();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
index a658a21..aeb84ef 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java
@@ -30,15 +30,16 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.filter.Filterable;
+import org.apache.qpid.server.message.AcquiringMessageInstanceConsumer;
+import org.apache.qpid.server.message.BaseMessageInstance;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageDeletedException;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.Exchange;
-import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.store.MessageEnqueueRecord;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.txn.LocalTransaction;
@@ -55,7 +56,7 @@
private final MessageReference _message;
- private Set<Long> _rejectedBy = null;
+ private Set<Object> _rejectedBy = null;
private static final EntryState HELD_STATE = new EntryState()
{
@@ -177,7 +178,7 @@
return _entryId;
}
- public Queue<?> getQueue()
+ public RecoverableBaseQueue getQueue()
{
return _queueEntryList.getQueue();
}
@@ -263,7 +264,7 @@
boolean acquired = acquire();
if(!acquired)
{
- QueueConsumer consumer = getDeliveredConsumer();
+ AcquiringMessageInstanceConsumer<?,?> consumer = getDeliveredConsumer();
acquired = removeAcquisitionFromConsumer(consumer);
if(acquired)
{
@@ -304,19 +305,19 @@
return acquired;
}
- public boolean acquire(ConsumerImpl sub)
+ public boolean acquire(MessageInstanceConsumer sub)
{
- final boolean acquired = acquire(((QueueConsumer<?>) sub).getOwningState().getUnstealableState());
+ final boolean acquired = acquire(((AcquiringMessageInstanceConsumer<?,?>) sub).getOwningState().getUnstealableState());
if(acquired)
{
_deliveryCountUpdater.compareAndSet(this,-1,0);
- getQueue().incrementUnackedMsgCount(this);
+ _queueEntryList.onAcquiredByConsumer(this, sub);
}
return acquired;
}
@Override
- public boolean makeAcquisitionUnstealable(final ConsumerImpl consumer)
+ public boolean makeAcquisitionUnstealable(final MessageInstanceConsumer consumer)
{
EntryState state = _state;
if(state instanceof StealableConsumerAcquiredState
@@ -357,9 +358,9 @@
}
@Override
- public ConsumerImpl getAcquiringConsumer()
+ public MessageInstanceConsumer getAcquiringConsumer()
{
- ConsumerImpl consumer;
+ AcquiringMessageInstanceConsumer<?,?> consumer;
EntryState state = _state;
if (state instanceof ConsumerAcquiredState)
{
@@ -373,14 +374,14 @@
}
@Override
- public boolean isAcquiredBy(ConsumerImpl consumer)
+ public boolean isAcquiredBy(MessageInstanceConsumer consumer)
{
EntryState state = _state;
return (state instanceof ConsumerAcquiredState && ((ConsumerAcquiredState)state).getConsumer() == consumer);
}
@Override
- public boolean removeAcquisitionFromConsumer(ConsumerImpl consumer)
+ public boolean removeAcquisitionFromConsumer(MessageInstanceConsumer consumer)
{
EntryState state = _state;
if(state instanceof StealableConsumerAcquiredState
@@ -411,7 +412,7 @@
}
@Override
- public void release(ConsumerImpl consumer)
+ public void release(MessageInstanceConsumer consumer)
{
EntryState state = _state;
if(isAcquiredBy(consumer) && _stateUpdater.compareAndSet(this, state, AVAILABLE_STATE))
@@ -424,12 +425,12 @@
{
if (previousState instanceof ConsumerAcquiredState)
{
- getQueue().decrementUnackedMsgCount(this);
+ _queueEntryList.onNoLongerAcquiredByConsumer(this);
}
if(!getQueue().isDeleted())
{
- getQueue().requeue(this);
+ _queueEntryList.requeue(this);
if (_stateChangeListeners != null && previousState.getState() == State.ACQUIRED)
{
notifyStateChange(previousState, AVAILABLE_STATE);
@@ -448,7 +449,7 @@
EntryState state;
while((state = _state).getState() == State.AVAILABLE)
{
- boolean isHeld = getQueue().isHeld(this, evaluationTime);
+ boolean isHeld = _queueEntryList.isHeld(this, evaluationTime);
if(state == AVAILABLE_STATE && isHeld)
{
if(!_stateUpdater.compareAndSet(this, state, HELD_STATE))
@@ -475,20 +476,20 @@
}
@Override
- public QueueConsumer getDeliveredConsumer()
+ public AcquiringMessageInstanceConsumer getDeliveredConsumer()
{
- return (QueueConsumer) getAcquiringConsumer();
+ return (AcquiringMessageInstanceConsumer) getAcquiringConsumer();
}
public void reject()
{
- QueueConsumer consumer = getDeliveredConsumer();
+ AcquiringMessageInstanceConsumer<?,?> consumer = getDeliveredConsumer();
if (consumer != null)
{
if (_rejectedBy == null)
{
- _rejectedBy = new HashSet<Long>();
+ _rejectedBy = new HashSet<>();
}
_rejectedBy.add(consumer.getConsumerNumber());
@@ -499,12 +500,12 @@
}
}
- public boolean isRejectedBy(ConsumerImpl consumer)
+ public boolean isRejectedBy(MessageInstanceConsumer consumer)
{
if (_rejectedBy != null) // We have consumers that rejected this message
{
- return _rejectedBy.contains(consumer.getConsumerNumber());
+ return _rejectedBy.contains(consumer.getIdentifier());
}
else // This message hasn't been rejected yet.
{
@@ -525,10 +526,10 @@
{
if (state instanceof ConsumerAcquiredState)
{
- getQueue().decrementUnackedMsgCount(this);
+ _queueEntryList.onNoLongerAcquiredByConsumer(this);
}
- getQueue().dequeue(this);
+ _queueEntryList.dequeue(this);
if(_stateChangeListeners != null)
{
notifyStateChange(state, DEQUEUED_STATE);
@@ -582,55 +583,10 @@
}
}
- public int routeToAlternate(final Action<? super MessageInstance> action, ServerTransaction txn)
+ public int routeToAlternate(final Action<? super BaseMessageInstance> action, ServerTransaction txn)
{
- if (!isAcquired())
- {
- throw new IllegalStateException("Illegal queue entry state. " + this + " is not acquired.");
- }
+ return _queueEntryList.routeToAlternate(this, action, txn);
- final Queue<?> currentQueue = getQueue();
- Exchange<?> alternateExchange = currentQueue.getAlternateExchange();
- boolean autocommit = txn == null;
- int enqueues;
-
- if(autocommit)
- {
- txn = new LocalTransaction(getQueue().getVirtualHost().getMessageStore());
- }
-
- if (alternateExchange != null)
- {
- enqueues = alternateExchange.send(getMessage(),
- getMessage().getInitialRoutingAddress(),
- getInstanceProperties(),
- txn,
- action);
- }
- else
- {
- enqueues = 0;
- }
-
- txn.dequeue(getEnqueueRecord(), new ServerTransaction.Action()
- {
- public void postCommit()
- {
- delete();
- }
-
- public void onRollback()
- {
-
- }
- });
-
- if(autocommit)
- {
- txn.commit();
- }
-
- return enqueues;
}
public boolean isQueueDeleted()
@@ -692,7 +648,7 @@
@Override
public int getMaximumDeliveryCount()
{
- return getQueue().getMaximumDeliveryAttempts();
+ return _queueEntryList.getMaximumDeliveryAttempts();
}
public void incrementDeliveryCount()
@@ -723,7 +679,7 @@
@Override
public boolean resend()
{
- QueueConsumer sub = getDeliveredConsumer();
+ AcquiringMessageInstanceConsumer<?,?> sub = getDeliveredConsumer();
if(sub != null)
{
return sub.resend(this);
@@ -734,7 +690,7 @@
@Override
public TransactionLogResource getOwningResource()
{
- return getQueue();
+ return _queueEntryList.getQueue();
}
public void setRedelivered()
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
index c97e58b..37e0868 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryList.java
@@ -20,13 +20,16 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.store.MessageEnqueueRecord;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
public interface QueueEntryList
{
- Queue<?> getQueue();
+ RecoverableBaseQueue getQueue();
QueueEntry add(ServerMessage message, final MessageEnqueueRecord enqueueRecord);
@@ -44,4 +47,17 @@
int getPriorities();
+ void onAcquiredByConsumer(QueueEntry queueEntry, final MessageInstanceConsumer consumer);
+
+ void onNoLongerAcquiredByConsumer(QueueEntry queueEntry);
+
+ void requeue(QueueEntry queueEntry);
+
+ boolean isHeld(QueueEntry queueEntry, long evaluationTime);
+
+ void dequeue(QueueEntry queueEntry);
+
+ int routeToAlternate(QueueEntry queueEntry, Action<? super BaseMessageInstance> action, ServerTransaction txn);
+
+ int getMaximumDeliveryAttempts();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/queue/RecoverableBaseQueue.java
similarity index 70%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/queue/RecoverableBaseQueue.java
index d2aff53..53a9e67 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/RecoverableBaseQueue.java
@@ -20,6 +20,15 @@
*/
package org.apache.qpid.server.queue;
-public interface QueueEntryListBase extends QueueEntryList
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.store.MessageEnqueueRecord;
+
+public interface RecoverableBaseQueue extends BaseQueue
{
+ void recover(ServerMessage<?> message, MessageEnqueueRecord record);
+
+ void completeRecovery();
+
+ VirtualHost<?> getVirtualHost();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java b/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java
index 0c8f541..4a1e81d 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/SortedQueueEntryList.java
@@ -20,9 +20,13 @@
*/
package org.apache.qpid.server.queue;
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.SortedQueueEntry.Colour;
import org.apache.qpid.server.store.MessageEnqueueRecord;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
/**
* A sorted implementation of QueueEntryList.
@@ -52,6 +56,50 @@
return _queue;
}
+
+ @Override
+ public void onAcquiredByConsumer(final QueueEntry queueEntry, final MessageInstanceConsumer consumer)
+ {
+ getQueue().incrementUnackedMsgCount(queueEntry);
+ }
+
+ @Override
+ public void onNoLongerAcquiredByConsumer(final QueueEntry queueEntry)
+ {
+ getQueue().decrementUnackedMsgCount(queueEntry);
+ }
+
+ @Override
+ public void requeue(final QueueEntry queueEntry)
+ {
+ getQueue().requeue(queueEntry);
+ }
+
+ @Override
+ public boolean isHeld(final QueueEntry queueEntry, final long evaluationTime)
+ {
+ return getQueue().isHeld(queueEntry, evaluationTime);
+ }
+
+ @Override
+ public void dequeue(final QueueEntry queueEntry)
+ {
+ getQueue().dequeue(queueEntry);
+ }
+
+ @Override
+ public int routeToAlternate(final QueueEntry queueEntry, final Action<? super BaseMessageInstance> action, ServerTransaction txn)
+ {
+ return getQueue().routeToAlternate(queueEntry, action, txn);
+ }
+
+ @Override
+ public int getMaximumDeliveryAttempts()
+ {
+ return getQueue().getMaximumDeliveryAttempts();
+ }
+
+
public SortedQueueEntry add(final ServerMessage message, final MessageEnqueueRecord enqueueRecord)
{
synchronized(_lock)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/AbstractKeyStore.java b/broker-core/src/main/java/org/apache/qpid/server/security/AbstractKeyStore.java
index bff091f..9a952e3 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/AbstractKeyStore.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/AbstractKeyStore.java
@@ -37,9 +37,9 @@
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.messages.KeyStoreMessages;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.IntegrityViolationException;
import org.apache.qpid.server.model.KeyStore;
@@ -115,7 +115,7 @@
else
{
final int frequency = checkFrequency;
- getBroker().addChangeListener(new ConfigurationChangeListener()
+ getBroker().addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
@@ -135,38 +135,6 @@
}
}
- @Override
- public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
- {
-
- }
-
- @Override
- public void childRemoved(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
- {
-
- }
-
- @Override
- public void attributeSet(final ConfiguredObject<?> object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
-
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
});
}
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/TrustStoreMessageSource.java b/broker-core/src/main/java/org/apache/qpid/server/security/TrustStoreMessageSource.java
index 82f3702..3da95f6 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/TrustStoreMessageSource.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/TrustStoreMessageSource.java
@@ -35,21 +35,20 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
import org.apache.qpid.server.filter.FilterManager;
-import org.apache.qpid.server.message.MessageSource;
+import org.apache.qpid.server.message.ConsumerOption;
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.ConfigurationChangeListener;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.TrustStore;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.virtualhost.AbstractSystemMessageSource;
-public class TrustStoreMessageSource extends AbstractSystemMessageSource implements MessageSource
+public class TrustStoreMessageSource extends AbstractSystemMessageSource
{
private static final Logger LOGGER = LoggerFactory.getLogger(TrustStoreMessageSource.class);
@@ -63,7 +62,7 @@
super(getSourceNameFromTrustStore(trustStore), virtualHost);
_virtualHost = virtualHost;
_trustStore = trustStore;
- _trustStore.addChangeListener(new ConfigurationChangeListener()
+ _trustStore.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
@@ -75,18 +74,6 @@
}
@Override
- public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
- {
-
- }
-
- @Override
- public void childRemoved(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
- {
-
- }
-
- @Override
public void attributeSet(final ConfiguredObject<?> object,
final String attributeName,
final Object oldAttributeValue,
@@ -95,17 +82,7 @@
updateCertCache();
}
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
});
if(_trustStore.getState() == State.ACTIVE)
{
@@ -114,15 +91,16 @@
}
@Override
- public Consumer addConsumer(final ConsumerTarget target,
- final FilterManager filters,
- final Class<? extends ServerMessage> messageClass,
- final String consumerName,
- final EnumSet<ConsumerImpl.Option> options, final Integer priority)
+ public SystemMessageSourceConsumer addConsumer(final ConsumerTarget target,
+ final FilterManager filters,
+ final Class<? extends ServerMessage> messageClass,
+ final String consumerName,
+ final EnumSet<ConsumerOption> options, final Integer priority)
throws ExistingExclusiveConsumer, ExistingConsumerPreventsExclusive,
ConsumerAccessRefused
{
- final Consumer consumer = super.addConsumer(target, filters, messageClass, consumerName, options, priority);
+ final SystemMessageSourceConsumer
+ consumer = super.addConsumer(target, filters, messageClass, consumerName, options, priority);
consumer.send(createMessage());
target.queueEmpty();
return consumer;
@@ -141,7 +119,7 @@
{
InternalMessage message = createMessage();
- for(Consumer c : new ArrayList<>(getConsumers()))
+ for(SystemMessageSourceConsumer c : new ArrayList<>(getConsumers()))
{
c.send(message);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/TrustStoreMessageSourceCreator.java b/broker-core/src/main/java/org/apache/qpid/server/security/TrustStoreMessageSourceCreator.java
index c81d19e..d05f9cd 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/TrustStoreMessageSourceCreator.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/TrustStoreMessageSourceCreator.java
@@ -22,8 +22,8 @@
import java.util.Collection;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.TrustStore;
@@ -58,12 +58,8 @@
updateTrustStoreSourceRegistration(registry, trustStore);
trustStore.addChangeListener(trustStoreChangeListener);
}
- broker.addChangeListener(new ConfigurationChangeListener()
+ broker.addChangeListener(new AbstractConfigurationChangeListener()
{
- @Override
- public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
- {
- }
@Override
public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
@@ -90,26 +86,6 @@
}
}
- @Override
- public void attributeSet(final ConfiguredObject<?> object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
-
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
});
}
@@ -141,7 +117,7 @@
}
}
- private class TrustStoreChangeListener implements ConfigurationChangeListener
+ private class TrustStoreChangeListener extends AbstractConfigurationChangeListener
{
private final SystemNodeRegistry _registry;
@@ -159,19 +135,6 @@
updateTrustStoreSourceRegistration(_registry, (TrustStore<?>)object);
}
-
- @Override
- public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
- {
-
- }
-
- @Override
- public void childRemoved(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
- {
-
- }
-
@Override
public void attributeSet(final ConfiguredObject<?> object,
final String attributeName,
@@ -181,16 +144,5 @@
updateTrustStoreSourceRegistration(_registry, (TrustStore<?>)object);
}
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
}
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java b/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java
index d5cd49d..e596ab9 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java
@@ -36,13 +36,12 @@
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener;
import org.apache.qpid.server.filter.FilterSupport;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.Binding;
-import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.Queue;
-import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.VirtualHostNode;
@@ -627,13 +626,8 @@
}
});
}
- _virtualHostNode.addChangeListener(new ConfigurationChangeListener()
+ _virtualHostNode.addChangeListener(new AbstractConfigurationChangeListener()
{
- @Override
- public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
- {
-
- }
@Override
public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
@@ -665,26 +659,6 @@
}
}
- @Override
- public void attributeSet(final ConfiguredObject<?> object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
-
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
});
if(isNew)
{
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transfer/OutboundTransferDestination.java b/broker-core/src/main/java/org/apache/qpid/server/transfer/OutboundTransferDestination.java
new file mode 100644
index 0000000..96e5918
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transfer/OutboundTransferDestination.java
@@ -0,0 +1,112 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.transfer;
+
+import java.security.AccessControlException;
+import java.util.Map;
+
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.NamedAddressSpace;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.security.SecurityToken;
+import org.apache.qpid.server.store.MessageEnqueueRecord;
+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.VirtualHostUnavailableException;
+
+public class OutboundTransferDestination implements MessageDestination
+{
+ private final VirtualHost<?> _virtualHost;
+ private final String _address;
+
+ public OutboundTransferDestination(final VirtualHost<?> virtualHost, final String address)
+ {
+ _virtualHost = virtualHost;
+ _address = address;
+ }
+
+ @Override
+ public String getName()
+ {
+ return "$transfer";
+ }
+
+ @Override
+ public NamedAddressSpace getAddressSpace()
+ {
+ return _virtualHost;
+ }
+
+ @Override
+ public void authorisePublish(final SecurityToken token, final Map<String, Object> arguments)
+ throws AccessControlException
+ {
+
+ }
+
+ @Override
+ public <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message,
+ final String routingAddress,
+ final InstanceProperties instanceProperties,
+ final ServerTransaction txn,
+ final Action<? super BaseMessageInstance> postEnqueueAction)
+ {
+ if (_virtualHost.getState() != State.ACTIVE)
+ {
+ throw new VirtualHostUnavailableException(this._virtualHost);
+ }
+
+
+ final TransferQueue transferQueue = _virtualHost.getTransferQueue();
+ txn.enqueue(transferQueue, message, new ServerTransaction.EnqueueAction()
+ {
+ MessageReference _reference = message.newReference();
+
+ public void postCommit(MessageEnqueueRecord... records)
+ {
+ try
+ {
+ for (final MessageEnqueueRecord record : records)
+ {
+ transferQueue.enqueue(message, postEnqueueAction, record);
+ }
+ }
+ finally
+ {
+ _reference.release();
+ }
+ }
+
+ public void onRollback()
+ {
+ _reference.release();
+ }
+ });
+ return 1;
+
+ }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transfer/QueueContext.java b/broker-core/src/main/java/org/apache/qpid/server/transfer/QueueContext.java
new file mode 100755
index 0000000..183b4e3
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transfer/QueueContext.java
@@ -0,0 +1,66 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.qpid.server.transfer;
+
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+import org.apache.qpid.server.queue.QueueEntry;
+
+final class QueueContext
+{
+ private volatile QueueEntry _lastSeenEntry;
+ private volatile QueueEntry _releasedEntry;
+
+ static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry>
+ _lastSeenUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (QueueContext.class, QueueEntry.class, "_lastSeenEntry");
+ static final AtomicReferenceFieldUpdater<QueueContext, QueueEntry>
+ _releasedUpdater =
+ AtomicReferenceFieldUpdater.newUpdater
+ (QueueContext.class, QueueEntry.class, "_releasedEntry");
+
+ public QueueContext(QueueEntry head)
+ {
+ _lastSeenEntry = head;
+ }
+
+ public QueueEntry getLastSeenEntry()
+ {
+ return _lastSeenEntry;
+ }
+
+
+ QueueEntry getReleasedEntry()
+ {
+ return _releasedEntry;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "QueueContext{" +
+ "_lastSeenEntry=" + _lastSeenEntry +
+ ", _releasedEntry=" + _releasedEntry +
+ '}';
+ }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueue.java
similarity index 69%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueue.java
index d2aff53..cce739b 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueue.java
@@ -18,8 +18,13 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.transfer;
-public interface QueueEntryListBase extends QueueEntryList
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.queue.RecoverableBaseQueue;
+
+public interface TransferQueue extends RecoverableBaseQueue, MessageDestination
{
+ TransferQueueConsumer addConsumer(TransferTarget target,
+ String consumerName);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueConsumer.java b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueConsumer.java
new file mode 100644
index 0000000..0547fee
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueConsumer.java
@@ -0,0 +1,225 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.transfer;
+
+import java.util.Collection;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.regex.Pattern;
+
+import org.apache.qpid.server.message.AcquiringMessageInstanceConsumer;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.queue.QueueEntry;
+
+public class TransferQueueConsumer implements AcquiringMessageInstanceConsumer<TransferQueueConsumer, TransferTarget>
+{
+ private final TransferQueueImpl _transferQueue;
+ private final TransferTarget _target;
+ private final String _name;
+
+ private final ConcurrentLinkedQueue<TransferQueueEntry> _entries = new ConcurrentLinkedQueue<>();
+ private final Pattern _matchPattern;
+ private volatile QueueContext _queueContext;
+
+
+ private final MessageInstance.StealableConsumerAcquiredState<TransferQueueConsumer>
+ _owningState = new MessageInstance.StealableConsumerAcquiredState<>(this);
+ private final Object _identifier = new Object();
+
+
+ TransferQueueConsumer(final TransferQueueImpl transferQueue,
+ final TransferTarget target,
+ final String consumerName)
+ {
+ _transferQueue = transferQueue;
+ _target = target;
+ _name = consumerName;
+
+ Collection<String> globalAddressDomains = _target.getGlobalAddressDomains();
+ StringBuilder matchPattern = new StringBuilder();
+ boolean isFirst = true;
+ for(String domain : globalAddressDomains)
+ {
+ if(isFirst)
+ {
+ isFirst = false;
+ }
+ else
+ {
+ matchPattern.append('|');
+ }
+ matchPattern.append('(');
+ matchPattern.append(Pattern.quote(domain.endsWith("/") ? domain : (domain + "/")));
+ matchPattern.append(".*)");
+ }
+ _matchPattern = Pattern.compile(matchPattern.toString());
+ }
+
+ boolean hasInterest(final QueueEntry entry)
+ {
+ String initialRoutingAddress = entry.getMessage().getInitialRoutingAddress();
+ boolean matches = _matchPattern.matcher(initialRoutingAddress).matches();
+ return matches;
+ }
+
+ public boolean processPending()
+ {
+ if(!isSuspended())
+ {
+ TransferQueueEntry entry = _transferQueue.getNextAvailableEntry(this);
+ if(entry != null && !wouldSuspend(entry))
+ {
+ if (!entry.acquire(this))
+ {
+ // restore credit here that would have been taken away by wouldSuspend since we didn't manage
+ // to acquire the entry for this consumer
+ restoreCredit(entry);
+ }
+ else
+ {
+ _transferQueue.setLastSeenEntry(this, entry);
+
+ send(entry);
+ return true;
+ }
+ }
+
+ }
+ return false;
+ }
+
+ void setQueueContext(final QueueContext queueContext)
+ {
+ _queueContext = queueContext;
+ }
+
+ QueueContext getQueueContext()
+ {
+ return _queueContext;
+ }
+
+ @Override
+ public MessageInstance.StealableConsumerAcquiredState<TransferQueueConsumer> getOwningState()
+ {
+ return _owningState;
+ }
+
+ public boolean isSuspended()
+ {
+ return _target.isSuspended();
+ }
+
+ boolean wouldSuspend(final TransferQueueEntry entry)
+ {
+ return _target.wouldSuspend(entry);
+ }
+
+ public TransferTarget getTarget()
+ {
+ return _target;
+ }
+
+ @Override
+ public void acquisitionRemoved(final QueueEntry queueEntry)
+ {
+
+ }
+
+ @Override
+ public long getConsumerNumber()
+ {
+ return 0;
+ }
+
+ @Override
+ public boolean resend(final QueueEntry queueEntry)
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isClosed()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean acquires()
+ {
+ return true;
+ }
+
+ @Override
+ public String getName()
+ {
+ return "$transfer";
+ }
+
+ @Override
+ public void close()
+ {
+
+ }
+
+ @Override
+ public void flush()
+ {
+
+ }
+
+ @Override
+ public void externalStateChange()
+ {
+
+ }
+
+ @Override
+ public Object getIdentifier()
+ {
+ return _identifier;
+ }
+
+ @Override
+ public boolean hasAvailableMessages()
+ {
+ return _transferQueue.hasAvailableMessages(this);
+ }
+
+ @Override
+ public void pullMessage()
+ {
+
+ }
+
+ public void send(final TransferQueueEntry entry)
+ {
+ _target.send(entry);
+ }
+
+ public void restoreCredit(final TransferQueueEntry entry)
+ {
+ _target.restoreCredit(entry.getMessage());
+ }
+
+ public void notifyWork()
+ {
+ _target.notifyWork();
+ }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueEntry.java b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueEntry.java
new file mode 100644
index 0000000..8931bd4
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueEntry.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.transfer;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.queue.OrderedQueueEntry;
+import org.apache.qpid.server.store.MessageEnqueueRecord;
+
+public class TransferQueueEntry extends OrderedQueueEntry
+{
+
+ protected TransferQueueEntry(final TransferQueueEntryList queueEntryList)
+ {
+ super(queueEntryList);
+ }
+
+ public TransferQueueEntry(final TransferQueueEntryList queueEntryList,
+ final ServerMessage message,
+ final MessageEnqueueRecord messageEnqueueRecord)
+ {
+ super(queueEntryList, message, messageEnqueueRecord);
+ }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueEntryList.java b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueEntryList.java
new file mode 100644
index 0000000..c8c632e
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueEntryList.java
@@ -0,0 +1,102 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.transfer;
+
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.queue.OrderedBaseQueueEntryList;
+import org.apache.qpid.server.queue.OrderedQueueEntry;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.QueueEntryList;
+import org.apache.qpid.server.store.MessageEnqueueRecord;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+
+public class TransferQueueEntryList extends OrderedBaseQueueEntryList<TransferQueue>
+{
+
+ private static final HeadCreator HEAD_CREATOR = new HeadCreator()
+ {
+ @Override
+ public TransferQueueEntry createHead(final QueueEntryList list)
+ {
+ return new TransferQueueEntry((TransferQueueEntryList) list);
+ }
+ };
+
+ public TransferQueueEntryList(final TransferQueue queue)
+ {
+ super(queue, HEAD_CREATOR);
+ }
+
+
+ @Override
+ protected OrderedQueueEntry createQueueEntry(final ServerMessage<?> message,
+ final MessageEnqueueRecord enqueueRecord)
+ {
+ return new TransferQueueEntry(this, message, enqueueRecord);
+ }
+
+ @Override
+ public void onAcquiredByConsumer(final QueueEntry queueEntry, final MessageInstanceConsumer consumer)
+ {
+
+ }
+
+ @Override
+ public void onNoLongerAcquiredByConsumer(final QueueEntry queueEntry)
+ {
+
+ }
+
+ @Override
+ public void requeue(final QueueEntry queueEntry)
+ {
+
+ }
+
+ @Override
+ public boolean isHeld(final QueueEntry queueEntry, final long evaluationTime)
+ {
+ return false;
+ }
+
+ @Override
+ public void dequeue(final QueueEntry queueEntry)
+ {
+
+ }
+
+ @Override
+ public int routeToAlternate(final QueueEntry queueEntry,
+ final Action<? super BaseMessageInstance> action,
+ final ServerTransaction txn)
+ {
+ return 0;
+ }
+
+ @Override
+ public int getMaximumDeliveryAttempts()
+ {
+ return 0;
+ }
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueImpl.java b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueImpl.java
new file mode 100644
index 0000000..ce81bb7
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferQueueImpl.java
@@ -0,0 +1,409 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.transfer;
+
+import java.nio.charset.StandardCharsets;
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageReference;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.NamedAddressSpace;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.security.SecurityToken;
+import org.apache.qpid.server.store.MessageDurability;
+import org.apache.qpid.server.store.MessageEnqueueRecord;
+import org.apache.qpid.server.store.StorableMessageMetaData;
+import org.apache.qpid.server.txn.AutoCommitTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.virtualhost.VirtualHostUnavailableException;
+
+public class TransferQueueImpl implements TransferQueue
+{
+ private static final UUID TRANSFER_QUEUE_ID = UUID.nameUUIDFromBytes("$transfer".getBytes(StandardCharsets.UTF_8));
+
+ private static final int RECOVERING = 1;
+ private static final int COMPLETING_RECOVERY = 2;
+ private static final int RECOVERED = 3;
+
+ private final AtomicInteger _recovering = new AtomicInteger(RECOVERING);
+ private final AtomicInteger _enqueuingWhileRecovering = new AtomicInteger(0);
+
+ private final ConcurrentLinkedQueue<EnqueueRequest> _postRecoveryQueue = new ConcurrentLinkedQueue<>();
+
+ private final VirtualHost<?> _virtualHost;
+
+ private final TransferQueueEntryList _queueEntryList;
+ private Collection<TransferQueueConsumer> _consumers = new CopyOnWriteArrayList<>();
+
+
+ public TransferQueueImpl(final VirtualHost<?> virtualHost)
+ {
+ _virtualHost = virtualHost;
+ _queueEntryList = new TransferQueueEntryList(this);
+ }
+
+ @Override
+ public void enqueue(final ServerMessage message,
+ final Action<? super BaseMessageInstance> action,
+ final MessageEnqueueRecord enqueueRecord)
+ {
+ if(_recovering.get() != RECOVERED)
+ {
+ _enqueuingWhileRecovering.incrementAndGet();
+
+ boolean addedToRecoveryQueue;
+ try
+ {
+ if(addedToRecoveryQueue = (_recovering.get() == RECOVERING))
+ {
+ _postRecoveryQueue.add(new EnqueueRequest(message, action, enqueueRecord));
+ }
+ }
+ finally
+ {
+ _enqueuingWhileRecovering.decrementAndGet();
+ }
+
+ if(!addedToRecoveryQueue)
+ {
+ while(_recovering.get() != RECOVERED)
+ {
+ Thread.yield();
+ }
+ doEnqueue(message, action, enqueueRecord);
+ }
+ }
+ else
+ {
+ doEnqueue(message, action, enqueueRecord);
+ }
+
+
+ }
+
+ @Override
+ public void recover(final ServerMessage<?> message, final MessageEnqueueRecord enqueueRecord)
+ {
+ doEnqueue(message, null, enqueueRecord);
+ }
+
+ @Override
+ public final void completeRecovery()
+ {
+ if(_recovering.compareAndSet(RECOVERING, COMPLETING_RECOVERY))
+ {
+ while(_enqueuingWhileRecovering.get() != 0)
+ {
+ Thread.yield();
+ }
+
+ // at this point we can assert that any new enqueue to the queue will not try to put into the post recovery
+ // queue (because the state is no longer RECOVERING, but also no threads are currently trying to enqueue
+ // because the _enqueuingWhileRecovering count is 0.
+
+ enqueueFromPostRecoveryQueue();
+
+ _recovering.set(RECOVERED);
+
+ }
+ }
+
+ @Override
+ public VirtualHost<?> getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+ private void enqueueFromPostRecoveryQueue()
+ {
+ while(!_postRecoveryQueue.isEmpty())
+ {
+ EnqueueRequest request = _postRecoveryQueue.poll();
+ MessageReference<?> messageReference = request.getMessage();
+ doEnqueue(messageReference.getMessage(), request.getAction(), request.getEnqueueRecord());
+ messageReference.release();
+ }
+ }
+
+
+
+ protected void doEnqueue(final ServerMessage message, final Action<? super BaseMessageInstance> action, MessageEnqueueRecord enqueueRecord)
+ {
+ final TransferQueueEntry entry = (TransferQueueEntry) _queueEntryList.add(message, enqueueRecord);
+ for (TransferQueueConsumer consumer : getConsumers())
+ {
+ if (consumer.hasInterest(entry))
+ {
+ consumer.notifyWork();
+ }
+ }
+ }
+
+ private Collection<TransferQueueConsumer> getConsumers()
+ {
+ return _consumers;
+ }
+
+ @Override
+ public TransferQueueConsumer addConsumer(final TransferTarget target,
+ final String consumerName)
+ {
+
+
+
+ TransferQueueConsumer consumer = new TransferQueueConsumer(this,
+ target,
+ consumerName);
+
+ QueueContext queueContext = new QueueContext(_queueEntryList.getHead());
+ consumer.setQueueContext(queueContext);
+ _consumers.add(consumer);
+ consumer.notifyWork();
+
+ return consumer;
+ }
+
+ boolean hasAvailableMessages(final TransferQueueConsumer queueConsumer)
+ {
+ return getNextAvailableEntry(queueConsumer) != null;
+ }
+
+
+ void setLastSeenEntry(final TransferQueueConsumer sub, final TransferQueueEntry entry)
+ {
+ QueueContext subContext = sub.getQueueContext();
+ if (subContext != null)
+ {
+ QueueEntry releasedEntry = subContext.getReleasedEntry();
+
+ QueueContext._lastSeenUpdater.set(subContext, entry);
+ if(releasedEntry == entry)
+ {
+ QueueContext._releasedUpdater.compareAndSet(subContext, releasedEntry, null);
+ }
+ }
+ }
+
+ TransferQueueEntry getNextAvailableEntry(final TransferQueueConsumer sub)
+ {
+ QueueContext context = sub.getQueueContext();
+ if(context != null)
+ {
+ QueueEntry lastSeen = context.getLastSeenEntry();
+ QueueEntry releasedNode = context.getReleasedEntry();
+
+ TransferQueueEntry node =
+ (TransferQueueEntry) ((releasedNode != null && lastSeen.compareTo(releasedNode) >= 0)
+ ? releasedNode : _queueEntryList.next(lastSeen));
+
+ boolean expired = false;
+ while (node != null
+ && (!node.isAvailable()
+ || (expired = node.expired())
+ || !sub.hasInterest(node)))
+ {
+ if (expired)
+ {
+ expired = false;
+ if (node.acquire())
+ {
+ dequeueEntry(node);
+ }
+ }
+
+ if(QueueContext._lastSeenUpdater.compareAndSet(context, lastSeen, node))
+ {
+ QueueContext._releasedUpdater.compareAndSet(context, releasedNode, null);
+ }
+
+ lastSeen = context.getLastSeenEntry();
+ releasedNode = context.getReleasedEntry();
+ node = (TransferQueueEntry) ((releasedNode != null && lastSeen.compareTo(releasedNode) >= 0)
+ ? releasedNode
+ : _queueEntryList.next(lastSeen));
+ }
+ return node;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private void dequeueEntry(final QueueEntry node)
+ {
+ ServerTransaction txn = new AutoCommitTransaction(_virtualHost.getMessageStore());
+ dequeueEntry(node, txn);
+ }
+
+ private void dequeueEntry(final QueueEntry node, ServerTransaction txn)
+ {
+ txn.dequeue(node.getEnqueueRecord(),
+ new ServerTransaction.Action()
+ {
+
+ public void postCommit()
+ {
+ node.delete();
+ }
+
+ public void onRollback()
+ {
+
+ }
+ });
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isDeleted()
+ {
+ return false;
+ }
+
+ @Override
+ public String getName()
+ {
+ return "$transfer";
+ }
+
+ @Override
+ public NamedAddressSpace getAddressSpace()
+ {
+ return _virtualHost;
+ }
+
+ @Override
+ public void authorisePublish(final SecurityToken token, final Map<String, Object> arguments)
+ throws AccessControlException
+ {
+ // TODO
+ }
+
+ @Override
+ public <M extends ServerMessage<? extends StorableMessageMetaData>> int send(final M message,
+ final String routingAddress,
+ final InstanceProperties instanceProperties,
+ final ServerTransaction txn,
+ final Action<? super BaseMessageInstance> postEnqueueAction)
+ {
+ if (_virtualHost.getState() != State.ACTIVE)
+ {
+ throw new VirtualHostUnavailableException(this._virtualHost);
+ }
+
+ if(!message.isReferenced(this))
+ {
+ txn.enqueue(this, message, new ServerTransaction.EnqueueAction()
+ {
+ MessageReference _reference = message.newReference();
+
+ public void postCommit(MessageEnqueueRecord... records)
+ {
+ try
+ {
+ TransferQueueImpl.this.enqueue(message, postEnqueueAction, records[0]);
+ }
+ finally
+ {
+ _reference.release();
+ }
+ }
+
+ public void onRollback()
+ {
+ _reference.release();
+ }
+ });
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return TRANSFER_QUEUE_ID;
+ }
+
+ @Override
+ public MessageDurability getMessageDurability()
+ {
+ return MessageDurability.DEFAULT;
+ }
+
+ public void flushConsumer(final TransferQueueConsumer consumer, final int count)
+ {
+
+ }
+
+ private static class EnqueueRequest
+ {
+ private final MessageReference<?> _message;
+ private final Action<? super BaseMessageInstance> _action;
+ private final MessageEnqueueRecord _enqueueRecord;
+
+ public EnqueueRequest(final ServerMessage message,
+ final Action<? super BaseMessageInstance> action,
+ final MessageEnqueueRecord enqueueRecord)
+ {
+ _enqueueRecord = enqueueRecord;
+ _message = message.newReference();
+ _action = action;
+ }
+
+ public MessageReference<?> getMessage()
+ {
+ return _message;
+ }
+
+ public Action<? super BaseMessageInstance> getAction()
+ {
+ return _action;
+ }
+
+ public MessageEnqueueRecord getEnqueueRecord()
+ {
+ return _enqueueRecord;
+ }
+ }
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferTarget.java
similarity index 66%
copy from broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
copy to broker-core/src/main/java/org/apache/qpid/server/transfer/TransferTarget.java
index d2aff53..7539dd5 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryListBase.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transfer/TransferTarget.java
@@ -18,8 +18,24 @@
* under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.transfer;
-public interface QueueEntryListBase extends QueueEntryList
+import java.util.Collection;
+
+import org.apache.qpid.server.message.ServerMessage;
+
+public interface TransferTarget
{
+
+ void notifyWork();
+
+ Collection<String> getGlobalAddressDomains();
+
+ void send(TransferQueueEntry entry);
+
+ void restoreCredit(ServerMessage message);
+
+ boolean wouldSuspend(TransferQueueEntry entry);
+
+ boolean isSuspended();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/AbstractAMQPConnection.java b/broker-core/src/main/java/org/apache/qpid/server/transport/AbstractAMQPConnection.java
index fe5a219..bb77538 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/AbstractAMQPConnection.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/AbstractAMQPConnection.java
@@ -331,18 +331,18 @@
@Override
public void pushScheduler(final NetworkConnectionScheduler networkConnectionScheduler)
{
- if(_network instanceof NonBlockingConnection)
+ if(_network instanceof NonBlockingInboundConnection)
{
- ((NonBlockingConnection) _network).pushScheduler(networkConnectionScheduler);
+ ((NonBlockingInboundConnection) _network).pushScheduler(networkConnectionScheduler);
}
}
@Override
public NetworkConnectionScheduler popScheduler()
{
- if(_network instanceof NonBlockingConnection)
+ if(_network instanceof NonBlockingInboundConnection)
{
- return ((NonBlockingConnection) _network).popScheduler();
+ return ((NonBlockingInboundConnection) _network).popScheduler();
}
return null;
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/NetworkConnectionScheduler.java b/broker-core/src/main/java/org/apache/qpid/server/transport/NetworkConnectionScheduler.java
index 9828d46..faa327f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/NetworkConnectionScheduler.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/NetworkConnectionScheduler.java
@@ -119,7 +119,7 @@
}
}
- void processConnection(final NonBlockingConnection connection)
+ void processConnection(final SchedulableConnection connection)
{
Thread.currentThread().setName(connection.getThreadName());
connection.doPreWork();
@@ -235,12 +235,12 @@
return _selectorThread.cancelAcceptingSocket(serverSocket);
}
- public void addConnection(final NonBlockingConnection connection)
+ public void addConnection(final SchedulableConnection connection)
{
_selectorThread.addConnection(connection);
}
- public void removeConnection(final NonBlockingConnection connection)
+ public void removeConnection(final SchedulableConnection connection)
{
_selectorThread.removeConnection(connection);
}
@@ -250,7 +250,7 @@
return _poolSize;
}
- public void schedule(final NonBlockingConnection connection)
+ public void schedule(final SchedulableConnection connection)
{
_selectorThread.addToWork(connection);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java
index 7eaa721..ff64fe8 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnection.java
@@ -1,5 +1,5 @@
/*
-*
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -29,7 +29,6 @@
import java.util.Deque;
import java.util.Iterator;
import java.util.List;
-import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -40,231 +39,232 @@
import org.slf4j.LoggerFactory;
import org.apache.qpid.bytebuffer.QpidByteBuffer;
-import org.apache.qpid.server.model.port.AmqpPort;
import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
import org.apache.qpid.transport.ByteBufferSender;
import org.apache.qpid.transport.network.Ticker;
-import org.apache.qpid.transport.network.TransportEncryption;
import org.apache.qpid.util.SystemUtils;
-public class NonBlockingConnection implements ServerNetworkConnection, ByteBufferSender
+public abstract class NonBlockingConnection implements SchedulableConnection
{
private static final Logger LOGGER = LoggerFactory.getLogger(NonBlockingConnection.class);
+ final AtomicLong _usedOutboundMessageSpace = new AtomicLong();
private final SocketChannel _socketChannel;
- private NonBlockingConnectionDelegate _delegate;
private final Deque<NetworkConnectionScheduler> _schedulerDeque = new ConcurrentLinkedDeque<>();
- private final ConcurrentLinkedQueue<QpidByteBuffer> _buffers = new ConcurrentLinkedQueue<>();
-
- private final String _remoteSocketAddress;
- private final AtomicBoolean _closed = new AtomicBoolean(false);
- private final ProtocolEngine _protocolEngine;
- private final Runnable _onTransportEncryptionAction;
- private final AtomicLong _usedOutboundMessageSpace = new AtomicLong();
- private final long _outboundMessageBufferLimit;
-
- private volatile boolean _fullyWritten = true;
-
- private boolean _partialRead = false;
-
- private final AmqpPort _port;
+ private final String _remoteAddressString;
private final AtomicBoolean _scheduled = new AtomicBoolean();
- private volatile long _scheduledTime;
- private volatile boolean _unexpectedByteBufferSizeReported;
- private final String _threadName;
- private volatile SelectorThread.SelectionTask _selectionTask;
- private Iterator<Runnable> _pendingIterator;
private final AtomicLong _maxWriteIdleMillis = new AtomicLong();
private final AtomicLong _maxReadIdleMillis = new AtomicLong();
- private final List<SchedulingDelayNotificationListener> _schedulingDelayNotificationListeners = new CopyOnWriteArrayList<>();
- private final AtomicBoolean _hasShutdown = new AtomicBoolean();
+ private final List<SchedulingDelayNotificationListener>
+ _schedulingDelayNotificationListeners = new CopyOnWriteArrayList<>();
+ private final String _threadName;
+ private final ConcurrentLinkedQueue<QpidByteBuffer> _buffers = new ConcurrentLinkedQueue<>();
+ private NonBlockingConnectionDelegate _delegate;
+ private final AtomicBoolean _closed = new AtomicBoolean(false);
- public NonBlockingConnection(SocketChannel socketChannel,
- ProtocolEngine protocolEngine,
- final Set<TransportEncryption> encryptionSet,
- final Runnable onTransportEncryptionAction,
- final NetworkConnectionScheduler scheduler,
- final AmqpPort port)
+ private volatile SelectorThread.SelectionTask _selectionTask;
+ private volatile long _scheduledTime;
+ private final AtomicBoolean _hasShutdown = new AtomicBoolean();
+ private final AtomicBoolean _unexpectedByteBufferSizeReported = new AtomicBoolean();
+ private final ProtocolEngine _protocolEngine;
+ private volatile Iterator<Runnable> _pendingIterator;
+ private volatile boolean _fullyWritten = true;
+ private volatile boolean _partialRead = false;
+
+ protected NonBlockingConnection(final SocketChannel socketChannel, ProtocolEngine protocolEngine,
+ final NetworkConnectionScheduler scheduler,
+ String remoteAddressString)
{
_socketChannel = socketChannel;
- pushScheduler(scheduler);
-
_protocolEngine = protocolEngine;
- _onTransportEncryptionAction = onTransportEncryptionAction;
-
- _remoteSocketAddress = _socketChannel.socket().getRemoteSocketAddress().toString();
- _port = port;
- _threadName = SelectorThread.IO_THREAD_NAME_PREFIX + _remoteSocketAddress.toString();
-
- _outboundMessageBufferLimit = (long) _port.getContextValue(Long.class,
- AmqpPort.PORT_AMQP_OUTBOUND_MESSAGE_BUFFER_SIZE);
-
+ _remoteAddressString = remoteAddressString;
+ _threadName = SelectorThread.IO_THREAD_NAME_PREFIX + _remoteAddressString;
+ pushScheduler(scheduler);
protocolEngine.setWorkListener(new Action<ProtocolEngine>()
{
@Override
public void performAction(final ProtocolEngine object)
{
- if(!_scheduled.get())
+ NetworkConnectionScheduler scheduler = getScheduler();
+ if(scheduler != null && !_scheduled.get())
{
getScheduler().schedule(NonBlockingConnection.this);
}
}
});
- if(encryptionSet.size() == 1)
- {
- setTransportEncryption(encryptionSet.iterator().next());
- }
- else
- {
- _delegate = new NonBlockingConnectionUndecidedDelegate(this);
- }
}
- String getThreadName()
+ @Override
+ public final String getThreadName()
{
return _threadName;
}
- public boolean isPartialRead()
+
+ protected final String getRemoteAddressString()
{
- return _partialRead;
+ return _remoteAddressString;
}
- Ticker getTicker()
+ protected final boolean isClosed()
{
- return _protocolEngine.getAggregateTicker();
+ return _closed.get();
}
- SocketChannel getSocketChannel()
+ protected final boolean setClosed()
+ {
+ return _closed.compareAndSet(false,true);
+ }
+
+ @Override
+ public final SocketChannel getSocketChannel()
{
return _socketChannel;
}
+
@Override
- public void start()
+ public final SocketAddress getRemoteAddress()
{
+ return getSocketChannel().socket().getRemoteSocketAddress();
}
@Override
- public ByteBufferSender getSender()
+ public final SocketAddress getLocalAddress()
{
- return this;
+ return getSocketChannel().socket().getLocalSocketAddress();
+ }
+
+
+ public final void pushScheduler(NetworkConnectionScheduler scheduler)
+ {
+ _schedulerDeque.addFirst(scheduler);
+ }
+
+ public final NetworkConnectionScheduler popScheduler()
+ {
+ return _schedulerDeque.removeFirst();
}
@Override
- public void close()
+ public final NetworkConnectionScheduler getScheduler()
{
- LOGGER.debug("Closing " + _remoteSocketAddress);
- if(_closed.compareAndSet(false,true))
- {
- _protocolEngine.notifyWork();
- _selectionTask.wakeup();
- }
+ return _schedulerDeque.peekFirst();
}
@Override
- public SocketAddress getRemoteAddress()
- {
- return _socketChannel.socket().getRemoteSocketAddress();
- }
-
- @Override
- public SocketAddress getLocalAddress()
- {
- return _socketChannel.socket().getLocalSocketAddress();
- }
-
- @Override
- public void setMaxWriteIdleMillis(final long millis)
- {
- _maxWriteIdleMillis.set(millis);
- }
-
- @Override
- public void setMaxReadIdleMillis(final long millis)
- {
- _maxReadIdleMillis.set(millis);
- }
-
- @Override
- public Principal getPeerPrincipal()
+ public final Principal getPeerPrincipal()
{
return _delegate.getPeerPrincipal();
}
@Override
- public Certificate getPeerCertificate()
+ public final Certificate getPeerCertificate()
{
return _delegate.getPeerCertificate();
}
@Override
- public long getMaxReadIdleMillis()
+ public final String getTransportInfo()
+ {
+ return _delegate.getTransportInfo();
+ }
+
+
+ @Override
+ public final SelectorThread.SelectionTask getSelectionTask()
+ {
+ return _selectionTask;
+ }
+
+ @Override
+ public final void setSelectionTask(final SelectorThread.SelectionTask selectionTask)
+ {
+ _selectionTask = selectionTask;
+ }
+
+ @Override
+ public final boolean setScheduled()
+ {
+ final boolean scheduled = _scheduled.compareAndSet(false, true);
+ if (scheduled)
+ {
+ _scheduledTime = System.currentTimeMillis();
+ }
+ return scheduled;
+ }
+
+ @Override
+ public final void clearScheduled()
+ {
+ _scheduled.set(false);
+ _scheduledTime = 0;
+ }
+
+ @Override
+ public final long getScheduledTime()
+ {
+ return _scheduledTime;
+ }
+
+ @Override
+ public final void setMaxWriteIdleMillis(final long millis)
+ {
+ _maxWriteIdleMillis.set(millis);
+ }
+
+ @Override
+ public final void setMaxReadIdleMillis(final long millis)
+ {
+ _maxReadIdleMillis.set(millis);
+ }
+
+ @Override
+ public final long getMaxReadIdleMillis()
{
return _maxReadIdleMillis.get();
}
@Override
- public long getMaxWriteIdleMillis()
+ public final long getMaxWriteIdleMillis()
{
return _maxWriteIdleMillis.get();
}
-
@Override
- public void reserveOutboundMessageSpace(long size)
- {
- if (_usedOutboundMessageSpace.addAndGet(size) > _outboundMessageBufferLimit)
- {
- _protocolEngine.setMessageAssignmentSuspended(true, false);
- }
- }
-
- @Override
- public String getTransportInfo()
- {
- return _delegate.getTransportInfo();
- }
-
- boolean wantsRead()
- {
- return _fullyWritten;
- }
-
- boolean wantsWrite()
- {
- return !_fullyWritten;
- }
-
- public boolean isStateChanged()
+ public final boolean isStateChanged()
{
return _protocolEngine.hasWork();
}
- public void doPreWork()
+ @Override
+ public final boolean wantsRead()
{
- if (!_closed.get())
- {
- long currentTime = System.currentTimeMillis();
- long schedulingDelay = currentTime - getScheduledTime();
- if (!_schedulingDelayNotificationListeners.isEmpty())
- {
- for (SchedulingDelayNotificationListener listener : _schedulingDelayNotificationListeners)
- {
- listener.notifySchedulingDelay(schedulingDelay);
- }
- }
- }
+ return _fullyWritten;
}
+ @Override
+ public final boolean wantsWrite()
+ {
+ return !_fullyWritten;
+ }
+
+ @Override
+ public final boolean isPartialRead()
+ {
+ return _partialRead;
+ }
+
+ @Override
public boolean doWork()
{
_protocolEngine.clearWork();
- if (!_closed.get())
+ try
{
- try
+
+ if (!isClosed() && (!wantsConnect() || completeConnection()))
{
long currentTime = System.currentTimeMillis();
int tick = getTicker().getTimeToNextTick(currentTime);
@@ -278,14 +278,16 @@
boolean processPendingComplete = processPending();
- if(processPendingComplete)
+ if (processPendingComplete)
{
_pendingIterator = null;
_protocolEngine.setTransportBlockedForWriting(false);
boolean dataRead = doRead();
- _protocolEngine.setTransportBlockedForWriting(!doWrite());
+ _fullyWritten = doWrite();
+ _protocolEngine.setTransportBlockedForWriting(!_fullyWritten);
- if (!_fullyWritten || dataRead || (_delegate.needsWork() && _delegate.getNetInputBuffer().position() != 0))
+ if (!_fullyWritten || dataRead || (_delegate.needsWork()
+ && _delegate.getNetInputBuffer().position() != 0))
{
_protocolEngine.notifyWork();
}
@@ -299,34 +301,33 @@
{
_protocolEngine.notifyWork();
}
-
- }
- catch (IOException |
- ConnectionScopedRuntimeException e)
- {
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Exception performing I/O for connection '{}'",
- _remoteSocketAddress, e);
- }
- else
- {
- LOGGER.info("Exception performing I/O for connection '{}' : {}",
- _remoteSocketAddress, e.getMessage());
- }
-
- if(_closed.compareAndSet(false,true))
- {
- _protocolEngine.notifyWork();
- }
- }
- finally
- {
- _protocolEngine.setIOThread(null);
}
}
+ catch (IOException |
+ ConnectionScopedRuntimeException e)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Exception performing I/O for connection '{}'",
+ getRemoteAddressString(), e);
+ }
+ else
+ {
+ LOGGER.info("Exception performing I/O for connection '{}' : {}",
+ getRemoteAddressString(), e.getMessage());
+ }
- final boolean closed = _closed.get();
+ if(setClosed())
+ {
+ _protocolEngine.notifyWork();
+ }
+ }
+ finally
+ {
+ _protocolEngine.setIOThread(null);
+ }
+
+ final boolean closed = isClosed();
if (closed)
{
shutdown();
@@ -336,17 +337,12 @@
}
- @Override
- public void addSchedulingDelayNotificationListeners(final SchedulingDelayNotificationListener listener)
+ private boolean completeConnection() throws IOException
{
- _schedulingDelayNotificationListeners.add(listener);
+ boolean finishConnect = getSocketChannel().finishConnect();
+ return finishConnect && !wantsConnect();
}
- @Override
- public void removeSchedulingDelayNotificationListeners(final SchedulingDelayNotificationListener listener)
- {
- _schedulingDelayNotificationListeners.remove(listener);
- }
private boolean processPending() throws IOException
{
@@ -355,14 +351,14 @@
_pendingIterator = _protocolEngine.processPendingIterator();
}
- final int networkBufferSize = _port.getNetworkBufferSize();
+ final int networkBufferSize = getNetworkBufferSize();
while(_pendingIterator.hasNext())
{
long size = getBufferedSize();
if(size >= networkBufferSize)
{
- doWrite();
+ _fullyWritten = doWrite();
long bytesWritten = size - getBufferedSize();
if(bytesWritten < (networkBufferSize / 2))
{
@@ -379,19 +375,123 @@
boolean complete = !_pendingIterator.hasNext();
if (getBufferedSize() >= networkBufferSize)
{
- doWrite();
+ _fullyWritten = doWrite();
complete &= getBufferedSize() < networkBufferSize /2;
}
return complete;
}
- private long getBufferedSize()
+ protected abstract int getNetworkBufferSize();
+
+
+ @Override
+ public final void doPreWork()
+ {
+ if (!isClosed())
+ {
+ long currentTime = System.currentTimeMillis();
+ long schedulingDelay = currentTime - getScheduledTime();
+ if (!_schedulingDelayNotificationListeners.isEmpty())
+ {
+ for (SchedulingDelayNotificationListener listener : _schedulingDelayNotificationListeners)
+ {
+ listener.notifySchedulingDelay(schedulingDelay);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * doRead is not reentrant.
+ */
+ boolean doRead() throws IOException
+ {
+ _partialRead = false;
+ if(!isClosed() && _delegate.readyForRead())
+ {
+ int readData = readFromNetwork();
+
+ if (readData > 0)
+ {
+ return _delegate.processData();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public long writeToTransport(Collection<QpidByteBuffer> buffers) throws IOException
+ {
+ long written = QpidByteBuffer.write(getSocketChannel(), buffers);
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Written " + written + " bytes");
+ }
+ return written;
+ }
+
+ protected int readFromNetwork() throws IOException
+ {
+ QpidByteBuffer buffer = _delegate.getNetInputBuffer();
+
+ int read = buffer.read(getSocketChannel());
+ if (read == -1)
+ {
+ setClosed();
+ }
+
+ _partialRead = read != 0;
+
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Read " + read + " byte(s)");
+ }
+ return read;
+ }
+
+
+
+
+ @Override
+ public final void addSchedulingDelayNotificationListeners(final SchedulingDelayNotificationListener listener)
+ {
+ _schedulingDelayNotificationListeners.add(listener);
+ }
+
+ @Override
+ public final void removeSchedulingDelayNotificationListeners(final SchedulingDelayNotificationListener listener)
+ {
+ _schedulingDelayNotificationListeners.remove(listener);
+ }
+
+ @Override
+ public final ByteBufferSender getSender()
+ {
+ return this;
+ }
+
+ @Override
+ public final boolean isDirectBufferPreferred()
+ {
+ return true;
+ }
+
+ private final long getBufferedSize()
{
// Avoids iterator garbage if empty
if (_buffers.isEmpty())
{
return 0L;
}
+
long totalSize = 0L;
for(QpidByteBuffer buf : _buffers)
{
@@ -400,7 +500,44 @@
return totalSize;
}
- private void shutdown()
+ final boolean doWrite() throws IOException
+ {
+ boolean fullyWritten = _delegate.doWrite(_buffers);
+ while(!_buffers.isEmpty())
+ {
+ QpidByteBuffer buf = _buffers.peek();
+ if(buf.hasRemaining())
+ {
+ break;
+ }
+ _buffers.poll();
+ buf.dispose();
+ }
+ if (fullyWritten)
+ {
+ _usedOutboundMessageSpace.set(0);
+ }
+ return fullyWritten;
+
+ }
+
+ @Override
+ public final void send(final QpidByteBuffer msg)
+ {
+
+ if (isClosed())
+ {
+ LOGGER.warn("Send ignored as the connection is already closed");
+ }
+ else if (msg.remaining() > 0)
+ {
+ _buffers.add(msg.duplicate());
+ }
+ msg.position(msg.limit());
+ }
+
+
+ protected final void shutdown()
{
if (_hasShutdown.getAndSet(true))
{
@@ -411,7 +548,9 @@
{
shutdownInput();
shutdownFinalWrite();
+
_protocolEngine.closed();
+
shutdownOutput();
}
finally
@@ -428,12 +567,12 @@
}
finally
{
- _socketChannel.close();
+ getSocketChannel().close();
}
}
catch (IOException e)
{
- LOGGER.info("Exception closing socket '{}': {}", _remoteSocketAddress, e.getMessage());
+ LOGGER.info("Exception closing socket '{}': {}", getRemoteAddressString(), e.getMessage());
}
if (SystemUtils.isWindows())
@@ -454,7 +593,7 @@
}
catch (IOException e)
{
- LOGGER.info("Exception performing final write/close for '{}': {}", _remoteSocketAddress, e.getMessage());
+ LOGGER.info("Exception performing final write/close for '{}': {}", getRemoteAddressString(), e.getMessage());
}
}
@@ -464,11 +603,11 @@
{
try
{
- _socketChannel.shutdownOutput();
+ getSocketChannel().shutdownOutput();
}
catch (IOException e)
{
- LOGGER.info("Exception closing socket '{}': {}", _remoteSocketAddress, e.getMessage());
+ LOGGER.info("Exception closing socket '{}': {}", getRemoteAddressString(), e.getMessage());
}
finally
{
@@ -484,11 +623,11 @@
{
try
{
- _socketChannel.shutdownInput();
+ getSocketChannel().shutdownInput();
}
catch (IOException e)
{
- LOGGER.info("Exception shutting down input for '{}': {}", _remoteSocketAddress, e.getMessage());
+ LOGGER.info("Exception shutting down input for '{}': {}", getRemoteAddressString(), e.getMessage());
}
finally
{
@@ -497,197 +636,78 @@
}
}
- /**
- * doRead is not reentrant.
- */
- boolean doRead() throws IOException
+
+ @Override
+ public final void start()
{
- _partialRead = false;
- if(!_closed.get() && _delegate.readyForRead())
- {
- int readData = readFromNetwork();
-
- if (readData > 0)
- {
- return _delegate.processData();
- }
- else
- {
- return false;
- }
- }
- else
- {
- return false;
- }
- }
-
- long writeToTransport(Collection<QpidByteBuffer> buffers) throws IOException
- {
- long written = QpidByteBuffer.write(_socketChannel, buffers);
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Written " + written + " bytes");
- }
- return written;
- }
-
- private boolean doWrite() throws IOException
- {
- _fullyWritten = _delegate.doWrite(_buffers);
- while(!_buffers.isEmpty())
- {
- QpidByteBuffer buf = _buffers.peek();
- if(buf.hasRemaining())
- {
- break;
- }
- _buffers.poll();
- buf.dispose();
- }
- if (_fullyWritten)
- {
- _usedOutboundMessageSpace.set(0);
- }
- return _fullyWritten;
-
- }
-
- protected int readFromNetwork() throws IOException
- {
- QpidByteBuffer buffer = _delegate.getNetInputBuffer();
-
- int read = buffer.read(_socketChannel);
- if (read == -1)
- {
- _closed.set(true);
- }
-
- _partialRead = read != 0;
-
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Read " + read + " byte(s)");
- }
- return read;
}
@Override
- public boolean isDirectBufferPreferred()
+ public final void flush()
{
- return true;
}
- @Override
- public void send(final QpidByteBuffer msg)
- {
- if (_closed.get())
+ @Override
+ public final void close()
+ {
+ LOGGER.debug("Closing " + getRemoteAddressString());
+ if(setClosed())
{
- LOGGER.warn("Send ignored as the connection is already closed");
+ _protocolEngine.notifyWork();
+ getSelectionTask().wakeup();
}
- else if (msg.remaining() > 0)
- {
- _buffers.add(msg.duplicate());
- }
- msg.position(msg.limit());
}
+
@Override
- public void flush()
- {
- }
-
- public final void pushScheduler(NetworkConnectionScheduler scheduler)
- {
- _schedulerDeque.addFirst(scheduler);
- }
-
- public final NetworkConnectionScheduler popScheduler()
- {
- return _schedulerDeque.removeFirst();
- }
-
- public final NetworkConnectionScheduler getScheduler()
- {
- return _schedulerDeque.peekFirst();
- }
-
- @Override
- public String toString()
- {
- return "[NonBlockingConnection " + _remoteSocketAddress + "]";
- }
-
public void processAmqpData(QpidByteBuffer applicationData)
{
_protocolEngine.received(applicationData);
}
- public void setTransportEncryption(TransportEncryption transportEncryption)
- {
- NonBlockingConnectionDelegate oldDelegate = _delegate;
- switch (transportEncryption)
- {
- case TLS:
- _onTransportEncryptionAction.run();
- _delegate = new NonBlockingConnectionTLSDelegate(this, _port);
- break;
- case NONE:
- _delegate = new NonBlockingConnectionPlainDelegate(this, _port);
- break;
- default:
- throw new IllegalArgumentException("unknown TransportEncryption " + transportEncryption);
- }
- if(oldDelegate != null)
- {
- QpidByteBuffer src = oldDelegate.getNetInputBuffer().duplicate();
- src.flip();
- _delegate.getNetInputBuffer().put(src);
- src.dispose();
- }
- LOGGER.debug("Identified transport encryption as " + transportEncryption);
- }
-
- public boolean setScheduled()
- {
- final boolean scheduled = _scheduled.compareAndSet(false, true);
- if (scheduled)
- {
- _scheduledTime = System.currentTimeMillis();
- }
- return scheduled;
- }
-
- public void clearScheduled()
- {
- _scheduled.set(false);
- _scheduledTime = 0;
- }
@Override
- public long getScheduledTime()
+ public final void reserveOutboundMessageSpace(long size)
{
- return _scheduledTime;
- }
-
- void reportUnexpectedByteBufferSizeUsage()
- {
- if (!_unexpectedByteBufferSizeReported)
+ if (_usedOutboundMessageSpace.addAndGet(size) > getOutboundMessageBufferLimit())
{
- LOGGER.info("At least one frame unexpectedly does not fit into default byte buffer size ({}B) on a connection {}.",
- _port.getNetworkBufferSize(), this.toString());
- _unexpectedByteBufferSizeReported = true;
+ _protocolEngine.setMessageAssignmentSuspended(true, false);
}
}
- public SelectorThread.SelectionTask getSelectionTask()
+
+ @Override
+ public final Ticker getTicker()
{
- return _selectionTask;
+ return _protocolEngine.getAggregateTicker();
}
- public void setSelectionTask(final SelectorThread.SelectionTask selectionTask)
+
+ protected abstract long getOutboundMessageBufferLimit();
+
+
+ public final void reportUnexpectedByteBufferSizeUsage()
{
- _selectionTask = selectionTask;
+ if (_unexpectedByteBufferSizeReported.compareAndSet(false,true))
+ {
+ LOGGER.info("At least one frame unexpectedly does not fit into default byte buffer size ({}B) on a connection {}.",
+ getNetworkBufferSize(), this.toString());
+ }
+ }
+
+ protected NonBlockingConnectionDelegate getDelegate()
+ {
+ return _delegate;
+ }
+
+ protected void setDelegate(NonBlockingConnectionDelegate delegate)
+ {
+ _delegate = delegate;
+ }
+
+ public final ProtocolEngine getProtocolEngine()
+ {
+ return _protocolEngine;
}
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionPlainDelegate.java b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionPlainDelegate.java
index d4b1257..3bfd56e 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionPlainDelegate.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionPlainDelegate.java
@@ -24,7 +24,6 @@
import java.security.cert.Certificate;
import java.util.Collection;
-import org.apache.qpid.server.model.port.AmqpPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -34,14 +33,14 @@
{
private static final Logger LOGGER = LoggerFactory.getLogger(NonBlockingConnectionPlainDelegate.class);
- private final NonBlockingConnection _parent;
+ private final SchedulableConnection _parent;
private final int _networkBufferSize;
private volatile QpidByteBuffer _netInputBuffer;
- public NonBlockingConnectionPlainDelegate(NonBlockingConnection parent, AmqpPort<?> port)
+ public NonBlockingConnectionPlainDelegate(SchedulableConnection parent, int networkBufferSize)
{
_parent = parent;
- _networkBufferSize = port.getNetworkBufferSize();
+ _networkBufferSize = networkBufferSize;
_netInputBuffer = QpidByteBuffer.allocateDirect(_networkBufferSize);
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionTLSDelegate.java b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionTLSDelegate.java
index 564eb64..cda7c04 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionTLSDelegate.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionTLSDelegate.java
@@ -19,19 +19,6 @@
package org.apache.qpid.server.transport;
-import org.apache.qpid.bytebuffer.QpidByteBuffer;
-import org.apache.qpid.server.model.port.AmqpPort;
-import org.apache.qpid.server.util.ServerScopedRuntimeException;
-import org.apache.qpid.transport.network.security.ssl.SSLUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLEngineResult;
-import javax.net.ssl.SSLException;
-import javax.net.ssl.SSLPeerUnverifiedException;
-import javax.net.ssl.SSLSession;
-
import java.io.IOException;
import java.security.Principal;
import java.security.cert.Certificate;
@@ -41,12 +28,24 @@
import java.util.List;
import java.util.ListIterator;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.SSLEngineResult;
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
+
public class NonBlockingConnectionTLSDelegate implements NonBlockingConnectionDelegate
{
private static final Logger LOGGER = LoggerFactory.getLogger(NonBlockingConnectionTLSDelegate.class);
private final SSLEngine _sslEngine;
- private final NonBlockingConnection _parent;
+ private final SchedulableConnection _parent;
private final int _networkBufferSize;
private SSLEngineResult _status;
private final List<QpidByteBuffer> _encryptedOutput = new ArrayList<>();
@@ -58,11 +57,11 @@
private QpidByteBuffer _applicationBuffer;
- public NonBlockingConnectionTLSDelegate(NonBlockingConnection parent, AmqpPort port)
+ public NonBlockingConnectionTLSDelegate(SchedulableConnection parent, int networkBufferSize, SSLEngine sslEngine)
{
_parent = parent;
- _sslEngine = createSSLEngine(port);
- _networkBufferSize = port.getNetworkBufferSize();
+ _sslEngine = sslEngine;
+ _networkBufferSize = networkBufferSize;
final int tlsPacketBufferSize = _sslEngine.getSession().getPacketBufferSize();
if (tlsPacketBufferSize > _networkBufferSize)
@@ -313,28 +312,6 @@
}
}
- private SSLEngine createSSLEngine(AmqpPort<?> port)
- {
- SSLEngine sslEngine = port.getSSLContext().createSSLEngine();
- sslEngine.setUseClientMode(false);
- SSLUtil.updateEnabledTlsProtocols(sslEngine, port.getTlsProtocolWhiteList(), port.getTlsProtocolBlackList());
- SSLUtil.updateEnabledCipherSuites(sslEngine, port.getTlsCipherSuiteWhiteList(), port.getTlsCipherSuiteBlackList());
- if(port.getTlsCipherSuiteWhiteList() != null && !port.getTlsCipherSuiteWhiteList().isEmpty())
- {
- SSLUtil.useCipherOrderIfPossible(sslEngine);
- }
-
- if(port.getNeedClientAuth())
- {
- sslEngine.setNeedClientAuth(true);
- }
- else if(port.getWantClientAuth())
- {
- sslEngine.setWantClientAuth(true);
- }
- return sslEngine;
- }
-
@Override
public QpidByteBuffer getNetInputBuffer()
{
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionUndecidedDelegate.java b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionUndecidedDelegate.java
index f80bd4e..6d7c723 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionUndecidedDelegate.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingConnectionUndecidedDelegate.java
@@ -19,22 +19,22 @@
package org.apache.qpid.server.transport;
-import org.apache.qpid.bytebuffer.QpidByteBuffer;
-import org.apache.qpid.transport.network.TransportEncryption;
-
import java.io.IOException;
import java.security.Principal;
import java.security.cert.Certificate;
import java.util.Collection;
+import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.transport.network.TransportEncryption;
+
public class NonBlockingConnectionUndecidedDelegate implements NonBlockingConnectionDelegate
{
private static final int NUMBER_OF_BYTES_FOR_TLS_CHECK = 6;
- public final NonBlockingConnection _parent;
+ public final NonBlockingInboundConnection _parent;
private QpidByteBuffer _netInputBuffer;
- public NonBlockingConnectionUndecidedDelegate(NonBlockingConnection parent)
+ public NonBlockingConnectionUndecidedDelegate(NonBlockingInboundConnection parent)
{
_parent = parent;
_netInputBuffer = QpidByteBuffer.allocateDirect(NUMBER_OF_BYTES_FOR_TLS_CHECK);
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingInboundConnection.java b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingInboundConnection.java
new file mode 100644
index 0000000..11ca4de
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingInboundConnection.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.transport;
+
+import java.nio.channels.SocketChannel;
+import java.util.Set;
+
+import javax.net.ssl.SSLEngine;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.server.model.port.AmqpPort;
+import org.apache.qpid.transport.network.TransportEncryption;
+import org.apache.qpid.transport.network.security.ssl.SSLUtil;
+
+public class NonBlockingInboundConnection extends NonBlockingConnection
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(NonBlockingInboundConnection.class);
+
+ private final Runnable _onTransportEncryptionAction;
+ private final long _outboundMessageBufferLimit;
+
+
+ private final AmqpPort _port;
+
+ public NonBlockingInboundConnection(SocketChannel socketChannel,
+ ProtocolEngine protocolEngine,
+ final Set<TransportEncryption> encryptionSet,
+ final Runnable onTransportEncryptionAction,
+ final NetworkConnectionScheduler scheduler,
+ final AmqpPort port)
+ {
+ super(socketChannel, protocolEngine, scheduler, socketChannel.socket().getRemoteSocketAddress().toString());
+ _onTransportEncryptionAction = onTransportEncryptionAction;
+
+ _port = port;
+
+ _outboundMessageBufferLimit = (long) _port.getContextValue(Long.class,
+ AmqpPort.PORT_AMQP_OUTBOUND_MESSAGE_BUFFER_SIZE);
+
+
+ if(encryptionSet.size() == 1)
+ {
+ setTransportEncryption(encryptionSet.iterator().next());
+ }
+ else
+ {
+ setDelegate(new NonBlockingConnectionUndecidedDelegate(this));
+ }
+
+ }
+
+ static SSLEngine createSSLEngine(AmqpPort<?> port)
+ {
+ SSLEngine sslEngine = port.getSSLContext().createSSLEngine();
+ sslEngine.setUseClientMode(false);
+ SSLUtil.updateEnabledTlsProtocols(sslEngine, port.getTlsProtocolWhiteList(), port.getTlsProtocolBlackList());
+ SSLUtil.updateEnabledCipherSuites(sslEngine, port.getTlsCipherSuiteWhiteList(), port.getTlsCipherSuiteBlackList());
+ if(port.getTlsCipherSuiteWhiteList() != null && !port.getTlsCipherSuiteWhiteList().isEmpty())
+ {
+ SSLUtil.useCipherOrderIfPossible(sslEngine);
+ }
+
+ if(port.getNeedClientAuth())
+ {
+ sslEngine.setNeedClientAuth(true);
+ }
+ else if(port.getWantClientAuth())
+ {
+ sslEngine.setWantClientAuth(true);
+ }
+ return sslEngine;
+ }
+
+ @Override
+ protected long getOutboundMessageBufferLimit()
+ {
+ return _outboundMessageBufferLimit;
+ }
+
+ @Override
+ protected int getNetworkBufferSize()
+ {
+ return _port.getNetworkBufferSize();
+ }
+
+ @Override
+ public boolean wantsConnect()
+ {
+ return false;
+ }
+
+
+ @Override
+ public String toString()
+ {
+ return "[InboundConnection " + getRemoteAddressString() + "]";
+ }
+
+ public void setTransportEncryption(TransportEncryption transportEncryption)
+ {
+ NonBlockingConnectionDelegate oldDelegate = getDelegate();
+ switch (transportEncryption)
+ {
+ case TLS:
+ _onTransportEncryptionAction.run();
+ setDelegate(new NonBlockingConnectionTLSDelegate(this,
+ _port.getNetworkBufferSize(),
+ createSSLEngine(_port)));
+ break;
+ case NONE:
+ setDelegate(new NonBlockingConnectionPlainDelegate(this, _port.getNetworkBufferSize()));
+ break;
+ default:
+ throw new IllegalArgumentException("unknown TransportEncryption " + transportEncryption);
+ }
+ if(oldDelegate != null)
+ {
+ QpidByteBuffer src = oldDelegate.getNetInputBuffer().duplicate();
+ src.flip();
+ getDelegate().getNetInputBuffer().put(src);
+ src.dispose();
+ }
+ LOGGER.debug("Identified transport encryption as " + transportEncryption);
+ }
+
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingNetworkTransport.java b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingNetworkTransport.java
index ad1435b..77ed00f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingNetworkTransport.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingNetworkTransport.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.transport;
+import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
+
import java.io.IOException;
import java.net.BindException;
import java.net.InetSocketAddress;
@@ -30,16 +32,14 @@
import java.util.EnumSet;
import java.util.Set;
-import org.apache.qpid.server.model.port.AmqpPort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.qpid.configuration.CommonProperties;
+import org.apache.qpid.server.model.port.AmqpPort;
import org.apache.qpid.transport.TransportException;
import org.apache.qpid.transport.network.TransportEncryption;
-import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
-
public class NonBlockingNetworkTransport
{
@@ -156,10 +156,10 @@
NonBlockingConnection connection =
- new NonBlockingConnection(socketChannel,
- engine,
- _encryptionSet,
- new Runnable()
+ new NonBlockingInboundConnection(socketChannel,
+ engine,
+ _encryptionSet,
+ new Runnable()
{
@Override
@@ -168,8 +168,8 @@
engine.encryptedTransport();
}
},
- _scheduler,
- _port);
+ _scheduler,
+ _port);
engine.setNetworkConnection(connection);
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingOutboundConnection.java b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingOutboundConnection.java
new file mode 100644
index 0000000..117a01b
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/NonBlockingOutboundConnection.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.transport;
+
+import java.nio.channels.SocketChannel;
+import java.security.GeneralSecurityException;
+import java.util.ArrayList;
+import java.util.Collection;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.federation.OutboundProtocolEngine;
+import org.apache.qpid.server.model.Container;
+import org.apache.qpid.server.model.KeyStore;
+import org.apache.qpid.server.model.RemoteHostAddress;
+import org.apache.qpid.server.model.TrustStore;
+import org.apache.qpid.server.model.port.AmqpPort;
+import org.apache.qpid.server.plugin.OutboundProtocolEngineCreator;
+import org.apache.qpid.server.plugin.QpidServiceLoader;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.virtualhost.AbstractVirtualHost;
+import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager;
+import org.apache.qpid.transport.network.security.ssl.SSLUtil;
+
+public class NonBlockingOutboundConnection extends NonBlockingConnection
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(NonBlockingOutboundConnection.class);
+
+ private final AbstractVirtualHost<?> _virtualHost;
+ private final RemoteHostAddress<?> _address;
+ private final int _networkBufferSize;
+ private final long _outboundMessageBufferLimit;
+ private volatile boolean _connected;
+
+ public NonBlockingOutboundConnection(SocketChannel socketChannel,
+ final RemoteHostAddress<?> address,
+ final NetworkConnectionScheduler networkConnectionScheduler,
+ final AbstractVirtualHost<?> virtualHost,
+ final Action<Boolean> onConnectionLoss)
+ {
+ super(socketChannel, createProtocolEngine(address, virtualHost), networkConnectionScheduler, address.getAddress()+":"+address.getPort());
+ OutboundProtocolEngine protocolEngine = (OutboundProtocolEngine) getProtocolEngine();
+ protocolEngine.setConnection(this);
+ protocolEngine.setOnClosedTask(onConnectionLoss);
+ _virtualHost = virtualHost;
+ _address = address;
+ _networkBufferSize = virtualHost.getAncestor(Container.class).getNetworkBufferSize();
+ _outboundMessageBufferLimit = (long) virtualHost.getContextValue(Long.class,
+ AmqpPort.PORT_AMQP_OUTBOUND_MESSAGE_BUFFER_SIZE);
+
+ final NonBlockingConnectionDelegate delegate;
+ switch(address.getTransport())
+ {
+ case TCP:
+ delegate = new NonBlockingConnectionPlainDelegate(this, getNetworkBufferSize());
+ break;
+ case SSL:
+ delegate = new NonBlockingConnectionTLSDelegate(this, getNetworkBufferSize(), createSSLEngine(address));
+ break;
+ default:
+ throw new IllegalArgumentException("Transport '"+address.getTransport()+"' is not supported");
+ }
+ setDelegate(delegate);
+ }
+
+ private static ProtocolEngine createProtocolEngine(final RemoteHostAddress<?> address, final AbstractVirtualHost<?> virtualHost)
+ {
+ for(OutboundProtocolEngineCreator engineCreator : (new QpidServiceLoader()).instancesOf(OutboundProtocolEngineCreator.class))
+ {
+ if(engineCreator.getVersion().equals(address.getProtocol()))
+ {
+ return engineCreator.newProtocolEngine(address, virtualHost);
+ }
+ }
+
+ return null;
+ }
+
+
+ @Override
+ protected long getOutboundMessageBufferLimit()
+ {
+ return _outboundMessageBufferLimit;
+ }
+
+ @Override
+ protected int getNetworkBufferSize()
+ {
+ return _networkBufferSize;
+ }
+
+
+ @Override
+ public boolean wantsConnect()
+ {
+ return !_connected && !(_connected = getSocketChannel().isConnected());
+ }
+
+ static SSLEngine createSSLEngine(RemoteHostAddress<?> address)
+ {
+ SSLEngine sslEngine = createSslContext(address).createSSLEngine();
+ sslEngine.setUseClientMode(true);
+ SSLUtil.updateEnabledTlsProtocols(sslEngine, address.getTlsProtocolWhiteList(), address.getTlsProtocolBlackList());
+ SSLUtil.updateEnabledCipherSuites(sslEngine, address.getTlsCipherSuiteWhiteList(), address.getTlsCipherSuiteBlackList());
+ if(address.getTlsCipherSuiteWhiteList() != null && !address.getTlsCipherSuiteWhiteList().isEmpty())
+ {
+ SSLUtil.useCipherOrderIfPossible(sslEngine);
+ }
+
+ return sslEngine;
+ }
+
+ private static SSLContext createSslContext(RemoteHostAddress<?> address)
+ {
+ KeyStore keyStore = address.getKeyStore();
+ Collection<TrustStore> trustStores = address.getTrustStores();
+
+ try
+ {
+ SSLContext sslContext = SSLUtil.tryGetSSLContext();
+
+ KeyManager[] keyManagers = keyStore.getKeyManagers();
+
+ TrustManager[] trustManagers;
+ if(trustStores == null || trustStores.isEmpty())
+ {
+ trustManagers = null;
+ }
+ else if(trustStores.size() == 1)
+ {
+ trustManagers = trustStores.iterator().next().getTrustManagers();
+ }
+ else
+ {
+ Collection<TrustManager> trustManagerList = new ArrayList<>();
+ final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager();
+
+ for(TrustStore ts : trustStores)
+ {
+ TrustManager[] managers = ts.getTrustManagers();
+ if(managers != null)
+ {
+ for(TrustManager manager : managers)
+ {
+ if(manager instanceof X509TrustManager)
+ {
+ mulTrustManager.addTrustManager((X509TrustManager)manager);
+ }
+ else
+ {
+ trustManagerList.add(manager);
+ }
+ }
+ }
+ }
+ if(!mulTrustManager.isEmpty())
+ {
+ trustManagerList.add(mulTrustManager);
+ }
+ trustManagers = trustManagerList.toArray(new TrustManager[trustManagerList.size()]);
+ }
+ sslContext.init(keyManagers, trustManagers, null);
+
+ return sslContext;
+
+ }
+ catch (GeneralSecurityException e)
+ {
+ throw new IllegalArgumentException("Unable to create SSLContext for key or trust store", e);
+ }
+ }
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/SchedulableConnection.java b/broker-core/src/main/java/org/apache/qpid/server/transport/SchedulableConnection.java
new file mode 100644
index 0000000..d95bb56
--- /dev/null
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/SchedulableConnection.java
@@ -0,0 +1,68 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.transport;
+
+import java.io.IOException;
+import java.nio.channels.SocketChannel;
+import java.util.Collection;
+
+import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.transport.ByteBufferSender;
+import org.apache.qpid.transport.network.Ticker;
+
+public interface SchedulableConnection extends ServerNetworkConnection, ByteBufferSender
+{
+ String getThreadName();
+
+ boolean isPartialRead();
+
+ Ticker getTicker();
+
+ SocketChannel getSocketChannel();
+
+ boolean wantsRead();
+
+ boolean wantsWrite();
+
+ boolean wantsConnect();
+
+ boolean isStateChanged();
+
+ void doPreWork();
+
+ boolean doWork();
+
+ NetworkConnectionScheduler getScheduler();
+
+ boolean setScheduled();
+
+ void clearScheduled();
+
+ SelectorThread.SelectionTask getSelectionTask();
+
+ void setSelectionTask(SelectorThread.SelectionTask selectionTask);
+
+ void processAmqpData(QpidByteBuffer applicationData);
+
+ long writeToTransport(Collection<QpidByteBuffer> bufferArray) throws IOException;
+
+ void reportUnexpectedByteBufferSizeUsage();
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java b/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java
index 04ee506..157e15b 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/transport/SelectorThread.java
@@ -71,10 +71,10 @@
* Queue of connections that are not currently scheduled and not registered with the selector.
* These need to go back into the Selector.
*/
- private final Queue<NonBlockingConnection> _unregisteredConnections = new ConcurrentLinkedQueue<>();
+ private final Queue<SchedulableConnection> _unregisteredConnections = new ConcurrentLinkedQueue<>();
/** Set of connections that are currently being selected upon */
- private final Set<NonBlockingConnection> _unscheduledConnections = new HashSet<>();
+ private final Set<SchedulableConnection> _unscheduledConnections = new HashSet<>();
@@ -104,17 +104,17 @@
return _selector;
}
- public Queue<NonBlockingConnection> getUnregisteredConnections()
+ public Queue<SchedulableConnection> getUnregisteredConnections()
{
return _unregisteredConnections;
}
- public Set<NonBlockingConnection> getUnscheduledConnections()
+ public Set<SchedulableConnection> getUnscheduledConnections()
{
return _unscheduledConnections;
}
- private List<NonBlockingConnection> processUnscheduledConnections()
+ private List<SchedulableConnection> processUnscheduledConnections()
{
_nextTimeout = Integer.MAX_VALUE;
if (getUnscheduledConnections().isEmpty())
@@ -122,13 +122,13 @@
return Collections.emptyList();
}
- List<NonBlockingConnection> toBeScheduled = new ArrayList<>();
+ List<SchedulableConnection> toBeScheduled = new ArrayList<>();
long currentTime = System.currentTimeMillis();
- Iterator<NonBlockingConnection> iterator = getUnscheduledConnections().iterator();
+ Iterator<SchedulableConnection> iterator = getUnscheduledConnections().iterator();
while (iterator.hasNext())
{
- NonBlockingConnection connection = iterator.next();
+ SchedulableConnection connection = iterator.next();
int period = connection.getTicker().getTimeToNextTick(currentTime);
@@ -153,10 +153,10 @@
}
// QPID-7447: prevent unnecessary allocation of empty iterator
- return toBeScheduled.isEmpty() ? Collections.<NonBlockingConnection>emptyList() : toBeScheduled;
+ return toBeScheduled.isEmpty() ? Collections.<SchedulableConnection>emptyList() : toBeScheduled;
}
- private List<NonBlockingConnection> processSelectionKeys()
+ private List<SchedulableConnection> processSelectionKeys()
{
Set<SelectionKey> selectionKeys = _selector.selectedKeys();
if (selectionKeys.isEmpty())
@@ -164,7 +164,7 @@
return Collections.emptyList();
}
- List<NonBlockingConnection> toBeScheduled = new ArrayList<>();
+ List<SchedulableConnection> toBeScheduled = new ArrayList<>();
for (SelectionKey key : selectionKeys)
{
if(key.isAcceptable())
@@ -215,7 +215,7 @@
}
else
{
- NonBlockingConnection connection = (NonBlockingConnection) key.attachment();
+ SchedulableConnection connection = (SchedulableConnection) key.attachment();
if(connection != null)
{
try
@@ -238,15 +238,15 @@
return toBeScheduled;
}
- private List<NonBlockingConnection> reregisterUnregisteredConnections()
+ private List<SchedulableConnection> reregisterUnregisteredConnections()
{
if (getUnregisteredConnections().isEmpty())
{
return Collections.emptyList();
}
- List<NonBlockingConnection> unregisterableConnections = new ArrayList<>();
+ List<SchedulableConnection> unregisterableConnections = new ArrayList<>();
- NonBlockingConnection unregisteredConnection;
+ SchedulableConnection unregisteredConnection;
while ((unregisteredConnection = getUnregisteredConnections().poll()) != null)
{
getUnscheduledConnections().add(unregisteredConnection);
@@ -265,7 +265,7 @@
}
// QPID-7447: prevent unnecessary allocation of empty iterator
- return unregisterableConnections.isEmpty() ? Collections.<NonBlockingConnection>emptyList() : unregisterableConnections;
+ return unregisterableConnections.isEmpty() ? Collections.<SchedulableConnection>emptyList() : unregisterableConnections;
}
private void performSelect()
@@ -306,21 +306,21 @@
{
_inSelect.set(false);
}
- for (NonBlockingConnection connection : processSelectionKeys())
+ for (SchedulableConnection connection : processSelectionKeys())
{
if (connection.setScheduled())
{
connections.add(new ConnectionProcessor(_scheduler, connection));
}
}
- for (NonBlockingConnection connection : reregisterUnregisteredConnections())
+ for (SchedulableConnection connection : reregisterUnregisteredConnections())
{
if (connection.setScheduled())
{
connections.add(new ConnectionProcessor(_scheduler, connection));
}
}
- for (NonBlockingConnection connection : processUnscheduledConnections())
+ for (SchedulableConnection connection : processUnscheduledConnections())
{
if (connection.setScheduled())
{
@@ -501,10 +501,10 @@
{
private final NetworkConnectionScheduler _scheduler;
- private final NonBlockingConnection _connection;
+ private final SchedulableConnection _connection;
private AtomicBoolean _running = new AtomicBoolean();
- public ConnectionProcessor(final NetworkConnectionScheduler scheduler, final NonBlockingConnection connection)
+ public ConnectionProcessor(final NetworkConnectionScheduler scheduler, final SchedulableConnection connection)
{
_scheduler = scheduler;
_connection = connection;
@@ -533,7 +533,7 @@
}
}
- private void unregisterConnection(final NonBlockingConnection connection) throws ClosedChannelException
+ private void unregisterConnection(final SchedulableConnection connection) throws ClosedChannelException
{
SelectionKey register = connection.getSocketChannel().register(connection.getSelectionTask().getSelector(), 0);
register.cancel();
@@ -548,14 +548,15 @@
}
}
- private boolean selectionInterestRequiresUpdate(NonBlockingConnection connection)
+ private boolean selectionInterestRequiresUpdate(SchedulableConnection connection)
{
SelectionTask selectionTask = connection.getSelectionTask();
if(selectionTask != null)
{
final SelectionKey selectionKey = connection.getSocketChannel().keyFor(selectionTask.getSelector());
int expectedOps = (connection.wantsRead() ? SelectionKey.OP_READ : 0)
- | (connection.wantsWrite() ? SelectionKey.OP_WRITE : 0);
+ | (connection.wantsWrite() ? SelectionKey.OP_WRITE : 0)
+ | (connection.wantsConnect() ? SelectionKey.OP_CONNECT : 0);
try
{
@@ -572,7 +573,7 @@
}
}
- public void addConnection(final NonBlockingConnection connection)
+ public void addConnection(final SchedulableConnection connection)
{
if(selectionInterestRequiresUpdate(connection))
{
@@ -584,7 +585,7 @@
}
- public void returnConnectionToSelector(final NonBlockingConnection connection)
+ public void returnConnectionToSelector(final SchedulableConnection connection)
{
if(selectionInterestRequiresUpdate(connection))
{
@@ -610,7 +611,7 @@
return _selectionTasks[index];
}
- void removeConnection(NonBlockingConnection connection)
+ void removeConnection(SchedulableConnection connection)
{
try
{
@@ -658,7 +659,7 @@
}
- public void addToWork(final NonBlockingConnection connection)
+ public void addToWork(final SchedulableConnection connection)
{
if (_closed.get())
{
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractSystemMessageSource.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractSystemMessageSource.java
index 4a69f00..935ab60 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractSystemMessageSource.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractSystemMessageSource.java
@@ -29,12 +29,14 @@
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;
-import org.apache.qpid.server.consumer.ConsumerImpl;
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.BaseMessageInstance;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.message.internal.InternalMessage;
@@ -48,12 +50,12 @@
import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.util.StateChangeListener;
-public abstract class AbstractSystemMessageSource implements MessageSource
+public abstract class AbstractSystemMessageSource implements MessageSource<AbstractSystemMessageSource.SystemMessageSourceConsumer>
{
- protected final UUID _id;
- protected final String _name;
- protected final NamedAddressSpace _addressSpace;
- private List<Consumer> _consumers = new CopyOnWriteArrayList<>();
+ private final UUID _id;
+ private final String _name;
+ private final NamedAddressSpace _addressSpace;
+ private List<SystemMessageSourceConsumer> _consumers = new CopyOnWriteArrayList<>();
public AbstractSystemMessageSource(String name, final NamedAddressSpace addressSpace)
{
@@ -82,22 +84,22 @@
}
@Override
- public Consumer addConsumer(final ConsumerTarget target,
- final FilterManager filters,
- final Class<? extends ServerMessage> messageClass,
- final String consumerName,
- final EnumSet<ConsumerImpl.Option> options, final Integer priority)
+ public SystemMessageSourceConsumer addConsumer(final ConsumerTarget target,
+ final FilterManager filters,
+ final Class<? extends ServerMessage> messageClass,
+ final String consumerName,
+ final EnumSet<ConsumerOption> options, final Integer priority)
throws ExistingExclusiveConsumer, ExistingConsumerPreventsExclusive,
ConsumerAccessRefused
{
- final Consumer consumer = new Consumer(consumerName, target);
+ final SystemMessageSourceConsumer consumer = new SystemMessageSourceConsumer(consumerName, target);
target.consumerAdded(consumer);
_consumers.add(consumer);
return consumer;
}
@Override
- public Collection<Consumer> getConsumers()
+ public Collection<SystemMessageSourceConsumer> getConsumers()
{
return new ArrayList<>(_consumers);
}
@@ -108,19 +110,23 @@
return true;
}
- protected class Consumer implements ConsumerImpl
+ public NamedAddressSpace getAddressSpace()
+ {
+ return _addressSpace;
+ }
+
+ protected class SystemMessageSourceConsumer implements MessageInstanceConsumer
{
- private final long _id = ConsumerImpl.CONSUMER_NUMBER_GENERATOR.getAndIncrement();
private final List<PropertiesMessageInstance> _queue =
Collections.synchronizedList(new ArrayList<PropertiesMessageInstance>());
private final ConsumerTarget _target;
private final String _name;
private final StateChangeListener<ConsumerTarget, ConsumerTarget.State> _targetChangeListener =
- new Consumer.TargetChangeListener();
+ new SystemMessageSourceConsumer.TargetChangeListener();
+ private final Object _identifier = new Object();
-
- public Consumer(final String consumerName, ConsumerTarget target)
+ SystemMessageSourceConsumer(final String consumerName, ConsumerTarget target)
{
_name = consumerName;
_target = target;
@@ -133,13 +139,16 @@
}
- @Override
+ public Object getIdentifier()
+ {
+ return _identifier;
+ }
+
public ConsumerTarget getTarget()
{
return _target;
}
- @Override
public boolean hasAvailableMessages()
{
return !_queue.isEmpty();
@@ -151,55 +160,12 @@
}
- @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 MessageSource getMessageSource()
- {
- return AbstractSystemMessageSource.this;
- }
-
- @Override
- public long getConsumerNumber()
- {
- return _id;
- }
-
- @Override
- public boolean isSuspended()
- {
- return false;
- }
-
- @Override
public boolean isClosed()
{
return false;
@@ -212,42 +178,12 @@
}
@Override
- public boolean seesRequeues()
- {
- return false;
- }
-
- @Override
public void close()
{
_consumers.remove(this);
}
@Override
- public boolean trySendLock()
- {
- return _target.trySendLock();
- }
-
- @Override
- public void getSendLock()
- {
- _target.getSendLock();
- }
-
- @Override
- public void releaseSendLock()
- {
- _target.releaseSendLock();
- }
-
- @Override
- public boolean isActive()
- {
- return false;
- }
-
- @Override
public String getName()
{
return _name;
@@ -334,16 +270,15 @@
}
- class PropertiesMessageInstance implements MessageInstance
+ private class PropertiesMessageInstance implements MessageInstance
{
- private final Consumer _consumer;
+ private final SystemMessageSourceConsumer _consumer;
private int _deliveryCount;
private boolean _isRedelivered;
- private boolean _isDelivered;
private boolean _isDeleted;
private InternalMessage _message;
- PropertiesMessageInstance(final Consumer consumer, final InternalMessage message)
+ PropertiesMessageInstance(final SystemMessageSourceConsumer consumer, final InternalMessage message)
{
_consumer = consumer;
_message = message;
@@ -352,7 +287,7 @@
@Override
public int getDeliveryCount()
{
- return 0;
+ return _deliveryCount;
}
@Override
@@ -387,7 +322,7 @@
}
@Override
- public ConsumerImpl getAcquiringConsumer()
+ public MessageInstanceConsumer getAcquiringConsumer()
{
return _consumer;
}
@@ -399,13 +334,13 @@
}
@Override
- public boolean isAcquiredBy(final ConsumerImpl consumer)
+ public boolean isAcquiredBy(final MessageInstanceConsumer consumer)
{
return consumer == _consumer && !isDeleted();
}
@Override
- public boolean removeAcquisitionFromConsumer(final ConsumerImpl consumer)
+ public boolean removeAcquisitionFromConsumer(final MessageInstanceConsumer consumer)
{
return consumer == _consumer;
}
@@ -423,7 +358,7 @@
}
@Override
- public Consumer getDeliveredConsumer()
+ public SystemMessageSourceConsumer getDeliveredConsumer()
{
return isDeleted() ? null : _consumer;
}
@@ -435,7 +370,7 @@
}
@Override
- public boolean isRejectedBy(final ConsumerImpl consumer)
+ public boolean isRejectedBy(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -443,7 +378,7 @@
@Override
public boolean getDeliveredToConsumer()
{
- return _isDelivered;
+ return _deliveryCount > 0;
}
@Override
@@ -453,13 +388,13 @@
}
@Override
- public boolean acquire(final ConsumerImpl sub)
+ public boolean acquire(final MessageInstanceConsumer sub)
{
return false;
}
@Override
- public boolean makeAcquisitionUnstealable(final ConsumerImpl consumer)
+ public boolean makeAcquisitionUnstealable(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -477,7 +412,7 @@
}
@Override
- public int routeToAlternate(final Action<? super MessageInstance> action,
+ public int routeToAlternate(final Action<? super BaseMessageInstance> action,
final ServerTransaction txn)
{
return 0;
@@ -515,7 +450,7 @@
}
@Override
- public void release(ConsumerImpl consumer)
+ public void release(MessageInstanceConsumer consumer)
{
release();
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index bc072f2..5b9c3ac 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -30,9 +30,11 @@
import java.io.OutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
+import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
+import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.security.AccessControlContext;
import java.security.Principal;
@@ -132,8 +134,11 @@
import org.apache.qpid.server.store.preferences.PreferencesRecoverer;
import org.apache.qpid.server.store.preferences.PreferencesRoot;
import org.apache.qpid.server.store.serializer.MessageStoreSerializer;
+import org.apache.qpid.server.transfer.TransferQueue;
+import org.apache.qpid.server.transfer.TransferQueueImpl;
import org.apache.qpid.server.transport.AMQPConnection;
import org.apache.qpid.server.transport.NetworkConnectionScheduler;
+import org.apache.qpid.server.transport.NonBlockingOutboundConnection;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.DtxRegistry;
import org.apache.qpid.server.txn.LocalTransaction;
@@ -155,6 +160,9 @@
private final AtomicBoolean _acceptsConnections = new AtomicBoolean(false);
private TaskExecutor _preferenceTaskExecutor;
+ private Map<String,MessageDestination> _availableRoutes = new HashMap<>();
+ private TransferQueue _transferQueue;
+
private static enum BlockingType { STORE, FILESYSTEM };
private static final String USE_ASYNC_RECOVERY = "use_async_message_store_recovery";
@@ -216,7 +224,6 @@
}
}, Result.DEFER);
-
@ManagedAttributeField
private boolean _queue_deadLetterQueueEnabled;
@@ -304,6 +311,7 @@
_fileSystemSpaceCheckerJobContext = getSystemTaskControllerContext("FileSystemSpaceChecker["+getName()+"]", _principal);
_fileSystemSpaceChecker = new FileSystemSpaceChecker();
+ _transferQueue = new TransferQueueImpl(this);
addChangeListener(new TargetSizeAssigningListener());
}
@@ -438,6 +446,13 @@
{
super.postResolveChildren();
addChangeListener(_accessControlProviderListener);
+ for(RemoteHost<?> remoteHost : getChildren(RemoteHost.class))
+ {
+ for(String address : remoteHost.getRoutableAddresses())
+ {
+ _availableRoutes.put(address, _transferQueue);
+ }
+ }
}
private void validateNodeAutoCreationPolicy(final NodeAutoCreationPolicy policy)
@@ -793,7 +808,9 @@
{
throw new UnsupportedOperationException();
}
- else if(childClass == VirtualHostLogger.class || childClass == VirtualHostAccessControlProvider.class)
+ else if(childClass == VirtualHostLogger.class
+ || childClass == VirtualHostAccessControlProvider.class
+ || childClass == RemoteHost.class)
{
return getObjectFactory().createAsync(childClass, attributes, this);
}
@@ -1333,12 +1350,60 @@
}
if(destination == null)
{
-
destination = autoCreateNode(name, MessageDestination.class, true);
}
+ if(destination == null)
+ {
+ destination = getTransferAgent( name );
+ }
return destination;
}
+ private MessageDestination getTransferAgent(final String address)
+ {
+ if(address.contains("/") && getGlobalAddressDomains() != null)
+ {
+ for(String domain : getGlobalAddressDomains())
+ {
+ if(address.startsWith(domain + "/"))
+ {
+ return null;
+ }
+ }
+ }
+ for(Map.Entry<String, MessageDestination> route : _availableRoutes.entrySet())
+ {
+ if(address.equals(route.getKey()) || address.startsWith(route.getKey() + "/"))
+ {
+ return route.getValue();
+ }
+ }
+ return null;
+ }
+
+ private boolean isGlobalAddress(final String address)
+ {
+ if(address.contains("/") && getGlobalAddressDomains() != null)
+ {
+ for(String domain : getGlobalAddressDomains())
+ {
+ if(address.startsWith(domain + "/"))
+ {
+ return false;
+ }
+ }
+ }
+ Set<String> routes = _availableRoutes.keySet();
+ for(String route : routes)
+ {
+ if(address.equals(route) || address.startsWith(address + "/"))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
@Override
public <T extends ConfiguredObject<?>> T getAttainedChildFromAddress(final Class<T> childClass,
final String address)
@@ -1410,7 +1475,7 @@
{
if(localAddress.length() > routingAddress.length() - domain.length() && routingAddress.startsWith(domain + "/"))
{
- localAddress = routingAddress.substring(domain.length());
+ localAddress = routingAddress.substring(domain.length()+1);
}
}
}
@@ -1752,7 +1817,7 @@
}
}
- private class TargetSizeAssigningListener implements ConfigurationChangeListener
+ private class TargetSizeAssigningListener extends AbstractConfigurationChangeListener
{
@Override
public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
@@ -1780,23 +1845,6 @@
{
}
- @Override
- public void attributeSet(final ConfiguredObject<?> object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
- }
}
private class VirtualHostHouseKeepingTask extends HouseKeepingTask
@@ -2559,6 +2607,29 @@
}
}
+ public boolean makeConnection(final RemoteHostAddress<?> address, final Action<Boolean> onConnectionLoss)
+ {
+ try
+ {
+
+ _logger.info("Attempting to connect to {}", address);
+ SocketChannel socketChannel = SocketChannel.open();
+ socketChannel.configureBlocking(false);
+ socketChannel.connect(new InetSocketAddress(address.getAddress(), address.getPort()));
+ NonBlockingOutboundConnection connection = new NonBlockingOutboundConnection(socketChannel,
+ address,
+ _networkConnectionScheduler,
+ this, onConnectionLoss);
+ _networkConnectionScheduler.addConnection(connection);
+ return true;
+ }
+ catch (IOException e)
+ {
+ _logger.debug("Failed to make connection to {}", address, e);
+ return false;
+ }
+ }
+
protected void startFileSystemSpaceChecking()
{
File storeLocationAsFile = _messageStore.getStoreLocationAsFile();
@@ -2702,6 +2773,12 @@
}
@Override
+ public TransferQueue getTransferQueue()
+ {
+ return _transferQueue;
+ }
+
+ @Override
public <T extends MessageDestination> T createMessageDestination(final Class<T> clazz,
final Map<String, Object> attributes)
{
@@ -2725,17 +2802,11 @@
return !(_systemNodeSources.isEmpty() && getChildren(Queue.class).isEmpty());
}
- private final class AccessControlProviderListener implements ConfigurationChangeListener
+ private final class AccessControlProviderListener extends AbstractConfigurationChangeListener
{
private final Set<ConfiguredObject<?>> _bulkChanges = new HashSet<>();
@Override
- public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
- {
-
- }
-
- @Override
public void childAdded(final ConfiguredObject<?> object, final ConfiguredObject<?> child)
{
if(object.getCategoryClass() == VirtualHost.class && child.getCategoryClass() == VirtualHostAccessControlProvider.class)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AsynchronousMessageStoreRecoverer.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AsynchronousMessageStoreRecoverer.java
index b1617b2..84b8774 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AsynchronousMessageStoreRecoverer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AsynchronousMessageStoreRecoverer.java
@@ -48,6 +48,7 @@
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.plugin.MessageMetaDataType;
import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.RecoverableBaseQueue;
import org.apache.qpid.server.store.MessageEnqueueRecord;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StorableMessageMetaData;
@@ -127,6 +128,9 @@
ListenableFuture<Void> result = _queueRecoveryExecutor.submit(new QueueRecoveringTask(queue), null);
queueRecoveryFutures.add(result);
}
+ ListenableFuture<Void> result = _queueRecoveryExecutor.submit(new QueueRecoveringTask(_virtualHost.getTransferQueue()), null);
+ queueRecoveryFutures.add(result);
+
ListenableFuture<List<Void>> combinedFuture = Futures.allAsList(queueRecoveryFutures);
return Futures.transform(combinedFuture, new Function<List<?>, Void>()
{
@@ -163,7 +167,7 @@
return _recoveringQueues.contains(queue);
}
- private void recoverQueue(Queue<?> queue)
+ private void recoverQueue(RecoverableBaseQueue queue)
{
MessageInstanceVisitor handler = new MessageInstanceVisitor(queue);
_storeReader.visitMessageInstances(queue, handler);
@@ -434,9 +438,9 @@
private class QueueRecoveringTask implements Runnable
{
- private final Queue<?> _queue;
+ private final RecoverableBaseQueue _queue;
- public QueueRecoveringTask(final Queue<?> queue)
+ public QueueRecoveringTask(final RecoverableBaseQueue queue)
{
_queue = queue;
}
@@ -461,10 +465,10 @@
private class MessageInstanceVisitor implements MessageInstanceHandler
{
- private final Queue<?> _queue;
+ private final RecoverableBaseQueue _queue;
long _recoveredCount;
- private MessageInstanceVisitor(Queue<?> queue)
+ private MessageInstanceVisitor(RecoverableBaseQueue queue)
{
_queue = queue;
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/SynchronousMessageStoreRecoverer.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/SynchronousMessageStoreRecoverer.java
index f67935d..6f3c94a 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/SynchronousMessageStoreRecoverer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/SynchronousMessageStoreRecoverer.java
@@ -40,6 +40,7 @@
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.plugin.MessageMetaDataType;
import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.queue.RecoverableBaseQueue;
import org.apache.qpid.server.store.MessageEnqueueRecord;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StorableMessageMetaData;
@@ -49,6 +50,7 @@
import org.apache.qpid.server.store.handler.DistributedTransactionHandler;
import org.apache.qpid.server.store.handler.MessageHandler;
import org.apache.qpid.server.store.handler.MessageInstanceHandler;
+import org.apache.qpid.server.transfer.TransferQueue;
import org.apache.qpid.server.txn.DtxBranch;
import org.apache.qpid.server.txn.DtxRegistry;
import org.apache.qpid.server.txn.ServerTransaction;
@@ -85,7 +87,11 @@
{
eventLogger.message(logSubject, TransactionLogMessages.RECOVERED(entry.getValue(), entry.getKey()));
eventLogger.message(logSubject, TransactionLogMessages.RECOVERY_COMPLETE(entry.getKey(), true));
- virtualHost.getAttainedChildFromAddress(Queue.class, entry.getKey()).completeRecovery();
+ Queue queue = virtualHost.getAttainedChildFromAddress(Queue.class, entry.getKey());
+ if(queue != null)
+ {
+ queue.completeRecovery();
+ }
}
for(Queue<?> q : virtualHost.getChildren(Queue.class))
@@ -95,6 +101,8 @@
q.completeRecovery();
}
}
+ TransferQueue q = virtualHost.getTransferQueue();
+ q.completeRecovery();
storeReader.visitDistributedTransactions(new DistributedTransactionVisitor(virtualHost, store, eventLogger,
logSubject, recoveredMessages, unusedMessages));
@@ -179,7 +187,11 @@
{
final UUID queueId = record.getQueueId();
long messageId = record.getMessageNumber();
- Queue<?> queue = _virtualHost.getAttainedQueue(queueId);
+ RecoverableBaseQueue queue = _virtualHost.getAttainedQueue(queueId);
+ if(queue == null && _virtualHost.getTransferQueue().getId().equals(queueId))
+ {
+ queue = _virtualHost.getTransferQueue();
+ }
if(queue != null)
{
String queueName = queue.getName();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostPropertiesNode.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostPropertiesNode.java
index 8392ce4..81b8232 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostPropertiesNode.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostPropertiesNode.java
@@ -26,9 +26,9 @@
import java.util.Map;
import java.util.UUID;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.message.internal.InternalMessage;
import org.apache.qpid.server.message.internal.InternalMessageHeader;
@@ -47,15 +47,16 @@
}
@Override
- public Consumer addConsumer(final ConsumerTarget target,
- final FilterManager filters,
- final Class<? extends ServerMessage> messageClass,
- final String consumerName,
- final EnumSet<ConsumerImpl.Option> options, final Integer priority)
+ public SystemMessageSourceConsumer addConsumer(final ConsumerTarget target,
+ final FilterManager filters,
+ final Class<? extends ServerMessage> messageClass,
+ final String consumerName,
+ final EnumSet<ConsumerOption> options, final Integer priority)
throws ExistingExclusiveConsumer, ExistingConsumerPreventsExclusive,
ConsumerAccessRefused
{
- final Consumer consumer = super.addConsumer(target, filters, messageClass, consumerName, options, priority);
+ final SystemMessageSourceConsumer
+ consumer = super.addConsumer(target, filters, messageClass, consumerName, options, priority);
consumer.send(createMessage());
target.queueEmpty();
return consumer;
@@ -66,7 +67,7 @@
Map<String, Object> headers = new HashMap<>();
- final List<String> globalAddresseDomains = _addressSpace.getGlobalAddressDomains();
+ final List<String> globalAddresseDomains = getAddressSpace().getGlobalAddressDomains();
if (globalAddresseDomains != null && !globalAddresseDomains.isEmpty())
{
String primaryDomain = globalAddresseDomains.get(0);
@@ -80,13 +81,13 @@
headers.put("virtualHost.temporaryQueuePrefix", primaryDomain);
}
}
-
+ headers.put("virtualhost.globalDomains", globalAddresseDomains);
InternalMessageHeader header = new InternalMessageHeader(headers,
null, 0l, null, null, UUID.randomUUID().toString(),
null, null, (byte) 4, System.currentTimeMillis(),
0L, null, null);
final InternalMessage message =
- InternalMessage.createBytesMessage(_addressSpace.getMessageStore(), header, new byte[0]);
+ InternalMessage.createBytesMessage(getAddressSpace().getMessageStore(), header, new byte[0]);
message.setInitialRoutingAddress(getName());
return message;
}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostImpl.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostImpl.java
index 289287f..fc51d42 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostImpl.java
@@ -47,6 +47,7 @@
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.RemoteHostAddress;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.server.model.port.AmqpPort;
@@ -55,8 +56,10 @@
import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.transfer.TransferQueue;
import org.apache.qpid.server.transport.AMQPConnection;
import org.apache.qpid.server.txn.DtxRegistry;
+import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.virtualhost.HouseKeepingTask;
import org.apache.qpid.server.virtualhost.NodeAutoCreationPolicy;
import org.apache.qpid.server.virtualhost.VirtualHostPrincipal;
@@ -524,6 +527,12 @@
}
@Override
+ public TransferQueue getTransferQueue()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public Principal getPrincipal()
{
return _principal;
@@ -554,6 +563,13 @@
}
@Override
+ public boolean makeConnection(final RemoteHostAddress<?> address, final Action<Boolean> onConnectionLoss)
+ {
+ throwUnsupportedForRedirector();
+ return false;
+ }
+
+ @Override
public UserPreferences createUserPreferences(final ConfiguredObject<?> object)
{
throwUnsupportedForRedirector();
diff --git a/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java b/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java
index 50ade31..5cec366 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/consumer/MockConsumer.java
@@ -36,6 +36,7 @@
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.BrokerModel;
import org.apache.qpid.server.model.ConfiguredObjectFactory;
@@ -136,7 +137,7 @@
{
}
- public long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+ public long send(final MessageInstanceConsumer consumer, MessageInstance entry, boolean batch)
{
long size = entry.getMessage().getSize();
if (messages.contains(entry))
@@ -188,12 +189,12 @@
}
@Override
- public void consumerAdded(final ConsumerImpl sub)
+ public void consumerAdded(final MessageInstanceConsumer consumer)
{
}
@Override
- public void consumerRemoved(final ConsumerImpl sub)
+ public void consumerRemoved(final MessageInstanceConsumer consumer)
{
close();
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/ConfiguredObjectTypeRegistryTest.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/ConfiguredObjectTypeRegistryTest.java
index fab9944..cc83945 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/ConfiguredObjectTypeRegistryTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/ConfiguredObjectTypeRegistryTest.java
@@ -98,7 +98,8 @@
(ConfiguredObjectOperation<TestCar>) kitCarOperations.get("openDoor");
// test explicitly setting parameter
- Object returnVal = operation.perform(object, Collections.<String, Object>singletonMap("door", "DRIVER"));
+ Object returnVal = operation.perform(object, Collections.<String, Object>singletonMap("door", "DRIVER")
+ );
assertEquals(TestCar.Door.DRIVER, returnVal);
// test default parameter
@@ -117,7 +118,8 @@
try
{
- operation.perform(object, Collections.<String, Object>singletonMap("door", "[\"eggs\", \"flour\", \"milk\"]"));
+ operation.perform(object, Collections.<String, Object>singletonMap("door", "[\"eggs\", \"flour\", \"milk\"]")
+ );
fail("Should not be able to pass in a parameter of the wrong type");
}
catch(IllegalArgumentException e)
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java
index 1c69983..85503ae 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java
@@ -385,11 +385,13 @@
final ConfiguredObjectOperation foundOperation = allOperations.get("fly");
- Object result = foundOperation.perform(testCar, Collections.<String, Object>singletonMap("height", 0));
+ Object result = foundOperation.perform(testCar, Collections.<String, Object>singletonMap("height", 0)
+ );
assertEquals("Car should be able to fly at 0m", Boolean.TRUE, result);
- result = foundOperation.perform(testCar, Collections.<String, Object>singletonMap("height", 5000));
+ result = foundOperation.perform(testCar, Collections.<String, Object>singletonMap("height", 5000)
+ );
assertEquals("Car should not be able to fly at 5000m", Boolean.FALSE, result);
}
@@ -436,11 +438,13 @@
final ConfiguredObjectOperation helloOperation = allOperations.get("sayHello");
final ConfiguredObjectOperation goodbyeOperation = allOperations.get("sayGoodbye");
- Object result = helloOperation.perform(testCar, Collections.<String, Object>singletonMap("count", 3));
+ Object result = helloOperation.perform(testCar, Collections.<String, Object>singletonMap("count", 3)
+ );
assertEquals("Car should say 'Hello' 3 times", Arrays.asList("Hello", "Hello", "Hello"), result);
- result = goodbyeOperation.perform(testCar, Collections.<String, Object>singletonMap("count", 1));
+ result = goodbyeOperation.perform(testCar, Collections.<String, Object>singletonMap("count", 1)
+ );
assertEquals("Car say 'Goodbye' once", Collections.singletonList("Goodbye"), result);
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/AbstractConfiguredObjectTest.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/AbstractConfiguredObjectTest.java
index a63fb82..4a95c40 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/AbstractConfiguredObjectTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/AbstractConfiguredObjectTest.java
@@ -30,7 +30,7 @@
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.IllegalStateTransitionException;
-import org.apache.qpid.server.model.NoopConfigurationChangeListener;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.State;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -231,7 +231,7 @@
final AtomicReference<State> newState = new AtomicReference<>();
final AtomicInteger callCounter = new AtomicInteger();
- parent.addChangeListener(new NoopConfigurationChangeListener()
+ parent.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(final ConfiguredObject<?> object, final State old, final State state)
@@ -262,7 +262,7 @@
parent.create();
final AtomicInteger callCounter = new AtomicInteger();
- parent.addChangeListener(new NoopConfigurationChangeListener()
+ parent.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void stateChanged(final ConfiguredObject<?> object, final State old, final State state)
@@ -300,7 +300,7 @@
configuredObject.create();
final List<ChangeEvent> events = new ArrayList<>();
- configuredObject.addChangeListener(new NoopConfigurationChangeListener()
+ configuredObject.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/AbstractConfiguredObjectTest.java b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/AbstractConfiguredObjectTest.java
index 321d585..5ebf24a 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/AbstractConfiguredObjectTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/AbstractConfiguredObjectTest.java
@@ -37,7 +37,7 @@
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Model;
-import org.apache.qpid.server.model.NoopConfigurationChangeListener;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
import org.apache.qpid.server.security.auth.UsernamePrincipal;
@@ -789,7 +789,7 @@
final AtomicInteger listenerCount = new AtomicInteger();
final LinkedHashMap<String, String> updates = new LinkedHashMap<>();
- object.addChangeListener(new NoopConfigurationChangeListener()
+ object.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void attributeSet(final ConfiguredObject<?> object,
@@ -844,7 +844,7 @@
final TestSingleton object = _model.getObjectFactory().create(TestSingleton.class, attributes);
final AtomicInteger listenerCount = new AtomicInteger();
- object.addChangeListener(new NoopConfigurationChangeListener()
+ object.addChangeListener(new AbstractConfigurationChangeListener()
{
@Override
public void attributeSet(final ConfiguredObject<?> object,
diff --git a/broker-core/src/test/java/org/apache/qpid/server/queue/AbstractQueueTestBase.java b/broker-core/src/test/java/org/apache/qpid/server/queue/AbstractQueueTestBase.java
index f53ea8f..fffdea6 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/queue/AbstractQueueTestBase.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/queue/AbstractQueueTestBase.java
@@ -40,10 +40,6 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import org.apache.qpid.server.model.Binding;
-import org.apache.qpid.server.model.Exchange;
-import org.apache.qpid.server.model.VirtualHost;
-import org.apache.qpid.server.util.StateChangeListener;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -51,21 +47,27 @@
import org.slf4j.LoggerFactory;
import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.MockConsumer;
import org.apache.qpid.server.exchange.DirectExchange;
import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.BrokerTestHelper;
+import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.QueueNotificationListener;
+import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.queue.AbstractQueue.QueueEntryFilter;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.util.Action;
-import org.apache.qpid.server.model.BrokerTestHelper;
+import org.apache.qpid.server.util.StateChangeListener;
import org.apache.qpid.test.utils.QpidTestCase;
abstract class AbstractQueueTestBase extends QpidTestCase
@@ -173,8 +175,8 @@
// Check adding a consumer adds it to the queue
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
assertEquals("Queue does not have consumer", 1,
_queue.getConsumerCount());
assertEquals("Queue does not have active consumer", 1,
@@ -205,8 +207,8 @@
ServerMessage messageA = createMessage(new Long(24));
_queue.enqueue(messageA, null, null);
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
Thread.sleep(_queueRunnerWaitTime);
assertEquals(messageA, _consumer.getQueueContext().getLastSeenEntry().getMessage());
assertNull("There should be no releasedEntry after an enqueue",
@@ -223,8 +225,8 @@
_queue.enqueue(messageA, null, null);
_queue.enqueue(messageB, null, null);
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
Thread.sleep(_queueRunnerWaitTime);
assertEquals(messageB, _consumer.getQueueContext().getLastSeenEntry().getMessage());
assertNull("There should be no releasedEntry after enqueues",
@@ -246,8 +248,8 @@
when(messageHeader.getNotValidBefore()).thenReturn(System.currentTimeMillis()+20000L);
_queue.enqueue(messageA, null, null);
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
Thread.sleep(_queueRunnerWaitTime);
assertEquals("Message which was not yet valid was received", 0, _consumerTarget.getMessages().size());
@@ -272,8 +274,8 @@
when(messageHeader.getNotValidBefore()).thenReturn(System.currentTimeMillis()+20000L);
_queue.enqueue(messageA, null, null);
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
Thread.sleep(_queueRunnerWaitTime);
assertEquals("Message was held despite queue not having holding enabled", 1, _consumerTarget.getMessages().size());
@@ -298,8 +300,8 @@
_queue.enqueue(messageB, null, null);
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
Thread.sleep(_queueRunnerWaitTime);
assertEquals("Expect one message (message B)", 1, _consumerTarget.getMessages().size());
@@ -326,8 +328,8 @@
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
EntryListAddingAction postEnqueueAction = new EntryListAddingAction(queueEntries);
@@ -375,7 +377,7 @@
_consumerTarget = new MockConsumer()
{
@Override
- public long send(ConsumerImpl consumer, MessageInstance entry, boolean batch)
+ public long send(MessageInstanceConsumer consumer, MessageInstance entry, boolean batch)
{
try
{
@@ -389,8 +391,8 @@
};
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.SEES_REQUEUES,
- ConsumerImpl.Option.ACQUIRES), 0);
+ EnumSet.of(ConsumerOption.SEES_REQUEUES,
+ ConsumerOption.ACQUIRES), 0);
final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
EntryListAddingAction postEnqueueAction = new EntryListAddingAction(queueEntries);
@@ -460,8 +462,8 @@
ServerMessage messageC = createMessage(new Long(26));
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
EntryListAddingAction postEnqueueAction = new EntryListAddingAction(queueEntries);
@@ -513,12 +515,12 @@
QueueConsumer consumer1 = (QueueConsumer) _queue.addConsumer(target1, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
QueueConsumer consumer2 = (QueueConsumer) _queue.addConsumer(target2, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
final ArrayList<QueueEntry> queueEntries = new ArrayList<QueueEntry>();
@@ -555,8 +557,8 @@
// Check adding an exclusive consumer adds it to the queue
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.EXCLUSIVE, ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.EXCLUSIVE, ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
assertEquals("Queue does not have consumer", 1,
_queue.getConsumerCount());
@@ -585,8 +587,8 @@
{
_queue.addConsumer(subB, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
}
catch (MessageSource.ExistingExclusiveConsumer e)
@@ -599,14 +601,14 @@
// existing consumer
_consumer.close();
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
try
{
_consumer = (QueueConsumer<?>) _queue.addConsumer(subB, null, messageA.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.EXCLUSIVE), 0);
+ EnumSet.of(ConsumerOption.EXCLUSIVE), 0);
}
catch (MessageSource.ExistingConsumerPreventsExclusive e)
@@ -623,13 +625,13 @@
ServerMessage message = createMessage(id);
_consumer = (QueueConsumer<?>) _queue.addConsumer(_consumerTarget, null, message.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES, ConsumerImpl.Option.SEES_REQUEUES),
+ EnumSet.of(ConsumerOption.ACQUIRES, ConsumerOption.SEES_REQUEUES),
0);
- _queue.enqueue(message, new Action<MessageInstance>()
+ _queue.enqueue(message, new Action<BaseMessageInstance>()
{
@Override
- public void performAction(final MessageInstance object)
+ public void performAction(final BaseMessageInstance object)
{
QueueEntryImpl entry = (QueueEntryImpl) object;
entry.setRedelivered();
@@ -1189,7 +1191,7 @@
return message;
}
- private static class EntryListAddingAction implements Action<MessageInstance>
+ private static class EntryListAddingAction implements Action<BaseMessageInstance>
{
private final ArrayList<QueueEntry> _queueEntries;
@@ -1198,7 +1200,7 @@
_queueEntries = queueEntries;
}
- public void performAction(MessageInstance entry)
+ public void performAction(BaseMessageInstance entry)
{
_queueEntries.add((QueueEntry) entry);
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/queue/ConsumerListTest.java b/broker-core/src/test/java/org/apache/qpid/server/queue/ConsumerListTest.java
index 357c720..58993ec 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/queue/ConsumerListTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/queue/ConsumerListTest.java
@@ -21,13 +21,12 @@
package org.apache.qpid.server.queue;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.message.MessageInstance;
-import org.apache.qpid.test.utils.QpidTestCase;
-
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.test.utils.QpidTestCase;
+
public class ConsumerListTest extends QpidTestCase
{
private QueueConsumerList _subList;
@@ -147,7 +146,7 @@
* Traverses the list nodes in a non-mutating fashion, returning the first node which matches the given
* Consumer, or null if none is found.
*/
- private ConsumerNode getNodeForConsumer(final QueueConsumerList list, final ConsumerImpl sub)
+ private ConsumerNode getNodeForConsumer(final QueueConsumerList list, final QueueConsumer sub)
{
ConsumerNode node = list.getHead();
while (node != null && node.getConsumer() != sub)
diff --git a/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java b/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java
index 31534be..728a72a 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/queue/MockMessageInstance.java
@@ -20,11 +20,12 @@
*/
package org.apache.qpid.server.queue;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.filter.Filterable;
import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.BaseMessageInstance;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.store.MessageEnqueueRecord;
import org.apache.qpid.server.store.TransactionLogResource;
@@ -49,7 +50,7 @@
}
@Override
- public int routeToAlternate(final Action<? super MessageInstance> action,
+ public int routeToAlternate(final Action<? super BaseMessageInstance> action,
final ServerTransaction txn)
{
return 0;
@@ -61,7 +62,7 @@
}
@Override
- public ConsumerImpl getAcquiringConsumer()
+ public MessageInstanceConsumer getAcquiringConsumer()
{
return null;
}
@@ -73,13 +74,13 @@
}
@Override
- public boolean isAcquiredBy(final ConsumerImpl consumer)
+ public boolean isAcquiredBy(final MessageInstanceConsumer consumer)
{
return false;
}
@Override
- public boolean removeAcquisitionFromConsumer(final ConsumerImpl consumer)
+ public boolean removeAcquisitionFromConsumer(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -95,13 +96,13 @@
}
@Override
- public boolean acquire(final ConsumerImpl sub)
+ public boolean acquire(final MessageInstanceConsumer sub)
{
return false;
}
@Override
- public boolean makeAcquisitionUnstealable(final ConsumerImpl consumer)
+ public boolean makeAcquisitionUnstealable(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -117,7 +118,7 @@
return false;
}
- public ConsumerImpl getDeliveredConsumer()
+ public MessageInstanceConsumer getDeliveredConsumer()
{
return null;
}
@@ -147,7 +148,7 @@
}
@Override
- public boolean isRejectedBy(final ConsumerImpl consumer)
+ public boolean isRejectedBy(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -158,7 +159,7 @@
}
@Override
- public void release(final ConsumerImpl release)
+ public void release(final MessageInstanceConsumer release)
{
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java b/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java
index d9ec109..e307c5b 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/queue/PriorityQueueTest.java
@@ -28,8 +28,8 @@
import junit.framework.AssertionFailedError;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.AMQMessageHeader;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
@@ -63,7 +63,7 @@
queue.enqueue(createMessage(9L, (byte) 0), null, null);
// Register subscriber
- queue.addConsumer(getConsumer(), null, null, "test", EnumSet.noneOf(ConsumerImpl.Option.class), 0);
+ queue.addConsumer(getConsumer(), null, null, "test", EnumSet.noneOf(ConsumerOption.class), 0);
Thread.sleep(150);
ArrayList<MessageInstance> msgs = getConsumer().getMessages();
diff --git a/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java b/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java
index 3e07bda..08f8dad 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java
@@ -145,7 +145,9 @@
StealableConsumerAcquiredState
owningState = new StealableConsumerAcquiredState(consumer);
when(consumer.getOwningState()).thenReturn(owningState);
- when(consumer.getConsumerNumber()).thenReturn(_consumerId++);
+ final long consumerNum = _consumerId++;
+ when(consumer.getConsumerNumber()).thenReturn(consumerNum);
+ when(consumer.getIdentifier()).thenReturn(consumerNum);
return consumer;
}
@@ -298,7 +300,7 @@
StandardQueueImpl queue = new StandardQueueImpl(queueAttributes, virtualHost);
queue.open();
- OrderedQueueEntryList queueEntryList = queue.getEntries();
+ OrderedBaseQueueEntryList queueEntryList = queue.getEntries();
// create test entries
for(int i = 0; i < numberOfEntries ; i++)
diff --git a/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java b/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
index 7671218..691879d 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java
@@ -44,7 +44,7 @@
public class SimpleQueueEntryImplTest extends QueueEntryImplTestBase
{
- private OrderedQueueEntryList queueEntryList;
+ private OrderedBaseQueueEntryList queueEntryList;
@Override
public void setUp() throws Exception
diff --git a/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java b/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java
index 2f4005c..44a65f1 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueEntryListTest.java
@@ -160,7 +160,7 @@
public void testScavenge() throws Exception
{
- OrderedQueueEntryList sqel = new StandardQueueEntryList(mock(StandardQueueImpl.class));
+ OrderedBaseQueueEntryList sqel = new StandardQueueEntryList(mock(StandardQueueImpl.class));
ConcurrentMap<Integer,QueueEntry> entriesMap = new ConcurrentHashMap<Integer,QueueEntry>();
@@ -265,7 +265,7 @@
{
final int numberOfEntries = 5;
final OrderedQueueEntry[] entries = new OrderedQueueEntry[numberOfEntries];
- final OrderedQueueEntryList queueEntryList = getTestList(true);
+ final OrderedBaseQueueEntryList queueEntryList = getTestList(true);
// create test entries
for(int i = 0; i < numberOfEntries; i++)
diff --git a/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java b/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java
index d386e49..aae05f4 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/queue/StandardQueueTest.java
@@ -29,10 +29,11 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
import org.apache.qpid.server.consumer.MockConsumer;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Queue;
@@ -57,8 +58,8 @@
ServerMessage message = createMessage(25l);
QueueConsumer consumer =
(QueueConsumer) getQueue().addConsumer(getConsumerTarget(), null, message.getClass(), "test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
getQueue().enqueue(message, null, null);
consumer.close();
@@ -83,8 +84,8 @@
null,
createMessage(-1l).getClass(),
"test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
assertEquals("Unexpected active consumer count", 1, queue.getConsumerCountWithCredit());
//verify adding an inactive consumer doesn't increase the count
@@ -96,8 +97,8 @@
null,
createMessage(-1l).getClass(),
"test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
assertEquals("Unexpected active consumer count", 1, queue.getConsumerCountWithCredit());
//verify behaviour in face of expected state changes:
@@ -151,8 +152,8 @@
null,
createMessage(-1l).getClass(),
"test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
// put test messages into a queue
putGivenNumberOfMessages(queue, 4);
@@ -201,7 +202,7 @@
* @param entry
* @param batch
*/
- public long send(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+ public long send(final MessageInstanceConsumer consumer, MessageInstance entry, boolean batch)
{
long size = super.send(consumer, entry, batch);
latch.countDown();
@@ -214,8 +215,8 @@
null,
entries.get(0).getMessage().getClass(),
"test",
- EnumSet.of(ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES), 0);
+ EnumSet.of(ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES), 0);
// process queue
testQueue.processQueue(new QueueRunner(testQueue, AccessController.getContext())
@@ -341,7 +342,7 @@
}
@Override
- public boolean acquire(ConsumerImpl sub)
+ public boolean acquire(MessageInstanceConsumer sub)
{
if(_message.getMessageNumber() % 2 == 0)
{
@@ -354,7 +355,7 @@
}
@Override
- public boolean makeAcquisitionUnstealable(final ConsumerImpl consumer)
+ public boolean makeAcquisitionUnstealable(final MessageInstanceConsumer consumer)
{
return true;
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/security/TrustStoreMessageSourceTest.java b/broker-core/src/test/java/org/apache/qpid/server/security/TrustStoreMessageSourceTest.java
index 0f9569f..6cada6d 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/security/TrustStoreMessageSourceTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/security/TrustStoreMessageSourceTest.java
@@ -38,9 +38,10 @@
import org.mockito.ArgumentCaptor;
import org.apache.qpid.bytebuffer.QpidByteBuffer;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.TrustStore;
@@ -74,14 +75,14 @@
public void testAddConsumer() throws Exception
{
- final EnumSet<ConsumerImpl.Option> options = EnumSet.noneOf(ConsumerImpl.Option.class);
+ final EnumSet<ConsumerOption> options = EnumSet.noneOf(ConsumerOption.class);
final ConsumerTarget target = mock(ConsumerTarget.class);
when(target.allocateCredit(any(ServerMessage.class))).thenReturn(true);
_trustStoreMessageSource.addConsumer(target, null, ServerMessage.class, getTestName(), options, 0);
ArgumentCaptor<MessageInstance> argumentCaptor = ArgumentCaptor.forClass(MessageInstance.class);
- verify(target).send(any(ConsumerImpl.class), argumentCaptor.capture(), anyBoolean());
+ verify(target).send(any(MessageInstanceConsumer.class), argumentCaptor.capture(), anyBoolean());
final ServerMessage message = argumentCaptor.getValue().getMessage();
assertCertificates(getCertificatesFromMessage(message));
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AsynchronousMessageStoreRecovererTest.java b/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AsynchronousMessageStoreRecovererTest.java
index f095f92..a948519 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AsynchronousMessageStoreRecovererTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AsynchronousMessageStoreRecovererTest.java
@@ -37,6 +37,7 @@
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.TransactionLogResource;
import org.apache.qpid.server.store.handler.MessageInstanceHandler;
+import org.apache.qpid.server.transfer.TransferQueue;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
import org.apache.qpid.test.utils.QpidTestCase;
@@ -54,6 +55,9 @@
_virtualHost = mock(VirtualHost.class);
_store = mock(MessageStore.class);
_storeReader = mock(MessageStore.MessageStoreReader.class);
+ TransferQueue tq = mock(TransferQueue.class);
+ when(tq.getName()).thenReturn("$transfer");
+ when(_virtualHost.getTransferQueue()).thenReturn(tq);
when(_virtualHost.getEventLogger()).thenReturn(new EventLogger());
when(_virtualHost.getMessageStore()).thenReturn(_store);
diff --git a/broker-core/src/test/java/org/apache/qpid/server/virtualhost/SynchronousMessageStoreRecovererTest.java b/broker-core/src/test/java/org/apache/qpid/server/virtualhost/SynchronousMessageStoreRecovererTest.java
index 55fde08..d5821c1 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/virtualhost/SynchronousMessageStoreRecovererTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/virtualhost/SynchronousMessageStoreRecovererTest.java
@@ -32,15 +32,14 @@
import java.util.UUID;
-import org.apache.qpid.server.model.Queue;
-import org.apache.qpid.server.model.VirtualHost;
-import org.apache.qpid.test.utils.QpidTestCase;
import org.mockito.ArgumentMatcher;
import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.message.BaseMessageInstance;
import org.apache.qpid.server.message.EnqueueableMessage;
-import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.store.MessageDurability;
import org.apache.qpid.server.store.MessageEnqueueRecord;
@@ -55,9 +54,11 @@
import org.apache.qpid.server.store.handler.DistributedTransactionHandler;
import org.apache.qpid.server.store.handler.MessageHandler;
import org.apache.qpid.server.store.handler.MessageInstanceHandler;
+import org.apache.qpid.server.transfer.TransferQueue;
import org.apache.qpid.server.txn.DtxBranch;
import org.apache.qpid.server.txn.DtxRegistry;
import org.apache.qpid.server.util.Action;
+import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.transport.Xid;
public class SynchronousMessageStoreRecovererTest extends QpidTestCase
@@ -70,7 +71,11 @@
super.setUp();
_virtualHost = mock(VirtualHost.class);
+ TransferQueue tq = mock(TransferQueue.class);
+ UUID tqId = UUID.randomUUID();
+ when(tq.getId()).thenReturn(tqId);
when(_virtualHost.getEventLogger()).thenReturn(new EventLogger());
+ when(_virtualHost.getTransferQueue()).thenReturn(tq);
}
@@ -294,7 +299,7 @@
branch.commit();
ServerMessage<?> message = storedMessage.getMetaData().getType().createMessage(storedMessage);
- verify(queue, times(1)).enqueue(eq(message), (Action<? super MessageInstance>)isNull(), any(MessageEnqueueRecord.class));
+ verify(queue, times(1)).enqueue(eq(message), (Action<? super BaseMessageInstance>)isNull(), any(MessageEnqueueRecord.class));
verify(transaction).commitTran();
}
diff --git a/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostPropertiesNodeTest.java b/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostPropertiesNodeTest.java
index dd2dd47..11e73e5 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostPropertiesNodeTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostPropertiesNodeTest.java
@@ -26,9 +26,10 @@
import java.util.EnumSet;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.store.MessageStore;
@@ -52,11 +53,11 @@
public void testAddConsumer() throws Exception
{
- final EnumSet<ConsumerImpl.Option> options = EnumSet.noneOf(ConsumerImpl.Option.class);
+ final EnumSet<ConsumerOption> options = EnumSet.noneOf(ConsumerOption.class);
final ConsumerTarget target = mock(ConsumerTarget.class);
when(target.allocateCredit(any(ServerMessage.class))).thenReturn(true);
_virtualHostPropertiesNode.addConsumer(target, null, ServerMessage.class, getTestName(), options, 0);
- verify(target).send(any(ConsumerImpl.class), any(MessageInstance.class), anyBoolean());
+ verify(target).send(any(MessageInstanceConsumer.class), any(MessageInstance.class), anyBoolean());
}
}
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java
index cfb6770..b93be3d 100644
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ConsumerTarget_0_10.java
@@ -31,13 +31,14 @@
import org.apache.qpid.bytebuffer.QpidByteBuffer;
import org.apache.qpid.server.consumer.AbstractConsumerTarget;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.messages.ChannelMessages;
+import org.apache.qpid.server.message.BaseMessageInstance;
import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageInstance.ConsumerAcquiredState;
import org.apache.qpid.server.message.MessageInstance.EntryState;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.Queue;
@@ -148,7 +149,6 @@
// TODO check for Session suspension
}
- @Override
protected void doCloseInternal()
{
_creditManager.removeListener(this);
@@ -213,7 +213,7 @@
private final AddMessageDispositionListenerAction _postIdSettingAction;
- public void doSend(final ConsumerImpl consumer, final MessageInstance entry, boolean batch)
+ public void doSend(final MessageInstanceConsumer consumer, final MessageInstance entry, boolean batch)
{
ServerMessage serverMsg = entry.getMessage();
@@ -435,7 +435,7 @@
});
}
- void reject(final ConsumerImpl consumer, final MessageInstance entry)
+ void reject(final MessageInstanceConsumer consumer, final MessageInstance entry)
{
entry.setRedelivered();
if (entry.makeAcquisitionUnstealable(consumer))
@@ -444,7 +444,7 @@
}
}
- void release(final ConsumerImpl consumer,
+ void release(final MessageInstanceConsumer consumer,
final MessageInstance entry,
final boolean setRedelivered)
{
@@ -468,17 +468,17 @@
}
}
- protected void sendToDLQOrDiscard(final ConsumerImpl consumer, MessageInstance entry)
+ protected void sendToDLQOrDiscard(final MessageInstanceConsumer consumer, MessageInstance entry)
{
final ServerMessage msg = entry.getMessage();
int requeues = 0;
if (entry.makeAcquisitionUnstealable(consumer))
{
- requeues = entry.routeToAlternate(new Action<MessageInstance>()
+ requeues = entry.routeToAlternate(new Action<BaseMessageInstance>()
{
@Override
- public void performAction(final MessageInstance requeueEntry)
+ public void performAction(final BaseMessageInstance requeueEntry)
{
getEventLogger().message(ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(),
requeueEntry.getOwningResource()
@@ -614,7 +614,7 @@
public void flush()
{
flushCreditState(true);
- for(ConsumerImpl consumer : getConsumers())
+ for(MessageInstanceConsumer consumer : getConsumers())
{
consumer.flush();
}
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java
index 0a12dfd..283315d 100755
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java
@@ -23,8 +23,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener
@@ -34,11 +34,11 @@
private final MessageInstance _entry;
private final ConsumerTarget_0_10 _target;
- private final ConsumerImpl _consumer;
+ private final MessageInstanceConsumer _consumer;
public ExplicitAcceptDispositionChangeListener(MessageInstance entry,
ConsumerTarget_0_10 target,
- final ConsumerImpl consumer)
+ final MessageInstanceConsumer consumer)
{
_entry = entry;
_target = target;
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java
index 10bc474..8adf027 100755
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java
@@ -23,8 +23,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener
{
@@ -33,11 +33,11 @@
private final MessageInstance _entry;
private final ConsumerTarget_0_10 _target;
- private final ConsumerImpl _consumer;
+ private final MessageInstanceConsumer _consumer;
public ImplicitAcceptDispositionChangeListener(MessageInstance entry,
ConsumerTarget_0_10 target,
- final ConsumerImpl consumer)
+ final MessageInstanceConsumer consumer)
{
_entry = entry;
_target = target;
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java
index d1a4d27..3641415 100755
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java
@@ -21,8 +21,8 @@
package org.apache.qpid.server.protocol.v0_10;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.transport.Method;
public class MessageAcceptCompletionListener implements Method.CompletionListener
@@ -30,12 +30,12 @@
private final ConsumerTarget_0_10 _sub;
private final MessageInstance _entry;
private final ServerSession _session;
- private final ConsumerImpl _consumer;
+ private final MessageInstanceConsumer _consumer;
private long _messageSize;
private boolean _restoreCredit;
public MessageAcceptCompletionListener(ConsumerTarget_0_10 sub,
- final ConsumerImpl consumer,
+ final MessageInstanceConsumer consumer,
ServerSession session,
MessageInstance entry,
boolean restoreCredit)
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
index 8afa6aa..cb1fb9b 100644
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java
@@ -56,15 +56,17 @@
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.connection.SessionPrincipal;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
import org.apache.qpid.server.logging.LogMessage;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.messages.ChannelMessages;
import org.apache.qpid.server.logging.subjects.ChannelLogSubject;
+import org.apache.qpid.server.message.BaseMessageInstance;
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.MessageInstanceConsumer;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
@@ -536,7 +538,7 @@
// Broker shouldn't block awaiting close - thus do override this method to do nothing
}
- public void acknowledge(final ConsumerImpl consumer,
+ public void acknowledge(final MessageInstanceConsumer consumer,
final ConsumerTarget_0_10 target,
final MessageInstance entry)
{
@@ -573,14 +575,14 @@
}
- public void register(final ConsumerImpl consumerImpl)
+ public void register(final MessageInstanceConsumer consumer)
{
- if(consumerImpl instanceof Consumer<?>)
+ if(consumer instanceof Consumer<?>)
{
- final Consumer<?> consumer = (Consumer<?>) consumerImpl;
- _consumers.add(consumer);
- consumer.addChangeListener(_consumerClosedListener);
- consumerAdded(consumer);
+ final Consumer<?> modelConsumer = (Consumer<?>) consumer;
+ _consumers.add(modelConsumer);
+ modelConsumer.addChangeListener(_consumerClosedListener);
+ consumerAdded(modelConsumer);
}
}
@@ -1296,10 +1298,10 @@
return getId().compareTo(o.getId());
}
- private class CheckCapacityAction implements Action<MessageInstance>
+ private class CheckCapacityAction implements Action<BaseMessageInstance>
{
@Override
- public void performAction(final MessageInstance entry)
+ public void performAction(final BaseMessageInstance entry)
{
TransactionLogResource queue = entry.getOwningResource();
if(queue instanceof CapacityChecker)
@@ -1309,7 +1311,7 @@
}
}
- private class ConsumerClosedListener implements ConfigurationChangeListener
+ private class ConsumerClosedListener extends AbstractConfigurationChangeListener
{
@Override
public void stateChanged(final ConfiguredObject object, final org.apache.qpid.server.model.State oldState, final org.apache.qpid.server.model.State newState)
@@ -1320,37 +1322,5 @@
}
}
- @Override
- public void childAdded(final ConfiguredObject object, final ConfiguredObject child)
- {
-
- }
-
- @Override
- public void childRemoved(final ConfiguredObject object, final ConfiguredObject child)
- {
-
- }
-
- @Override
- public void attributeSet(final ConfiguredObject object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
-
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
}
}
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
index 898edd6..a999d4e 100644
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
@@ -39,7 +39,6 @@
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.filter.AMQInvalidArgumentException;
import org.apache.qpid.server.filter.ArrivalTimeFilter;
import org.apache.qpid.server.filter.FilterManager;
@@ -48,6 +47,7 @@
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.messages.ChannelMessages;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
+import org.apache.qpid.server.message.ConsumerOption;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageDestination;
import org.apache.qpid.server.message.MessageReference;
@@ -338,18 +338,18 @@
((ServerSession)session).register(destination, target);
try
{
- EnumSet<ConsumerImpl.Option> options = EnumSet.noneOf(ConsumerImpl.Option.class);
+ EnumSet<ConsumerOption> options = EnumSet.noneOf(ConsumerOption.class);
if(method.getAcquireMode() == MessageAcquireMode.PRE_ACQUIRED)
{
- options.add(ConsumerImpl.Option.ACQUIRES);
+ options.add(ConsumerOption.ACQUIRES);
}
if(method.getAcquireMode() != MessageAcquireMode.NOT_ACQUIRED || method.getAcceptMode() == MessageAcceptMode.EXPLICIT)
{
- options.add(ConsumerImpl.Option.SEES_REQUEUES);
+ options.add(ConsumerOption.SEES_REQUEUES);
}
if(method.getExclusive())
{
- options.add(ConsumerImpl.Option.EXCLUSIVE);
+ options.add(ConsumerOption.EXCLUSIVE);
}
for(MessageSource source : sources)
{
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
index ccfb99e..46d5939 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
@@ -57,7 +57,6 @@
import org.apache.qpid.framing.*;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.connection.SessionPrincipal;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
import org.apache.qpid.server.filter.AMQInvalidArgumentException;
import org.apache.qpid.server.filter.ArrivalTimeFilter;
@@ -73,12 +72,16 @@
import org.apache.qpid.server.logging.messages.ChannelMessages;
import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.logging.subjects.ChannelLogSubject;
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.ConsumerOption;
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.MessageInstanceConsumer;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.MessageSource;
import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
@@ -307,7 +310,7 @@
final RecordDeliveryMethod getRecordMethod = new RecordDeliveryMethod()
{
- public void recordMessageDelivery(final ConsumerImpl sub,
+ public void recordMessageDelivery(final MessageInstanceConsumer sub,
final MessageInstance entry,
final long deliveryTag)
{
@@ -316,8 +319,8 @@
};
ConsumerTarget_0_8 target;
- EnumSet<ConsumerImpl.Option> options = EnumSet.of(ConsumerImpl.Option.TRANSIENT, ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES);
+ EnumSet<ConsumerOption> options = EnumSet.of(ConsumerOption.TRANSIENT, ConsumerOption.ACQUIRES,
+ ConsumerOption.SEES_REQUEUES);
if (acks)
{
@@ -332,7 +335,7 @@
singleMessageCredit, getDeliveryMethod, getRecordMethod);
}
- ConsumerImpl sub = queue.addConsumer(target, null, AMQMessage.class, "", options, null);
+ MessageInstanceConsumer sub = queue.addConsumer(target, null, AMQMessage.class, "", options, null);
sub.flush();
sub.close();
return getDeliveryMethod.hasDeliveredMessage();
@@ -629,12 +632,13 @@
}
else
{
+ if(_confirmOnPublish)
+ {
+ _connection.writeFrame(new AMQFrame(_channelId, new BasicNackBody(_confirmedMessageCounter, false, false)));
+ }
+
if (mandatory || message.isImmediate())
{
- if(_confirmOnPublish)
- {
- _connection.writeFrame(new AMQFrame(_channelId, new BasicNackBody(_confirmedMessageCounter, false, false)));
- }
_transaction.addPostTransactionAction(new WriteReturnAction(AMQConstant.NO_ROUTE,
"No Route for message "
+ description,
@@ -726,7 +730,7 @@
}
ConsumerTarget_0_8 target;
- EnumSet<ConsumerImpl.Option> options = EnumSet.noneOf(ConsumerImpl.Option.class);
+ EnumSet<ConsumerOption> options = EnumSet.noneOf(ConsumerOption.class);
final boolean multiQueue = sources.size()>1;
if(arguments != null && Boolean.TRUE.equals(arguments.get(AMQPFilterTypes.NO_CONSUME.getValue())))
{
@@ -735,19 +739,19 @@
else if(acks)
{
target = ConsumerTarget_0_8.createAckTarget(this, tag, arguments, _creditManager, multiQueue);
- options.add(ConsumerImpl.Option.ACQUIRES);
- options.add(ConsumerImpl.Option.SEES_REQUEUES);
+ options.add(ConsumerOption.ACQUIRES);
+ options.add(ConsumerOption.SEES_REQUEUES);
}
else
{
target = ConsumerTarget_0_8.createNoAckTarget(this, tag, arguments, _noAckCreditManager, multiQueue);
- options.add(ConsumerImpl.Option.ACQUIRES);
- options.add(ConsumerImpl.Option.SEES_REQUEUES);
+ options.add(ConsumerOption.ACQUIRES);
+ options.add(ConsumerOption.SEES_REQUEUES);
}
if(exclusive)
{
- options.add(ConsumerImpl.Option.EXCLUSIVE);
+ options.add(ConsumerOption.EXCLUSIVE);
}
@@ -831,7 +835,7 @@
for(MessageSource source : sources)
{
- ConsumerImpl sub =
+ MessageInstanceConsumer sub =
source.addConsumer(target,
filterManager,
AMQMessage.class,
@@ -871,15 +875,15 @@
}
ConsumerTarget_0_8 target = _tag2SubscriptionTargetMap.remove(consumerTag);
- Collection<ConsumerImpl> subs = target == null ? null : target.getConsumers();
- if (subs != null)
+ Collection<MessageInstanceConsumer> consumers = target == null ? null : target.getConsumers();
+ if (consumers != null)
{
- for(ConsumerImpl sub : subs)
+ for(MessageInstanceConsumer consumer : consumers)
{
- sub.close();
- if (sub instanceof Consumer<?>)
+ consumer.close();
+ if (consumer instanceof Consumer<?>)
{
- _consumers.remove(sub);
+ _consumers.remove(consumer);
}
}
return true;
@@ -959,13 +963,12 @@
/**
* Add a message to the channel-based list of unacknowledged messages
- *
- * @param entry the record of the message on the queue that was delivered
+ * @param entry the record of the message on the queue that was delivered
* @param deliveryTag the delivery tag used when delivering the message (see protocol spec for description of the
* delivery tag)
* @param consumer The consumer that is to acknowledge this message.
*/
- public void addUnacknowledgedMessage(MessageInstance entry, long deliveryTag, ConsumerImpl consumer)
+ public void addUnacknowledgedMessage(MessageInstance entry, long deliveryTag, MessageInstanceConsumer consumer)
{
if (_logger.isDebugEnabled())
{
@@ -1211,9 +1214,9 @@
// may need to deliver queued messages
for (ConsumerTarget_0_8 s : getConsumerTargets())
{
- for(ConsumerImpl sub : s.getConsumers())
+ for(MessageInstanceConsumer consumer : s.getConsumers())
{
- sub.externalStateChange();
+ consumer.externalStateChange();
}
}
}
@@ -1319,7 +1322,7 @@
for(MessageInstance entry : _resendList)
{
- ConsumerImpl sub = entry.getAcquiringConsumer();
+ MessageInstanceConsumer sub = entry.getAcquiringConsumer();
if (sub == null || sub.isClosed())
{
entry.release(sub);
@@ -1336,9 +1339,9 @@
_suspended.set(false);
for(ConsumerTarget_0_8 target : getConsumerTargets())
{
- for(ConsumerImpl sub : target.getConsumers())
+ for(MessageInstanceConsumer consumer : target.getConsumers())
{
- sub.externalStateChange();
+ consumer.externalStateChange();
}
}
@@ -1388,7 +1391,7 @@
private final RecordDeliveryMethod _recordDeliveryMethod = new RecordDeliveryMethod()
{
- public void recordMessageDelivery(final ConsumerImpl sub, final MessageInstance entry, final long deliveryTag)
+ public void recordMessageDelivery(final MessageInstanceConsumer sub, final MessageInstance entry, final long deliveryTag)
{
addUnacknowledgedMessage(entry, deliveryTag, sub);
}
@@ -1508,7 +1511,7 @@
}
@Override
- public long deliverToClient(final ConsumerImpl sub, final ServerMessage message,
+ public long deliverToClient(final MessageInstanceConsumer consumer, final ServerMessage message,
final InstanceProperties props, final long deliveryTag)
{
_singleMessageCredit.useCreditForMessage(message.getSize());
@@ -1530,14 +1533,14 @@
}
- private class ImmediateAction implements Action<MessageInstance>
+ private class ImmediateAction implements Action<BaseMessageInstance>
{
public ImmediateAction()
{
}
- public void performAction(MessageInstance entry)
+ public void performAction(BaseMessageInstance entry)
{
TransactionLogResource queue = entry.getOwningResource();
@@ -1595,10 +1598,10 @@
}
}
- private final class CapacityCheckAction implements Action<MessageInstance>
+ private final class CapacityCheckAction implements Action<BaseMessageInstance>
{
@Override
- public void performAction(final MessageInstance entry)
+ public void performAction(final BaseMessageInstance entry)
{
TransactionLogResource queue = entry.getOwningResource();
if(queue instanceof CapacityChecker)
@@ -1800,10 +1803,10 @@
int requeues = 0;
if (rejectedQueueEntry.makeAcquisitionUnstealable(rejectedQueueEntry.getAcquiringConsumer()))
{
- requeues = rejectedQueueEntry.routeToAlternate(new Action<MessageInstance>()
+ requeues = rejectedQueueEntry.routeToAlternate(new Action<BaseMessageInstance>()
{
@Override
- public void performAction(final MessageInstance requeueEntry)
+ public void performAction(final BaseMessageInstance requeueEntry)
{
messageWithSubject(ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(),
requeueEntry.getOwningResource()
@@ -1941,7 +1944,7 @@
return Collections.unmodifiableCollection(_consumers);
}
- private class ConsumerClosedListener implements ConfigurationChangeListener
+ private class ConsumerClosedListener extends AbstractConfigurationChangeListener
{
@Override
public void stateChanged(final ConfiguredObject object, final State oldState, final State newState)
@@ -1952,38 +1955,6 @@
}
}
- @Override
- public void childAdded(final ConfiguredObject object, final ConfiguredObject child)
- {
-
- }
-
- @Override
- public void childRemoved(final ConfiguredObject object, final ConfiguredObject child)
- {
-
- }
-
- @Override
- public void attributeSet(final ConfiguredObject object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
-
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
}
private void consumerAdded(final Consumer<?> consumer)
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQPConnection_0_8Impl.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQPConnection_0_8Impl.java
index 3a51f36..68aaaea 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQPConnection_0_8Impl.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQPConnection_0_8Impl.java
@@ -61,9 +61,9 @@
import org.apache.qpid.properties.ConnectionStartProperties;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.configuration.BrokerProperties;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.logging.messages.ConnectionMessages;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.NamedAddressSpace;
@@ -757,7 +757,7 @@
}, getAccessControllerContext());
}
- public synchronized void writerIdle()
+ public void writerIdle()
{
writeFrame(HeartbeatBody.FRAME);
}
@@ -1269,14 +1269,14 @@
}
@Override
- public long deliverToClient(final ConsumerImpl sub, final ServerMessage message,
+ public long deliverToClient(final MessageInstanceConsumer consumer, final ServerMessage message,
final InstanceProperties props, final long deliveryTag)
{
long size = _protocolOutputConverter.writeDeliver(message,
props,
_channelId,
deliveryTag,
- new AMQShortString(sub.getName()));
+ new AMQShortString(consumer.getName()));
registerMessageDelivered(size);
return size;
}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ClientDeliveryMethod.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ClientDeliveryMethod.java
index c7871e8..3703b02 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ClientDeliveryMethod.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ClientDeliveryMethod.java
@@ -20,12 +20,12 @@
*/
package org.apache.qpid.server.protocol.v0_8;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.InstanceProperties;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
public interface ClientDeliveryMethod
{
- long deliverToClient(final ConsumerImpl sub, final ServerMessage message, final InstanceProperties props,
+ long deliverToClient(final MessageInstanceConsumer consumer, final ServerMessage message, final InstanceProperties props,
final long deliveryTag);
}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java
index 8736eca..c549fe1 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ConsumerTarget_0_8.java
@@ -28,11 +28,11 @@
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.consumer.AbstractConsumerTarget;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.flow.FlowCreditManager;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.MessageInstance.EntryState;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.MessageReference;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.protocol.AMQSessionModel;
@@ -102,7 +102,7 @@
* @throws QpidException
*/
@Override
- public void doSend(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+ public void doSend(final MessageInstanceConsumer consumer, MessageInstance entry, boolean batch)
{
// We don't decrement the reference here as we don't want to consume the message
// but we do want to send it to the client.
@@ -146,13 +146,12 @@
/**
* This method can be called by each of the publisher threads. As a result all changes to the channel object must be
* thread safe.
- *
- * @param consumer
+ * @param consumer
* @param entry The message to send
* @param batch
*/
@Override
- public void doSend(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+ public void doSend(final MessageInstanceConsumer consumer, MessageInstance entry, boolean batch)
{
// if we do not need to wait for client acknowledgements
// we can decrement the reference count immediately.
@@ -253,13 +252,12 @@
/**
* This method can be called by each of the publisher threads. As a result all changes to the channel object must be
* thread safe.
- *
- * @param consumer
+ * @param consumer
* @param entry The message to send
* @param batch
*/
@Override
- public void doSend(final ConsumerImpl consumer, MessageInstance entry, boolean batch)
+ public void doSend(final MessageInstanceConsumer consumer, MessageInstance entry, boolean batch)
{
// put queue entry on a list and then notify the connection to read list.
@@ -350,8 +348,6 @@
&& Boolean.valueOf(String.valueOf(arguments.get(PULL_ONLY_CONSUMER)));
}
-
-
@Override
public String getTargetAddress()
{
@@ -444,7 +440,7 @@
}
}
- protected long sendToClient(final ConsumerImpl consumer, final ServerMessage message,
+ protected long sendToClient(final MessageInstanceConsumer consumer, final ServerMessage message,
final InstanceProperties props,
final long deliveryTag)
{
@@ -453,7 +449,7 @@
}
- protected void recordMessageDelivery(final ConsumerImpl consumer,
+ protected void recordMessageDelivery(final MessageInstanceConsumer consumer,
final MessageInstance entry,
final long deliveryTag)
{
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java
index 98fd6b6..634cecf 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java
@@ -25,8 +25,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
public class ExtractResendAndRequeue implements UnacknowledgedMessageMap.Visitor
{
@@ -49,7 +49,7 @@
{
message.setRedelivered();
- final ConsumerImpl consumer = message.getDeliveredConsumer();
+ final MessageInstanceConsumer consumer = message.getDeliveredConsumer();
if (consumer != null)
{
// Consumer exists
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageContentSourceBody.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageContentSourceBody.java
new file mode 100644
index 0000000..50f17e6
--- /dev/null
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageContentSourceBody.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.QpidException;
+import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.framing.AMQBody;
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import org.apache.qpid.server.message.MessageContentSource;
+import org.apache.qpid.transport.ByteBufferSender;
+
+public class MessageContentSourceBody implements AMQBody
+{
+ public static final byte TYPE = 3;
+ private final int _length;
+ private final MessageContentSource _content;
+ private final int _offset;
+
+ public MessageContentSourceBody(MessageContentSource content, int offset, int length)
+ {
+ _content = content;
+ _offset = offset;
+ _length = length;
+ }
+
+ public byte getFrameType()
+ {
+ return TYPE;
+ }
+
+ public int getSize()
+ {
+ return _length;
+ }
+
+ @Override
+ public long writePayload(final ByteBufferSender sender)
+ {
+ long size = 0L;
+ for(QpidByteBuffer buf : _content.getContent(_offset, _length))
+ {
+ size += buf.remaining();
+
+ sender.send(buf);
+ buf.dispose();
+ }
+ return size;
+ }
+
+ public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws QpidException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[" + getClass().getSimpleName() + " offset: " + _offset + ", length: " + _length + "]";
+ }
+
+}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolOutputConverterImpl.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolOutputConverterImpl.java
index a66318a..6bab565 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolOutputConverterImpl.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolOutputConverterImpl.java
@@ -246,57 +246,6 @@
return GZIP_ENCODING.equals(contentHeaderBody.getProperties().getEncoding());
}
- private class MessageContentSourceBody implements AMQBody
- {
- public static final byte TYPE = 3;
- private final int _length;
- private final MessageContentSource _content;
- private final int _offset;
-
- public MessageContentSourceBody(MessageContentSource content, int offset, int length)
- {
- _content = content;
- _offset = offset;
- _length = length;
- }
-
- public byte getFrameType()
- {
- return TYPE;
- }
-
- public int getSize()
- {
- return _length;
- }
-
- @Override
- public long writePayload(final ByteBufferSender sender)
- {
- long size = 0L;
- for(QpidByteBuffer buf : _content.getContent(_offset, _length))
- {
- size += buf.remaining();
-
- sender.send(buf);
- buf.dispose();
- }
- return size;
- }
-
- public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws QpidException
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String toString()
- {
- return "[" + getClass().getSimpleName() + " offset: " + _offset + ", length: " + _length + "]";
- }
-
- }
-
public long writeGetOk(final ServerMessage msg,
final InstanceProperties props,
int channelId,
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/RecordDeliveryMethod.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/RecordDeliveryMethod.java
index c13ff17..34a17a4 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/RecordDeliveryMethod.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/RecordDeliveryMethod.java
@@ -20,10 +20,10 @@
*/
package org.apache.qpid.server.protocol.v0_8;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
public interface RecordDeliveryMethod
{
- void recordMessageDelivery(final ConsumerImpl sub, final MessageInstance entry, final long deliveryTag);
+ void recordMessageDelivery(final MessageInstanceConsumer sub, final MessageInstance entry, final long deliveryTag);
}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/FederationDecoder.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/FederationDecoder.java
new file mode 100644
index 0000000..01eb3bb
--- /dev/null
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/FederationDecoder.java
@@ -0,0 +1,122 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.codec.ClientDecoder;
+import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.AMQProtocolVersionException;
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
+
+class FederationDecoder extends ClientDecoder
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(FederationDecoder.class);
+
+
+ private final OutboundConnection_0_8 _connection;
+
+ FederationDecoder(final OutboundConnection_0_8 connection)
+ {
+ super(connection);
+ _connection = connection;
+ }
+
+ public void decodeBuffer(QpidByteBuffer buf) throws AMQFrameDecodingException, AMQProtocolVersionException, IOException
+ {
+ decode(buf);
+ }
+
+ @Override
+ protected void processFrame(final int channelId, final byte type, final long bodySize, final QpidByteBuffer in)
+ throws AMQFrameDecodingException
+ {
+ long startTime = 0;
+ try
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ startTime = System.currentTimeMillis();
+ }
+ OutboundChannel channel = _connection.getChannel(channelId);
+ if(channel == null)
+ {
+ doProcessFrame(channelId, type, bodySize, in);
+ }
+ else
+ {
+
+ try
+ {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Object>()
+ {
+ @Override
+ public Void run() throws IOException, AMQFrameDecodingException
+ {
+ doProcessFrame(channelId, type, bodySize, in);
+ return null;
+ }
+ }, channel.getAccessControllerContext());
+ }
+ catch (PrivilegedActionException e)
+ {
+ Throwable cause = e.getCause();
+ if(cause instanceof AMQFrameDecodingException)
+ {
+ throw (AMQFrameDecodingException) cause;
+ }
+ else if(cause instanceof RuntimeException)
+ {
+ throw (RuntimeException) cause;
+ }
+ else
+ {
+ throw new ServerScopedRuntimeException(cause);
+ }
+ }
+ }
+ }
+ finally
+ {
+ if(LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Frame handled in {} ms.", (System.currentTimeMillis() - startTime));
+ }
+ }
+ }
+
+
+ private void doProcessFrame(final int channelId, final byte type, final long bodySize, final QpidByteBuffer in)
+ throws AMQFrameDecodingException
+ {
+ super.processFrame(channelId, type, bodySize, in);
+
+ }
+
+
+}
diff --git a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundChannel.java
similarity index 70%
copy from broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
copy to broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundChannel.java
index 7ca5c6d..4769f2f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/message/MessageSourceConsumer.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundChannel.java
@@ -18,11 +18,17 @@
* under the License.
*
*/
-package org.apache.qpid.server.message;
+package org.apache.qpid.server.protocol.v0_8.federation;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.model.Consumer;
+import java.security.AccessControlContext;
-public interface MessageSourceConsumer<X extends MessageSourceConsumer<X>> extends ConsumerImpl, Consumer<MessageSourceConsumer<X>>
+import org.apache.qpid.framing.ClientChannelMethodProcessor;
+
+interface OutboundChannel extends ClientChannelMethodProcessor
{
+ AccessControlContext getAccessControllerContext();
+
+ boolean processPending();
+
+ void receivedComplete();
}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundConnection_0_8.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundConnection_0_8.java
new file mode 100644
index 0000000..9ddb011
--- /dev/null
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundConnection_0_8.java
@@ -0,0 +1,772 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.security.auth.Subject;
+import javax.security.auth.SubjectDomainCombiner;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.common.ServerPropertyNames;
+import org.apache.qpid.configuration.CommonProperties;
+import org.apache.qpid.framing.AMQDataBlock;
+import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.ClientChannelMethodProcessor;
+import org.apache.qpid.framing.ClientMethodProcessor;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
+import org.apache.qpid.framing.HeartbeatBody;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.framing.ProtocolInitiation;
+import org.apache.qpid.framing.ProtocolVersion;
+import org.apache.qpid.server.configuration.BrokerProperties;
+import org.apache.qpid.server.federation.OutboundProtocolEngine;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.Credential;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.RemoteHost;
+import org.apache.qpid.server.model.RemoteHostAddress;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.store.StoreException;
+import org.apache.qpid.server.transport.AggregateTicker;
+import org.apache.qpid.server.transport.ProtocolEngine;
+import org.apache.qpid.server.transport.SchedulableConnection;
+import org.apache.qpid.server.transport.ServerIdleReadTimeoutTicker;
+import org.apache.qpid.server.transport.ServerIdleWriteTimeoutTicker;
+import org.apache.qpid.server.util.Action;
+import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
+
+
+class OutboundConnection_0_8 implements OutboundProtocolEngine, ClientMethodProcessor<ClientChannelMethodProcessor>
+{
+
+ private static final Map<Protocol, ProtocolVersion> PROTOCOL_VERSION_MAP;
+
+ static
+ {
+ Map<Protocol, ProtocolVersion> protocolVersionMap = new HashMap<>();
+ protocolVersionMap.put(Protocol.AMQP_0_8, ProtocolVersion.v0_8);
+ protocolVersionMap.put(Protocol.AMQP_0_9, ProtocolVersion.v0_9);
+ protocolVersionMap.put(Protocol.AMQP_0_9_1, ProtocolVersion.v0_91);
+
+ PROTOCOL_VERSION_MAP = Collections.unmodifiableMap(protocolVersionMap);
+ }
+
+ private static final int TRANSFER_SESSION_ID = 0;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(OutboundConnection_0_8.class);
+
+ private final Protocol _protocol;
+ private final RemoteHost<?> _remoteHost;
+ private final RemoteHostAddress<?> _address;
+ private final VirtualHost<?> _virtualHost;
+
+ private final FederationDecoder _decoder;
+
+
+ private final AggregateTicker _aggregateTicker;
+ private final ProtocolVersion _protocolVersion;
+
+ private final MethodRegistry _methodRegistry;
+ private volatile long _lastReadTime;
+ private volatile long _lastWriteTime;
+ private SchedulableConnection _connection;
+ private volatile AccessControlContext _accessControllerContext;
+
+
+
+ private final AtomicBoolean _stateChanged = new AtomicBoolean();
+ private final AtomicReference<Action<ProtocolEngine>> _workListener = new AtomicReference<>();
+ private volatile Thread _ioThread;
+ private final List<Runnable> _pendingTasks = new CopyOnWriteArrayList<>();
+ private int _classId;
+ private int _methodId;
+ private SaslClient _saslClient;
+ private int _maxFrameSize;
+ private int _maxNoOfChannels;
+
+ private static final OutboundChannel[] _channels = new OutboundChannel[3];
+ private Action<Boolean> _onClosedTask;
+
+ enum State
+ {
+ INIT,
+ AWAIT_START,
+ AWAIT_SECURE,
+ AWAIT_TUNE,
+ AWAIT_OPEN_OK,
+ OPEN,
+ AWAIT_CLOSE_OK,
+ CLOSED
+ }
+
+ private State _state = State.INIT;
+
+
+ public OutboundConnection_0_8(final RemoteHostAddress<?> address,
+ final VirtualHost<?> virtualHost,
+ final Protocol protocol,
+ final byte[] protocolHeader)
+ {
+ _address = address;
+ _protocol = protocol;
+ _virtualHost = virtualHost;
+ _aggregateTicker = new AggregateTicker();
+ _remoteHost = address.getParent(RemoteHost.class);
+ _decoder = new FederationDecoder(this);
+ _protocolVersion = PROTOCOL_VERSION_MAP.get(protocol);
+ _methodRegistry = new MethodRegistry(_protocolVersion);
+
+ _pendingTasks.add(new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ changeState(State.INIT, State.AWAIT_START);
+ _connection.send(QpidByteBuffer.wrap(protocolHeader));
+ }
+ });
+ _stateChanged.set(true);
+ }
+
+
+ public VirtualHost<?> getVirtualHost()
+ {
+ return _virtualHost;
+ }
+
+
+ private synchronized void changeState(final State currentState, final State newState)
+ {
+ if(_state != currentState)
+ {
+ throw new ConnectionScopedRuntimeException("Incorrect state");
+ }
+ _state = newState;
+ }
+
+ private synchronized void assertState(final State currentState)
+ {
+ if (_state != currentState)
+ {
+ throw new ConnectionScopedRuntimeException("Incorrect state");
+ }
+ }
+
+ public Protocol getProtocol()
+ {
+ return _protocol;
+ }
+
+ @Override
+ public final AggregateTicker getAggregateTicker()
+ {
+ return _aggregateTicker;
+ }
+
+ public final Date getLastIoTime()
+ {
+ return new Date(Math.max(getLastReadTime(), getLastWriteTime()));
+ }
+
+ @Override
+ public final long getLastReadTime()
+ {
+ return _lastReadTime;
+ }
+
+ public final void updateLastReadTime()
+ {
+ _lastReadTime = System.currentTimeMillis();
+ }
+
+ @Override
+ public final long getLastWriteTime()
+ {
+ return _lastWriteTime;
+ }
+
+ public final void updateLastWriteTime()
+ {
+ _lastWriteTime = System.currentTimeMillis();
+ }
+
+
+ MethodRegistry getMethodRegistry()
+ {
+ return _methodRegistry;
+ }
+
+
+ @Override
+ public void closed()
+ {
+ Action<Boolean> task = _onClosedTask;
+ if(task != null)
+ {
+ task.performAction(_state == State.OPEN);
+ }
+ }
+
+ public synchronized void writerIdle()
+ {
+ writeFrame(HeartbeatBody.FRAME);
+ }
+
+ @Override
+ public void readerIdle()
+ {
+
+ }
+
+ @Override
+ public Subject getSubject()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isTransportBlockedForWriting()
+ {
+ return false;
+ }
+
+ @Override
+ public void setTransportBlockedForWriting(final boolean blocked)
+ {
+
+ }
+
+ @Override
+ public void setMessageAssignmentSuspended(final boolean value, final boolean notifyConsumers)
+ {
+
+ }
+
+ @Override
+ public boolean isMessageAssignmentSuspended()
+ {
+ return false;
+ }
+
+
+ @Override
+ public Iterator<Runnable> processPendingIterator()
+ {
+ if (!isIOThread())
+ {
+ return Collections.emptyIterator();
+ }
+ return new ProcessPendingIterator();
+ }
+
+ @Override
+ public boolean hasWork()
+ {
+ return _stateChanged.get();
+ }
+
+ @Override
+ public void notifyWork()
+ {
+ _stateChanged.set(true);
+
+ final Action<ProtocolEngine> listener = _workListener.get();
+ if(listener != null)
+ {
+
+ listener.performAction(this);
+ }
+ }
+
+ @Override
+ public void clearWork()
+ {
+ _stateChanged.set(false);
+ }
+
+ @Override
+ public void setWorkListener(final Action<ProtocolEngine> listener)
+ {
+ _workListener.set(listener);
+ }
+
+
+ @Override
+ public void encryptedTransport()
+ {
+
+ }
+
+ @Override
+ public void received(final QpidByteBuffer msg)
+ {
+ AccessController.doPrivileged(new PrivilegedAction<Void>()
+ {
+ @Override
+ public Void run()
+ {
+ updateLastReadTime();
+
+ try
+ {
+ _decoder.decodeBuffer(msg);
+ receivedComplete();
+ }
+ catch (AMQFrameDecodingException | IOException e)
+ {
+ LOGGER.error("Unexpected exception", e);
+ throw new ConnectionScopedRuntimeException(e);
+ }
+ catch (StoreException e)
+ {
+ if (_virtualHost.isActive())
+ {
+ throw new ServerScopedRuntimeException(e);
+ }
+ else
+ {
+ throw new ConnectionScopedRuntimeException(e);
+ }
+ }
+ return null;
+ }
+ }, getAccessControllerContext());
+
+
+ }
+
+ private void receivedComplete()
+ {
+ for(OutboundChannel channel : _channels)
+ {
+ if (channel != null)
+ {
+ channel.receivedComplete();
+ }
+ }
+ }
+
+
+ public AccessControlContext getAccessControllerContext()
+ {
+ return _accessControllerContext;
+ }
+
+ public final void updateAccessControllerContext()
+ {
+ _accessControllerContext = getAccessControlContextFromSubject(
+ getSubject());
+ }
+
+ public final AccessControlContext getAccessControlContextFromSubject(final Subject subject)
+ {
+ final AccessControlContext acc = AccessController.getContext();
+ return AccessController.doPrivileged(
+ new PrivilegedAction<AccessControlContext>()
+ {
+ public AccessControlContext run()
+ {
+ if (subject == null)
+ return new AccessControlContext(acc, null);
+ else
+ return new AccessControlContext
+ (acc,
+ new SubjectDomainCombiner(subject));
+ }
+ });
+ }
+
+
+ @Override
+ public void setIOThread(final Thread ioThread)
+ {
+ _ioThread = ioThread;
+ }
+
+ public boolean isIOThread()
+ {
+ return Thread.currentThread() == _ioThread;
+ }
+
+
+ @Override
+ public void setConnection(final SchedulableConnection connection)
+ {
+ _connection = connection;
+ }
+
+ @Override
+ public void setOnClosedTask(final Action<Boolean> onClosedTask)
+ {
+ _onClosedTask = onClosedTask;
+ }
+
+ @Override
+ public ProtocolVersion getProtocolVersion()
+ {
+ return _protocolVersion;
+ }
+
+ @Override
+ public ClientChannelMethodProcessor getChannelMethodProcessor(final int channelId)
+ {
+ return getChannel(channelId);
+ }
+
+
+ public OutboundChannel getChannel(final int channelId)
+ {
+ return channelId < _channels.length ? _channels[channelId] : null;
+ }
+
+ public void setMaxFrameSize(int frameMax)
+ {
+ _maxFrameSize = frameMax;
+ _decoder.setMaxFrameSize(frameMax);
+ }
+
+ public int getMaxFrameSize()
+ {
+ return _maxFrameSize;
+ }
+
+ @Override
+ public void receiveConnectionClose(final int replyCode,
+ final AMQShortString replyText,
+ final int classId,
+ final int methodId)
+ {
+
+ writeFrame(_methodRegistry.createConnectionCloseOkBody().generateFrame(0));
+ _connection.close();
+ }
+
+ @Override
+ public void receiveConnectionCloseOk()
+ {
+ // TODO
+ }
+
+ @Override
+ public void receiveHeartbeat()
+ {
+ }
+
+ @Override
+ public void receiveProtocolHeader(final ProtocolInitiation protocolInitiation)
+ {
+ _connection.close();
+ }
+
+ @Override
+ public void setCurrentMethod(final int classId, final int methodId)
+ {
+ _classId = classId;
+ _methodId = methodId;
+ }
+
+ void writeFrame(AMQDataBlock frame)
+ {
+ LOGGER.debug("SEND: {}", frame);
+
+
+ frame.writePayload(_connection);
+
+
+ updateLastWriteTime();
+
+ }
+
+
+ @Override
+ public boolean ignoreAllButCloseOk()
+ {
+ // TODO
+ return false;
+ }
+
+ @Override
+ public void receiveConnectionStart(final short versionMajor,
+ final short versionMinor,
+ final FieldTable serverProperties,
+ final byte[] mechanisms,
+ final byte[] locales)
+ {
+ changeState(State.AWAIT_START, State.AWAIT_SECURE);
+ List<String> saslMechanisms = Arrays.asList(new String(mechanisms, StandardCharsets.UTF_8).split(" "));
+ Map propMap = FieldTable.convertToMap(serverProperties);
+
+ Collection<Credential> credentialList = _remoteHost.getChildren(Credential.class);
+
+ SaslClient client = null;
+ for(Credential<?> credentials : credentialList)
+ {
+ client = credentials.getSaslClient(saslMechanisms);
+ if(client != null)
+ {
+ break;
+ }
+ }
+
+ if(client != null)
+ {
+ _saslClient = client;
+ try
+ {
+ byte[] initialResponse = client.hasInitialResponse() ? client.evaluateChallenge(new byte[0]) : new byte[0];
+
+ FieldTable clientProperties = FieldTableFactory.newFieldTable();
+ clientProperties.setString(ServerPropertyNames.PRODUCT,
+ CommonProperties.getProductName());
+ clientProperties.setString(ServerPropertyNames.VERSION,
+ CommonProperties.getReleaseVersion());
+ clientProperties.setString(ServerPropertyNames.QPID_BUILD,
+ CommonProperties.getBuildVersion());
+ clientProperties.setString(ServerPropertyNames.QPID_INSTANCE_NAME,
+ _virtualHost.getName());
+
+
+ writeFrame(_methodRegistry.createConnectionStartOkBody(clientProperties, AMQShortString.valueOf(_saslClient.getMechanismName()), initialResponse, null).generateFrame(0));
+ if(client.isComplete())
+ {
+ changeState(State.AWAIT_SECURE, State.AWAIT_TUNE);
+ }
+ }
+ catch (SaslException e)
+ {
+ throw new ConnectionScopedRuntimeException(e);
+ }
+ }
+ else
+ {
+ throw new ConnectionScopedRuntimeException("Unable to find acceptable sasl mechanism");
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionSecure(final byte[] challenge)
+ {
+ assertState(State.AWAIT_SECURE);
+ try
+ {
+ byte[] response = _saslClient.evaluateChallenge(challenge);
+
+ writeFrame(_methodRegistry.createConnectionSecureOkBody(response).generateFrame(0));
+ if(_saslClient.isComplete())
+ {
+ changeState(State.AWAIT_SECURE, State.AWAIT_TUNE);
+ }
+ }
+ catch (SaslException e)
+ {
+ throw new ConnectionScopedRuntimeException(e);
+ }
+ }
+
+ @Override
+ public void receiveConnectionRedirect(final AMQShortString host, final AMQShortString knownHosts)
+ {
+ LOGGER.info("Connection redirect to {} received, however redirection is not followed for federation links");
+ _connection.close();
+ }
+
+ private int getDefaultMaxFrameSize()
+ {
+ Broker<?> broker = _virtualHost.getBroker();
+
+ return broker.getNetworkBufferSize();
+ }
+
+ protected void initialiseHeartbeating(final long writerDelay, final long readerDelay)
+ {
+ if (writerDelay > 0)
+ {
+ _aggregateTicker.addTicker(new ServerIdleWriteTimeoutTicker(this, (int) writerDelay));
+ _connection.setMaxWriteIdleMillis(writerDelay);
+ }
+
+ if (readerDelay > 0)
+ {
+ _aggregateTicker.addTicker(new ServerIdleReadTimeoutTicker(_connection, this, (int) readerDelay));
+ _connection.setMaxReadIdleMillis(readerDelay);
+ }
+ }
+
+
+
+ public int getMaximumNumberOfChannels()
+ {
+ return _maxNoOfChannels;
+ }
+
+ private void setMaximumNumberOfChannels(int value)
+ {
+ _maxNoOfChannels = value;
+ }
+
+
+ @Override
+ public void receiveConnectionTune(final int channelMax, final long frameMax, final int heartbeat)
+ {
+ assertState(State.AWAIT_TUNE);
+
+ final int desiredHeartbeatInterval = _address.getDesiredHeartbeatInterval();
+ int heartbeatDelay = heartbeat == 0
+ ? desiredHeartbeatInterval
+ : (desiredHeartbeatInterval == 0) ? heartbeat : Math.min(heartbeat, desiredHeartbeatInterval);
+
+ long writerDelay = 1000L * heartbeatDelay;
+ long readerDelay = 1000L * BrokerProperties.HEARTBEAT_TIMEOUT_FACTOR * heartbeatDelay;
+ initialiseHeartbeating(writerDelay, readerDelay);
+
+ int maxFrameSize = getDefaultMaxFrameSize();
+ if (maxFrameSize <= 0)
+ {
+ maxFrameSize = Integer.MAX_VALUE;
+ }
+
+ if (frameMax > 0 && frameMax < maxFrameSize)
+ {
+ maxFrameSize = (int) frameMax;
+ }
+
+ setMaxFrameSize(maxFrameSize);
+
+ //0 means no implied limit, except that forced by protocol limitations (0xFFFF)
+ setMaximumNumberOfChannels( ((channelMax == 0l) || (channelMax > 0xFFFFL))
+ ? 0xFFFF
+ : (int)channelMax);
+
+
+
+ writeFrame(_methodRegistry.createConnectionTuneOkBody(_maxNoOfChannels, maxFrameSize, heartbeatDelay).generateFrame(0));
+ writeFrame(_methodRegistry.createConnectionOpenBody(AMQShortString.valueOf(_address.getHostName()), AMQShortString.EMPTY_STRING, false).generateFrame(0));
+
+ changeState(State.AWAIT_TUNE, State.AWAIT_OPEN_OK);
+
+
+ }
+
+ @Override
+ public void receiveConnectionOpenOk(final AMQShortString knownHosts)
+ {
+ changeState(State.AWAIT_OPEN_OK, State.OPEN);
+
+ createTransferSession();
+
+ }
+
+ private void createTransferSession()
+ {
+ _channels[TRANSFER_SESSION_ID] = new TransferSession_0_8(TRANSFER_SESSION_ID, this);
+ }
+
+
+ private class ProcessPendingIterator implements Iterator<Runnable>
+ {
+ private final List<OutboundChannel> _sessionsWithPending;
+ private Iterator<OutboundChannel> _sessionIterator;
+ private ProcessPendingIterator()
+ {
+ _sessionsWithPending = new ArrayList<>();
+ for(OutboundChannel channel : _channels)
+ {
+ if(channel != null)
+ {
+ _sessionsWithPending.add(channel);
+ }
+ }
+ _sessionIterator = _sessionsWithPending.iterator();
+ }
+
+ @Override
+ public boolean hasNext()
+ {
+ return !(_sessionsWithPending.isEmpty() && _pendingTasks.isEmpty());
+ }
+
+ @Override
+ public Runnable next()
+ {
+ if(!_sessionsWithPending.isEmpty())
+ {
+ if(!_sessionIterator.hasNext())
+ {
+ _sessionIterator = _sessionsWithPending.iterator();
+ }
+ final OutboundChannel session = _sessionIterator.next();
+ return new Runnable()
+ {
+ @Override
+ public void run()
+ {
+ if(!session.processPending())
+ {
+ _sessionIterator.remove();
+ }
+ }
+ };
+ }
+ else if(!_pendingTasks.isEmpty())
+ {
+ return _pendingTasks.remove(0);
+ }
+ else
+ {
+ throw new NoSuchElementException();
+ }
+ }
+
+ @Override
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_8.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_8.java
new file mode 100644
index 0000000..b8af4ff
--- /dev/null
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_8.java
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import org.apache.qpid.server.federation.OutboundProtocolEngine;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.RemoteHostAddress;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.plugin.OutboundProtocolEngineCreator;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class OutboundProtocolEngineCreator_0_8 implements OutboundProtocolEngineCreator
+{
+
+ private static final byte[] AMQP_0_8_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 1,
+ (byte) 1,
+ (byte) 8,
+ (byte) 0
+ };
+
+ public OutboundProtocolEngineCreator_0_8()
+ {
+ }
+
+ public Protocol getVersion()
+ {
+ return Protocol.AMQP_0_8;
+ }
+
+ @Override
+ public OutboundProtocolEngine newProtocolEngine(final RemoteHostAddress<?> address, final VirtualHost<?> virtualHost)
+ {
+ return new OutboundConnection_0_8(address, virtualHost, Protocol.AMQP_0_8, AMQP_0_8_HEADER);
+ }
+
+ @Override
+ public String getType()
+ {
+ return getVersion().toString();
+ }
+}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_9.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_9.java
new file mode 100644
index 0000000..2854a42
--- /dev/null
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_9.java
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import org.apache.qpid.server.federation.OutboundProtocolEngine;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.RemoteHostAddress;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.plugin.OutboundProtocolEngineCreator;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class OutboundProtocolEngineCreator_0_9 implements OutboundProtocolEngineCreator
+{
+
+ private static final byte[] AMQP_0_9_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 1,
+ (byte) 1,
+ (byte) 0,
+ (byte) 9
+ };
+
+ public OutboundProtocolEngineCreator_0_9()
+ {
+ }
+
+ public Protocol getVersion()
+ {
+ return Protocol.AMQP_0_9;
+ }
+
+ @Override
+ public OutboundProtocolEngine newProtocolEngine(final RemoteHostAddress<?> address, final VirtualHost<?> virtualHost)
+ {
+ return new OutboundConnection_0_8(address, virtualHost, Protocol.AMQP_0_9, AMQP_0_9_HEADER);
+ }
+
+ @Override
+ public String getType()
+ {
+ return getVersion().toString();
+ }
+}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_9_1.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_9_1.java
new file mode 100644
index 0000000..87f7cd0
--- /dev/null
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/OutboundProtocolEngineCreator_0_9_1.java
@@ -0,0 +1,65 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import org.apache.qpid.server.federation.OutboundProtocolEngine;
+import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.RemoteHostAddress;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.plugin.OutboundProtocolEngineCreator;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class OutboundProtocolEngineCreator_0_9_1 implements OutboundProtocolEngineCreator
+{
+
+ private static final byte[] AMQP_0_9_1_HEADER =
+ new byte[] { (byte) 'A',
+ (byte) 'M',
+ (byte) 'Q',
+ (byte) 'P',
+ (byte) 0,
+ (byte) 0,
+ (byte) 9,
+ (byte) 1
+ };
+
+ public OutboundProtocolEngineCreator_0_9_1()
+ {
+ }
+
+ public Protocol getVersion()
+ {
+ return Protocol.AMQP_0_9_1;
+ }
+
+ @Override
+ public OutboundProtocolEngine newProtocolEngine(final RemoteHostAddress<?> address, final VirtualHost<?> virtualHost)
+ {
+ return new OutboundConnection_0_8(address, virtualHost, Protocol.AMQP_0_9_1, AMQP_0_9_1_HEADER);
+ }
+
+ @Override
+ public String getType()
+ {
+ return getVersion().toString();
+ }
+}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/TransferSession_0_8.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/TransferSession_0_8.java
new file mode 100644
index 0000000..b5d86cc
--- /dev/null
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/TransferSession_0_8.java
@@ -0,0 +1,721 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import java.security.AccessControlContext;
+import java.util.Collection;
+import java.util.EnumMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.concurrent.TimeoutException;
+
+import com.google.common.util.concurrent.AbstractFuture;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.framing.AMQBody;
+import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.AMQMethodBody;
+import org.apache.qpid.framing.AMQShortString;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.BasicGetOkBody;
+import org.apache.qpid.framing.ConfirmSelectBody;
+import org.apache.qpid.framing.ConfirmSelectOkBody;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.MethodRegistry;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.plugin.MessageConverter;
+import org.apache.qpid.server.protocol.MessageConverterRegistry;
+import org.apache.qpid.server.protocol.v0_8.AMQMessage;
+import org.apache.qpid.server.protocol.v0_8.MessageContentSourceBody;
+import org.apache.qpid.server.transfer.TransferQueueConsumer;
+import org.apache.qpid.server.transfer.TransferQueueEntry;
+import org.apache.qpid.server.txn.LocalTransaction;
+import org.apache.qpid.server.txn.ServerTransaction;
+import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
+
+class TransferSession_0_8 implements OutboundChannel
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(TransferSession_0_8.class);
+ private static final Runnable NO_OP = new Runnable()
+ {
+ @Override
+ public void run()
+ {
+
+ }
+ };
+
+ private final OutboundConnection_0_8 _connection;
+ private final int _channelId;
+ private final MethodRegistry _methodRegistry;
+ private final LocalTransaction _txn;
+ private Collection<String> _remoteHostGlobalDomains;
+ private TransferTarget_0_8 _target;
+ private TransferQueueConsumer _consumer;
+ private final SortedMap<Long, TransferQueueEntry> _unconfirmed = new TreeMap<>();
+ private volatile boolean _flowControlled;
+ private volatile long _lastSent = -0L;
+
+ private int _maxUnconfirmed = 200;
+
+ enum Operation {
+ EXCHANGE_DECLARE,
+ EXCHANGE_DELETE,
+ EXCHANGE_BOUND,
+ QUEUE_BIND,
+ QUEUE_UNBIND,
+ QUEUE_DECLARE,
+ QUEUE_DELETE,
+ QUEUE_PURGE,
+ BASIC_RECOVER_SYNC,
+ BAISC_QOS,
+ BASIC_CONSUME,
+ BASIC_CANCEL,
+ TX_SELECT,
+ TX_COMMIT,
+ TX_ROLLBACK,
+ CHANNEL_FLOW,
+ CONFIRM_SELECT,
+ ACK,
+ BASIC_GET
+ }
+
+ private static final class TimedSettableFuture<V> extends AbstractFuture<V>
+ {
+ private final long _timeoutTime;
+
+ private TimedSettableFuture(final long timeoutTime)
+ {
+ _timeoutTime = timeoutTime;
+ }
+
+ public boolean set(V value)
+ {
+ return super.set(value);
+ }
+
+ @Override
+ public boolean setException(Throwable throwable)
+ {
+ return super.setException(throwable);
+ }
+
+ public long getTimeoutTime()
+ {
+ return _timeoutTime;
+ }
+
+ public boolean checkTimeout(long time)
+ {
+ if(time > _timeoutTime)
+ {
+ setException(new TimeoutException("Timed out waiting for response"));
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ private final Map<Operation, Queue<TimedSettableFuture<AMQMethodBody>>> _synchronousOperationListeners = new EnumMap<>(Operation.class);
+
+ {
+ for(Operation op : Operation.values())
+ {
+ _synchronousOperationListeners.put(op, new LinkedList<TimedSettableFuture<AMQMethodBody>>());
+ }
+ }
+
+ enum State { AWAITING_OPEN, OPEN, AWAITING_CLOSE_OK }
+
+ private State _state = State.AWAITING_OPEN;
+
+ private interface MessageHandler
+ {
+ void receiveMessageHeader(BasicContentHeaderProperties properties, long bodySize);
+
+ void receiveMessageContent(QpidByteBuffer data);
+ }
+
+
+ private final MessageHandler _unexpectedMessageHandler = new MessageHandler()
+ {
+ @Override
+ public void receiveMessageHeader(final BasicContentHeaderProperties properties, final long bodySize)
+ {
+ throw new ConnectionScopedRuntimeException("Unexpected frame");
+ }
+
+ @Override
+ public void receiveMessageContent(final QpidByteBuffer data)
+ {
+ throw new ConnectionScopedRuntimeException("Unexpected frame");
+ }
+ };
+
+ private volatile MessageHandler _messageHandler = _unexpectedMessageHandler;
+
+
+ TransferSession_0_8(final int channelId, final OutboundConnection_0_8 outboundConnection)
+ {
+ _connection = outboundConnection;
+ _channelId = channelId;
+ _methodRegistry = outboundConnection.getMethodRegistry();
+ writeMethod(_methodRegistry.createChannelOpenBody(AMQShortString.EMPTY_STRING));
+ _txn = new LocalTransaction(outboundConnection.getVirtualHost().getMessageStore());
+ }
+
+ private synchronized void changeState(final State currentState, final State newState)
+ {
+ if(_state != currentState)
+ {
+ throw new ConnectionScopedRuntimeException("Incorrect state");
+ }
+ _state = newState;
+ }
+
+ private synchronized void assertState(final State currentState)
+ {
+ if (_state != currentState)
+ {
+ throw new ConnectionScopedRuntimeException("Incorrect state");
+ }
+ }
+
+
+ @Override
+ public void receiveChannelOpenOk()
+ {
+ changeState(State.AWAITING_OPEN, State.OPEN);
+
+ writeMethod(new ConfirmSelectBody(true));
+
+ writeMethod(_methodRegistry.createBasicGetBody(0, AMQShortString.valueOf("$virtualhostProperties"), true));
+ final FutureCallback<AMQMethodBody> callback = new FutureCallback<AMQMethodBody>()
+ {
+ @Override
+ public void onSuccess(final AMQMethodBody result)
+ {
+ if (result instanceof BasicGetOkBody)
+ {
+ _messageHandler = new VirtualHostPropertiesHandler();
+ }
+ else
+ {
+ throw new ConnectionScopedRuntimeException("Unable to determine virtual host properties from remote host");
+ }
+ }
+
+ @Override
+ public void onFailure(final Throwable t)
+ {
+ if(t instanceof RuntimeException)
+ {
+ throw ((RuntimeException)t);
+ }
+ else
+ {
+ throw new ConnectionScopedRuntimeException(t);
+ }
+ }
+ };
+ addOperationResponse(Operation.BASIC_GET, callback);
+ }
+
+ private void addOperationResponse(Operation operation, FutureCallback<AMQMethodBody> callback)
+ {
+ final TimedSettableFuture<AMQMethodBody> future =
+ new TimedSettableFuture<>(System.currentTimeMillis() + 30000L);
+ Futures.addCallback(future, callback);
+ _synchronousOperationListeners.get(operation).add(future);
+ }
+
+ private void performOperationResponse(Operation operation, AMQMethodBody body)
+ {
+ final TimedSettableFuture<AMQMethodBody> future = _synchronousOperationListeners.get(operation).poll();
+
+ if(future == null)
+ {
+ throw new ConnectionScopedRuntimeException("Unexpected frame ");
+ }
+ else
+ {
+ future.set(body);
+ }
+ }
+
+
+ private void setRemoteHostGlobalDomains(final Collection<String> remoteHostGlobalDomains)
+ {
+ LOGGER.debug("Setting remote host global domains: {}", remoteHostGlobalDomains);
+ _remoteHostGlobalDomains = remoteHostGlobalDomains;
+
+ _target = new TransferTarget_0_8(this, remoteHostGlobalDomains);
+ _consumer = _connection.getVirtualHost().getTransferQueue().addConsumer(_target, "consumer");
+ }
+
+
+
+ @Override
+ public void receiveChannelAlert(final int replyCode, final AMQShortString replyText, final FieldTable details)
+ {
+
+ }
+
+ @Override
+ public void receiveAccessRequestOk(final int ticket)
+ {
+
+ }
+
+ @Override
+ public void receiveExchangeDeclareOk()
+ {
+ performOperationResponse(Operation.EXCHANGE_DECLARE, _methodRegistry.createExchangeDeclareOkBody());
+ }
+
+ @Override
+ public void receiveExchangeDeleteOk()
+ {
+ performOperationResponse(Operation.EXCHANGE_DELETE, _methodRegistry.createExchangeDeleteOkBody());
+ }
+
+ @Override
+ public void receiveExchangeBoundOk(final int replyCode, final AMQShortString replyText)
+ {
+ performOperationResponse(Operation.EXCHANGE_BOUND, _methodRegistry.createExchangeBoundOkBody(replyCode, replyText));
+ }
+
+ @Override
+ public void receiveQueueBindOk()
+ {
+ performOperationResponse(Operation.QUEUE_BIND, _methodRegistry.createQueueBindOkBody());
+ }
+
+ @Override
+ public void receiveQueueUnbindOk()
+ {
+ performOperationResponse(Operation.QUEUE_UNBIND, _methodRegistry.createQueueUnbindOkBody());
+ }
+
+ @Override
+ public void receiveQueueDeclareOk(final AMQShortString queue, final long messageCount, final long consumerCount)
+ {
+ performOperationResponse(Operation.QUEUE_DECLARE, _methodRegistry.createQueueDeclareOkBody(queue, messageCount, consumerCount));
+ }
+
+ @Override
+ public void receiveQueuePurgeOk(final long messageCount)
+ {
+ performOperationResponse(Operation.QUEUE_PURGE, _methodRegistry.createQueuePurgeOkBody(messageCount));
+
+ }
+
+ @Override
+ public void receiveQueueDeleteOk(final long messageCount)
+ {
+ performOperationResponse(Operation.QUEUE_DELETE, _methodRegistry.createQueueDeleteOkBody(messageCount));
+
+ }
+
+ @Override
+ public void receiveBasicRecoverSyncOk()
+ {
+ performOperationResponse(Operation.BASIC_RECOVER_SYNC, _methodRegistry.createBasicRecoverSyncOkBody());
+ }
+
+ @Override
+ public void receiveBasicQosOk()
+ {
+ performOperationResponse(Operation.BAISC_QOS, _methodRegistry.createBasicQosOkBody());
+ }
+
+ @Override
+ public void receiveBasicConsumeOk(final AMQShortString consumerTag)
+ {
+ performOperationResponse(Operation.BASIC_CONSUME, _methodRegistry.createBasicConsumeOkBody(consumerTag));
+ }
+
+ @Override
+ public void receiveBasicCancelOk(final AMQShortString consumerTag)
+ {
+ performOperationResponse(Operation.BASIC_CANCEL, _methodRegistry.createBasicCancelOkBody(consumerTag));
+ }
+
+ @Override
+ public void receiveBasicReturn(final int replyCode,
+ final AMQShortString replyText,
+ final AMQShortString exchange,
+ final AMQShortString routingKey)
+ {
+
+ }
+
+ @Override
+ public void receiveBasicDeliver(final AMQShortString consumerTag,
+ final long deliveryTag,
+ final boolean redelivered,
+ final AMQShortString exchange,
+ final AMQShortString routingKey)
+ {
+
+ }
+
+ @Override
+ public void receiveBasicGetOk(final long deliveryTag,
+ final boolean redelivered,
+ final AMQShortString exchange,
+ final AMQShortString routingKey,
+ final long messageCount)
+ {
+ performOperationResponse(Operation.BASIC_GET, _methodRegistry.createBasicGetOkBody(deliveryTag, redelivered, exchange, routingKey, messageCount));
+ }
+
+ @Override
+ public void receiveBasicGetEmpty()
+ {
+ performOperationResponse(Operation.BASIC_GET, _methodRegistry.createBasicGetEmptyBody(AMQShortString.EMPTY_STRING));
+ }
+
+ @Override
+ public void receiveTxSelectOk()
+ {
+ performOperationResponse(Operation.TX_SELECT, _methodRegistry.createTxSelectOkBody());
+ }
+
+ @Override
+ public void receiveTxCommitOk()
+ {
+ performOperationResponse(Operation.TX_COMMIT, _methodRegistry.createTxCommitOkBody());
+ }
+
+ @Override
+ public void receiveTxRollbackOk()
+ {
+ performOperationResponse(Operation.TX_ROLLBACK, _methodRegistry.createTxRollbackOkBody());
+ }
+
+ @Override
+ public void receiveConfirmSelectOk()
+ {
+ performOperationResponse(Operation.CONFIRM_SELECT, ConfirmSelectOkBody.INSTANCE);
+ }
+
+ @Override
+ public void receiveChannelFlow(final boolean active)
+ {
+ _flowControlled = !active;
+ writeMethod(_methodRegistry.createChannelFlowOkBody(active));
+
+ }
+
+ @Override
+ public void receiveChannelFlowOk(final boolean active)
+ {
+ performOperationResponse(Operation.CHANNEL_FLOW, _methodRegistry.createChannelFlowOkBody(active));
+ }
+
+ @Override
+ public void receiveChannelClose(final int replyCode,
+ final AMQShortString replyText,
+ final int classId,
+ final int methodId)
+ {
+
+ }
+
+ @Override
+ public void receiveChannelCloseOk()
+ {
+ }
+
+ @Override
+ public void receiveMessageContent(final QpidByteBuffer data)
+ {
+ _messageHandler.receiveMessageContent(data);
+ }
+
+ @Override
+ public void receiveMessageHeader(final BasicContentHeaderProperties properties, final long bodySize)
+ {
+ _messageHandler.receiveMessageHeader(properties, bodySize);
+ }
+
+ @Override
+ public boolean ignoreAllButCloseOk()
+ {
+ return false;
+ }
+
+ @Override
+ public void receiveBasicNack(final long deliveryTag, final boolean multiple, final boolean requeue)
+ {
+ if(multiple)
+ {
+ Iterator<Map.Entry<Long, TransferQueueEntry>> iter = _unconfirmed.entrySet().iterator();
+ while(iter.hasNext())
+ {
+ Map.Entry<Long, TransferQueueEntry> pair = iter.next();
+ if(pair.getKey() > deliveryTag)
+ {
+ break;
+ }
+ else
+ {
+ final TransferQueueEntry entry = pair.getValue();
+
+ if(requeue)
+ {
+ entry.release();
+ }
+ else
+ {
+ _txn.dequeue(entry.getEnqueueRecord(), new ServerTransaction.Action()
+ {
+ @Override
+ public void postCommit()
+ {
+ entry.delete();
+ }
+
+ @Override
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+
+ }
+ }
+ }
+ }
+ else
+ {
+ final TransferQueueEntry entry = _unconfirmed.remove(deliveryTag);
+ if(requeue)
+ {
+ entry.release();
+ }
+ else
+ {
+ _txn.dequeue(entry.getEnqueueRecord(), new ServerTransaction.Action()
+ {
+ @Override
+ public void postCommit()
+ {
+ entry.delete();
+ }
+
+ @Override
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void receiveBasicAck(final long deliveryTag, final boolean multiple)
+ {
+ if(multiple)
+ {
+ Iterator<Map.Entry<Long, TransferQueueEntry>> iter = _unconfirmed.entrySet().iterator();
+ while(iter.hasNext())
+ {
+ Map.Entry<Long, TransferQueueEntry> pair = iter.next();
+ if(pair.getKey() > deliveryTag)
+ {
+ break;
+ }
+ else
+ {
+ final TransferQueueEntry entry = pair.getValue();
+ _txn.dequeue(entry.getEnqueueRecord(), new ServerTransaction.Action()
+ {
+ @Override
+ public void postCommit()
+ {
+ entry.delete();
+ }
+
+ @Override
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+ }
+ }
+ }
+ else
+ {
+ final TransferQueueEntry entry = _unconfirmed.remove(deliveryTag);
+ _txn.dequeue(entry.getEnqueueRecord(), new ServerTransaction.Action()
+ {
+ @Override
+ public void postCommit()
+ {
+ entry.delete();
+ }
+
+ @Override
+ public void onRollback()
+ {
+ entry.release();
+ }
+ });
+
+ }
+ }
+
+ boolean isSuspended()
+ {
+ return _flowControlled || _unconfirmed.size() > _maxUnconfirmed;
+ }
+
+ @Override
+ public AccessControlContext getAccessControllerContext()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean processPending()
+ {
+ if(_consumer != null)
+ {
+ return _consumer.processPending();
+ }
+ return false;
+ }
+
+ void notifyWork()
+ {
+ _connection.notifyWork();
+ }
+
+ @Override
+ public void receivedComplete()
+ {
+ _txn.commitAsync(NO_OP);
+ }
+
+ void writeMethod(AMQMethodBody body)
+ {
+ writeFrame(body.generateFrame(_channelId));
+ }
+
+ void writeFrame(AMQFrame frame)
+ {
+ _connection.writeFrame(frame);
+ }
+
+
+ private class VirtualHostPropertiesHandler implements MessageHandler
+ {
+ private long _remaining;
+ private BasicContentHeaderProperties _properties;
+
+ @Override
+ public void receiveMessageHeader(final BasicContentHeaderProperties properties, final long bodySize)
+ {
+ _remaining = bodySize;
+ _properties = properties;
+ receiveVirtualHostProperties(_properties);
+ }
+
+ @Override
+ public void receiveMessageContent(final QpidByteBuffer data)
+ {
+ if((_remaining -= data.remaining()) == 0l)
+ {
+ _messageHandler = _unexpectedMessageHandler;
+ }
+ }
+ }
+
+ private void receiveVirtualHostProperties(final BasicContentHeaderProperties properties)
+ {
+ Collection<String> remoteHostGlobalDomains =
+ properties.getHeaders().getFieldArray("virtualhost.globalDomains");
+ setRemoteHostGlobalDomains(remoteHostGlobalDomains);
+ }
+
+
+ void transfer(final TransferQueueEntry entry)
+ {
+ ServerMessage message = entry.getMessage();
+ _unconfirmed.put(++_lastSent, entry);
+
+ writeMethod(_methodRegistry.createBasicPublishBody(0, "", message.getInitialRoutingAddress(), false, false));
+ if(!(message instanceof AMQMessage))
+ {
+ final MessageConverter converter =
+ MessageConverterRegistry.getConverter(message.getClass(), AMQMessage.class);
+ message = converter.convert(message, _connection.getVirtualHost());
+ }
+
+ AMQMessage amqMessage = (AMQMessage) message;
+ ContentHeaderBody contentHeaderBody = amqMessage.getContentHeaderBody();
+ writeHeader(contentHeaderBody);
+
+ int bodySize = (int) contentHeaderBody.getBodySize();
+
+ if (bodySize > 0)
+ {
+ int maxBodySize = (int) _connection.getMaxFrameSize() - AMQFrame.getFrameOverhead();
+
+ int writtenSize = 0;
+
+ while (writtenSize < bodySize)
+ {
+ int capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
+ AMQBody body = new MessageContentSourceBody(message, writtenSize, capacity);
+ writtenSize += capacity;
+
+ writeFrame(new AMQFrame(_channelId, body));
+ }
+ }
+
+ }
+
+
+
+
+
+ private void writeHeader(final ContentHeaderBody headerBody)
+ {
+ _connection.writeFrame(new AMQFrame(_channelId, headerBody));
+ }
+}
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/TransferTarget_0_8.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/TransferTarget_0_8.java
new file mode 100644
index 0000000..135714e
--- /dev/null
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/federation/TransferTarget_0_8.java
@@ -0,0 +1,77 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT 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.federation;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.transfer.TransferQueueEntry;
+import org.apache.qpid.server.transfer.TransferTarget;
+
+public class TransferTarget_0_8 implements TransferTarget
+{
+ private final TransferSession_0_8 _session;
+ private final Collection<String> _globalDomains;
+
+ public TransferTarget_0_8(final TransferSession_0_8 transferSession_0_8,
+ final Collection<String> remoteHostGlobalDomains)
+ {
+ _session = transferSession_0_8;
+ _globalDomains = remoteHostGlobalDomains;
+ }
+
+ @Override
+ public void notifyWork()
+ {
+ _session.notifyWork();
+ }
+
+ @Override
+ public Collection<String> getGlobalAddressDomains()
+ {
+ return Collections.unmodifiableCollection(_globalDomains);
+ }
+
+ @Override
+ public void send(final TransferQueueEntry entry)
+ {
+ _session.transfer(entry);
+ }
+
+ @Override
+ public void restoreCredit(final ServerMessage message)
+ {
+
+ }
+
+ @Override
+ public boolean wouldSuspend(final TransferQueueEntry entry)
+ {
+ return _session.isSuspended();
+ }
+
+ @Override
+ public boolean isSuspended()
+ {
+ return _session.isSuspended();
+ }
+}
diff --git a/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java b/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java
index 74dccd6..33018b8 100644
--- a/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java
+++ b/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java
@@ -20,23 +20,25 @@
*/
package org.apache.qpid.server.protocol.v0_8;
-import org.apache.qpid.QpidException;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.message.MessageInstance;
-import org.apache.qpid.server.message.ServerMessage;
-import org.apache.qpid.server.model.Queue;
-import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.test.utils.QpidTestCase;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import org.apache.qpid.QpidException;
+import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.test.utils.QpidTestCase;
/**
* QPID-1385 : Race condition between added to unacked map and resending due to a rollback.
@@ -62,7 +64,7 @@
private static final int INITIAL_MSG_COUNT = 10;
private Queue _queue;
private LinkedList<MessageInstance> _referenceList = new LinkedList<MessageInstance>();
- private ConsumerImpl _consumer;
+ private MessageInstanceConsumer _consumer;
private boolean _queueDeleted;
@Override
@@ -73,8 +75,8 @@
_queue = mock(Queue.class);
when(_queue.getName()).thenReturn(getName());
when(_queue.isDeleted()).thenReturn(_queueDeleted);
- _consumer = mock(ConsumerImpl.class);
- when(_consumer.getConsumerNumber()).thenReturn(ConsumerImpl.CONSUMER_NUMBER_GENERATOR.getAndIncrement());
+ _consumer = mock(MessageInstanceConsumer.class);
+ when(_consumer.getIdentifier()).thenReturn(Consumer.CONSUMER_NUMBER_GENERATOR.getAndIncrement());
long id = 0;
diff --git a/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapTest.java b/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapTest.java
index f70afd6..52a6225 100644
--- a/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapTest.java
+++ b/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapTest.java
@@ -25,13 +25,13 @@
import java.util.Collection;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.test.utils.QpidTestCase;
public class UnacknowledgedMessageMapTest extends QpidTestCase
{
- private final ConsumerImpl _consumer = mock(ConsumerImpl.class);
+ private final MessageInstanceConsumer _consumer = mock(MessageInstanceConsumer.class);
public void testDeletedMessagesCantBeAcknowledged()
{
diff --git a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
index 876f91a..2e9a24c 100644
--- a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
+++ b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
@@ -27,6 +27,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.protocol.v1_0.codec.ValueHandler;
import org.apache.qpid.server.protocol.v1_0.messaging.SectionEncoder;
import org.apache.qpid.server.protocol.v1_0.messaging.SectionEncoderImpl;
@@ -49,7 +50,6 @@
import org.apache.qpid.bytebuffer.QpidByteBuffer;
import org.apache.qpid.server.transport.ProtocolEngine;
import org.apache.qpid.server.consumer.AbstractConsumerTarget;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.message.MessageInstance;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.plugin.MessageConverter;
@@ -106,7 +106,7 @@
}
- public void doSend(final ConsumerImpl consumer, final MessageInstance entry, boolean batch)
+ public void doSend(final MessageInstanceConsumer consumer, final MessageInstance entry, boolean batch)
{
// TODO
ServerMessage serverMessage = entry.getMessage();
@@ -329,7 +329,7 @@
public void flush()
{
- for(ConsumerImpl consumer : getConsumers())
+ for(MessageInstanceConsumer consumer : getConsumers())
{
consumer.flush();
}
@@ -340,16 +340,16 @@
private final MessageInstance _queueEntry;
private final Binary _deliveryTag;
- private final ConsumerImpl _consumer;
+ private final MessageInstanceConsumer _consumer;
- public DispositionAction(Binary tag, MessageInstance queueEntry, final ConsumerImpl consumer)
+ public DispositionAction(Binary tag, MessageInstance queueEntry, final MessageInstanceConsumer consumer)
{
_deliveryTag = tag;
_queueEntry = queueEntry;
_consumer = consumer;
}
- public ConsumerImpl getConsumer()
+ public MessageInstanceConsumer getConsumer()
{
return _consumer;
}
@@ -522,7 +522,6 @@
return target instanceof org.apache.qpid.server.protocol.v1_0.type.messaging.Target ? ((org.apache.qpid.server.protocol.v1_0.type.messaging.Target) target).getAddress() : _link.getEndpoint().getName();
}
- @Override
public long getUnacknowledgedBytes()
{
// TODO
diff --git a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
index 40f95da..7145ca9 100644
--- a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
+++ b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java
@@ -35,6 +35,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.message.ConsumerOption;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.model.NamedAddressSpace;
import org.apache.qpid.server.protocol.v1_0.type.AmqpErrorException;
import org.apache.qpid.server.protocol.v1_0.type.Binary;
@@ -61,7 +64,6 @@
import org.apache.qpid.filter.SelectorParsingException;
import org.apache.qpid.filter.selector.ParseException;
import org.apache.qpid.filter.selector.TokenMgrError;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.filter.JMSSelectorFilter;
import org.apache.qpid.server.message.MessageInstance;
@@ -84,7 +86,7 @@
private NamedAddressSpace _addressSpace;
private SendingDestination _destination;
- private ConsumerImpl _consumer;
+ private MessageInstanceConsumer _consumer;
private ConsumerTarget_1_0 _target;
private boolean _draining;
@@ -114,7 +116,7 @@
linkAttachment.setDeliveryStateHandler(this);
QueueDestination qd = null;
- EnumSet<ConsumerImpl.Option> options = EnumSet.noneOf(ConsumerImpl.Option.class);
+ EnumSet<ConsumerOption> options = EnumSet.noneOf(ConsumerOption.class);
boolean noLocal = false;
@@ -170,8 +172,8 @@
_target = new ConsumerTarget_1_0(this, source.getDistributionMode() != StdDistMode.COPY);
if(source.getDistributionMode() != StdDistMode.COPY)
{
- options.add(ConsumerImpl.Option.ACQUIRES);
- options.add(ConsumerImpl.Option.SEES_REQUEUES);
+ options.add(ConsumerOption.ACQUIRES);
+ options.add(ConsumerOption.SEES_REQUEUES);
}
}
@@ -330,8 +332,8 @@
_target = new ConsumerTarget_1_0(this, true);
- options.add(ConsumerImpl.Option.ACQUIRES);
- options.add(ConsumerImpl.Option.SEES_REQUEUES);
+ options.add(ConsumerOption.ACQUIRES);
+ options.add(ConsumerOption.SEES_REQUEUES);
}
else
@@ -343,13 +345,13 @@
{
if(noLocal)
{
- options.add(ConsumerImpl.Option.NO_LOCAL);
+ options.add(ConsumerOption.NO_LOCAL);
}
if(_durability == TerminusDurability.CONFIGURATION ||
_durability == TerminusDurability.UNSETTLED_STATE )
{
- options.add(ConsumerImpl.Option.DURABLE);
+ options.add(ConsumerOption.DURABLE);
}
try
@@ -588,7 +590,7 @@
public synchronized void setLinkAttachment(SendingLinkAttachment linkAttachment)
{
- if(_consumer.isActive())
+ if(_target.getState() == ConsumerTarget.State.ACTIVE)
{
_target.suspend();
}
@@ -694,7 +696,7 @@
return _addressSpace;
}
- public ConsumerImpl getConsumer()
+ public MessageInstanceConsumer getConsumer()
{
return _consumer;
}
diff --git a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
index 744f009..40f22ec 100644
--- a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
+++ b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java
@@ -45,7 +45,24 @@
import org.slf4j.LoggerFactory;
import org.apache.qpid.bytebuffer.QpidByteBuffer;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.connection.SessionPrincipal;
+import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.message.MessageDestination;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
+import org.apache.qpid.server.message.MessageSource;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Consumer;
+import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.NamedAddressSpace;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.protocol.ConsumerListener;
+import org.apache.qpid.server.protocol.LinkRegistry;
import org.apache.qpid.server.protocol.v1_0.framing.OversizeFrameException;
import org.apache.qpid.server.protocol.v1_0.type.AmqpErrorException;
import org.apache.qpid.server.protocol.v1_0.type.Binary;
@@ -75,22 +92,6 @@
import org.apache.qpid.server.protocol.v1_0.type.transport.LinkError;
import org.apache.qpid.server.protocol.v1_0.type.transport.Role;
import org.apache.qpid.server.protocol.v1_0.type.transport.Transfer;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.connection.SessionPrincipal;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.consumer.ConsumerTarget;
-import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.message.MessageDestination;
-import org.apache.qpid.server.message.MessageSource;
-import org.apache.qpid.server.model.ConfigurationChangeListener;
-import org.apache.qpid.server.model.ConfiguredObject;
-import org.apache.qpid.server.model.Consumer;
-import org.apache.qpid.server.model.Exchange;
-import org.apache.qpid.server.model.Queue;
-import org.apache.qpid.server.model.Session;
-import org.apache.qpid.server.protocol.AMQSessionModel;
-import org.apache.qpid.server.protocol.ConsumerListener;
-import org.apache.qpid.server.protocol.LinkRegistry;
import org.apache.qpid.server.security.SecurityToken;
import org.apache.qpid.server.transport.AMQPConnection;
import org.apache.qpid.server.txn.AutoCommitTransaction;
@@ -1042,7 +1043,7 @@
private void registerConsumer(final SendingLink_1_0 link)
{
- ConsumerImpl consumer = link.getConsumer();
+ MessageInstanceConsumer consumer = link.getConsumer();
if(consumer instanceof Consumer<?>)
{
Consumer<?> modelConsumer = (Consumer<?>) consumer;
@@ -1628,7 +1629,7 @@
}
}
- private class ConsumerClosedListener implements ConfigurationChangeListener
+ private class ConsumerClosedListener extends AbstractConfigurationChangeListener
{
@Override
public void stateChanged(final ConfiguredObject object, final org.apache.qpid.server.model.State oldState, final org.apache.qpid.server.model.State newState)
@@ -1638,39 +1639,6 @@
consumerRemoved((Consumer<?>)object);
}
}
-
- @Override
- public void childAdded(final ConfiguredObject object, final ConfiguredObject child)
- {
-
- }
-
- @Override
- public void childRemoved(final ConfiguredObject object, final ConfiguredObject child)
- {
-
- }
-
- @Override
- public void attributeSet(final ConfiguredObject object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
-
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
}
@Override
diff --git a/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractLogger.java b/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractLogger.java
index 35ad562..bfac0d6 100644
--- a/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractLogger.java
+++ b/broker-plugins/logging-logback/src/main/java/org/apache/qpid/server/logging/logback/AbstractLogger.java
@@ -36,9 +36,9 @@
import org.slf4j.LoggerFactory;
import org.apache.qpid.server.logging.LogInclusionRule;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.BrokerLogInclusionRule;
-import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;
import org.apache.qpid.server.model.ManagedObject;
@@ -149,7 +149,7 @@
}
}
- private class LogInclusionRuleListener implements ConfigurationChangeListener
+ private class LogInclusionRuleListener extends AbstractConfigurationChangeListener
{
@Override
@@ -170,28 +170,6 @@
}
}
- @Override
- public void stateChanged(final ConfiguredObject<?> object, final State oldState, final State newState)
- {
- }
-
- @Override
- public void attributeSet(final ConfiguredObject<?> object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
- }
}
public static Map<String, Collection<String>> getSupportedVirtualHostLoggerChildTypes()
diff --git a/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementAddressSpace.java b/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementAddressSpace.java
index ee633f6..7ee2200 100644
--- a/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementAddressSpace.java
+++ b/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementAddressSpace.java
@@ -29,9 +29,9 @@
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.server.message.BaseMessageInstance;
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.model.Broker;
@@ -237,7 +237,7 @@
final String routingAddress,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final Action<? super MessageInstance> postEnqueueAction)
+ final Action<? super BaseMessageInstance> postEnqueueAction)
{
MessageDestination destination = getAttainedMessageDestination(routingAddress);
if(destination == null || destination == this)
diff --git a/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java b/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java
index 243da37..b1e2650 100644
--- a/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java
+++ b/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNode.java
@@ -41,19 +41,22 @@
import javax.security.auth.Subject;
import org.apache.qpid.server.connection.SessionPrincipal;
-import org.apache.qpid.server.consumer.ConsumerImpl;
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.AcquiringMessageInstanceConsumer;
+import org.apache.qpid.server.message.BaseMessageInstance;
+import org.apache.qpid.server.message.ConsumerOption;
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.MessageInstanceConsumer;
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.ConfigurationChangeListener;
+import org.apache.qpid.server.model.AbstractConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.NamedAddressSpace;
@@ -71,7 +74,7 @@
import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.util.StateChangeListener;
-class ManagementNode implements MessageSource, MessageDestination
+class ManagementNode implements MessageSource<ManagementNodeConsumer>, MessageDestination
{
public static final String NAME_ATTRIBUTE = "name";
@@ -263,7 +266,7 @@
final String routingAddress,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final Action<? super MessageInstance> postEnqueueAction)
+ final Action<? super BaseMessageInstance> postEnqueueAction)
{
@SuppressWarnings("unchecked")
@@ -982,7 +985,7 @@
final FilterManager filters,
final Class<? extends ServerMessage> messageClass,
final String consumerName,
- final EnumSet<ConsumerImpl.Option> options,
+ final EnumSet<ConsumerOption> options,
final Integer priority)
{
@@ -1099,7 +1102,7 @@
}
@Override
- public ConsumerImpl getAcquiringConsumer()
+ public MessageInstanceConsumer getAcquiringConsumer()
{
return null;
}
@@ -1111,13 +1114,13 @@
}
@Override
- public boolean isAcquiredBy(final ConsumerImpl consumer)
+ public boolean isAcquiredBy(final MessageInstanceConsumer consumer)
{
return false;
}
@Override
- public boolean removeAcquisitionFromConsumer(final ConsumerImpl consumer)
+ public boolean removeAcquisitionFromConsumer(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -1135,7 +1138,7 @@
}
@Override
- public ConsumerImpl getDeliveredConsumer()
+ public AcquiringMessageInstanceConsumer<?,?> getDeliveredConsumer()
{
return null;
}
@@ -1147,7 +1150,7 @@
}
@Override
- public boolean isRejectedBy(final ConsumerImpl consumer)
+ public boolean isRejectedBy(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -1165,13 +1168,13 @@
}
@Override
- public boolean acquire(final ConsumerImpl sub)
+ public boolean acquire(final MessageInstanceConsumer sub)
{
return false;
}
@Override
- public boolean makeAcquisitionUnstealable(final ConsumerImpl consumer)
+ public boolean makeAcquisitionUnstealable(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -1189,7 +1192,7 @@
}
@Override
- public int routeToAlternate(final Action<? super MessageInstance> action,
+ public int routeToAlternate(final Action<? super BaseMessageInstance> action,
final ServerTransaction txn)
{
return 0;
@@ -1227,7 +1230,7 @@
}
@Override
- public void release(final ConsumerImpl release)
+ public void release(final MessageInstanceConsumer release)
{
}
@@ -1275,7 +1278,7 @@
}
}
- private class ModelObjectListener implements ConfigurationChangeListener
+ private class ModelObjectListener extends AbstractConfigurationChangeListener
{
@Override
public void stateChanged(final ConfiguredObject object, final State oldState, final State newState)
@@ -1328,27 +1331,6 @@
_entities.get(entityType).remove(child.getName());
}
}
-
- @Override
- public void attributeSet(final ConfiguredObject object,
- final String attributeName,
- final Object oldAttributeValue,
- final Object newAttributeValue)
- {
-
- }
-
- @Override
- public void bulkChangeStart(final ConfiguredObject<?> object)
- {
-
- }
-
- @Override
- public void bulkChangeEnd(final ConfiguredObject<?> object)
- {
-
- }
}
private static class MutableMessageHeader implements AMQMessageHeader
diff --git a/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java b/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java
index 9890992..e46273d 100644
--- a/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java
+++ b/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementNodeConsumer.java
@@ -26,12 +26,11 @@
import java.util.List;
import java.util.Map;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.consumer.ConsumerTarget;
+import org.apache.qpid.server.message.BaseMessageInstance;
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.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.message.internal.InternalMessage;
import org.apache.qpid.server.model.NamedAddressSpace;
@@ -42,15 +41,14 @@
import org.apache.qpid.server.util.Action;
import org.apache.qpid.server.util.StateChangeListener;
-class ManagementNodeConsumer implements ConsumerImpl, MessageDestination
+class ManagementNodeConsumer implements MessageInstanceConsumer, MessageDestination
{
- private final long _id = ConsumerImpl.CONSUMER_NUMBER_GENERATOR.getAndIncrement();
private final ManagementNode _managementNode;
private final List<ManagementResponse> _queue = Collections.synchronizedList(new ArrayList<ManagementResponse>());
private final ConsumerTarget _target;
private final String _name;
private final StateChangeListener<ConsumerTarget, ConsumerTarget.State> _targetChangeListener = new TargetChangeListener();
-
+ private final Object _identifier = new Object();
public ManagementNodeConsumer(final String consumerName, final ManagementNode managementNode, ConsumerTarget target)
{
@@ -67,6 +65,11 @@
}
@Override
+ public Object getIdentifier()
+ {
+ return _identifier;
+ }
+
public boolean hasAvailableMessages()
{
return !_queue.isEmpty();
@@ -78,53 +81,12 @@
}
- @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 MessageSource getMessageSource()
- {
- return _managementNode;
- }
-
- @Override
- public long getConsumerNumber()
- {
- return _id;
- }
-
- @Override
- public boolean isSuspended()
- {
- return false;
- }
@Override
public boolean isClosed()
@@ -139,42 +101,11 @@
}
@Override
- public boolean seesRequeues()
- {
- return false;
- }
-
- @Override
public void close()
{
}
@Override
- public boolean trySendLock()
- {
- return _target.trySendLock();
- }
-
- @Override
- public void getSendLock()
- {
- _target.getSendLock();
- }
-
- @Override
- public void releaseSendLock()
- {
- _target.releaseSendLock();
- }
-
-
- @Override
- public boolean isActive()
- {
- return false;
- }
-
- @Override
public NamedAddressSpace getAddressSpace()
{
return _managementNode.getAddressSpace();
@@ -198,7 +129,7 @@
final String routingAddress,
final InstanceProperties instanceProperties,
final ServerTransaction txn,
- final Action<? super MessageInstance> postEnqueueAction)
+ final Action<? super BaseMessageInstance> postEnqueueAction)
{
send((InternalMessage)message);
return 1;
@@ -210,7 +141,6 @@
}
- @Override
public ConsumerTarget getTarget()
{
return _target;
diff --git a/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java b/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java
index 0b17b0f..71d0225 100644
--- a/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java
+++ b/broker-plugins/management-amqp/src/main/java/org/apache/qpid/server/management/amqp/ManagementResponse.java
@@ -20,10 +20,11 @@
*/
package org.apache.qpid.server.management.amqp;
-import org.apache.qpid.server.consumer.ConsumerImpl;
import org.apache.qpid.server.filter.Filterable;
+import org.apache.qpid.server.message.BaseMessageInstance;
import org.apache.qpid.server.message.InstanceProperties;
import org.apache.qpid.server.message.MessageInstance;
+import org.apache.qpid.server.message.MessageInstanceConsumer;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.message.internal.InternalMessage;
import org.apache.qpid.server.store.MessageEnqueueRecord;
@@ -85,7 +86,7 @@
}
@Override
- public ConsumerImpl getAcquiringConsumer()
+ public MessageInstanceConsumer getAcquiringConsumer()
{
return _consumer;
}
@@ -97,13 +98,13 @@
}
@Override
- public boolean isAcquiredBy(final ConsumerImpl consumer)
+ public boolean isAcquiredBy(final MessageInstanceConsumer consumer)
{
return consumer == _consumer && !isDeleted();
}
@Override
- public boolean removeAcquisitionFromConsumer(final ConsumerImpl consumer)
+ public boolean removeAcquisitionFromConsumer(final MessageInstanceConsumer consumer)
{
return consumer == _consumer;
}
@@ -133,7 +134,7 @@
}
@Override
- public boolean isRejectedBy(final ConsumerImpl consumer)
+ public boolean isRejectedBy(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -151,13 +152,13 @@
}
@Override
- public boolean acquire(final ConsumerImpl sub)
+ public boolean acquire(final MessageInstanceConsumer sub)
{
return false;
}
@Override
- public boolean makeAcquisitionUnstealable(final ConsumerImpl consumer)
+ public boolean makeAcquisitionUnstealable(final MessageInstanceConsumer consumer)
{
return false;
}
@@ -175,7 +176,7 @@
}
@Override
- public int routeToAlternate(final Action<? super MessageInstance> action,
+ public int routeToAlternate(final Action<? super BaseMessageInstance> action,
final ServerTransaction txn)
{
return 0;
@@ -213,7 +214,7 @@
}
@Override
- public void release(final ConsumerImpl release)
+ public void release(final MessageInstanceConsumer release)
{
release();
}
diff --git a/client/src/main/java/org/apache/qpid/client/url/URLParser.java b/client/src/main/java/org/apache/qpid/client/url/URLParser.java
index 7791f32..2fe7216 100644
--- a/client/src/main/java/org/apache/qpid/client/url/URLParser.java
+++ b/client/src/main/java/org/apache/qpid/client/url/URLParser.java
@@ -21,16 +21,19 @@
package org.apache.qpid.client.url;
-import org.apache.qpid.client.BrokerDetails;
-import org.apache.qpid.client.AMQConnectionFactory;
-import org.apache.qpid.client.AMQConnectionURL;
-import org.apache.qpid.url.URLHelper;
-import org.apache.qpid.url.URLSyntaxException;
-
+import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
import java.util.StringTokenizer;
+import org.apache.qpid.client.AMQConnectionFactory;
+import org.apache.qpid.client.AMQConnectionURL;
+import org.apache.qpid.client.BrokerDetails;
+import org.apache.qpid.url.URLHelper;
+import org.apache.qpid.url.URLSyntaxException;
+
public class URLParser
{
private AMQConnectionURL _url;
@@ -82,12 +85,12 @@
_url.setClientName(connection.getHost());
}
- String userInfo = connection.getUserInfo();
+ String userInfo = connection.getRawUserInfo();
if (userInfo == null)
{
- // Fix for Java 1.5 which doesn't parse UserInfo for non http URIs
- userInfo = connection.getAuthority();
+ // Fix for Java Environments which don't parse UserInfo for non http URIs
+ userInfo = connection.getRawAuthority();
if (userInfo != null)
{
@@ -178,8 +181,16 @@
}
else
{
- _url.setUsername(userinfo.substring(0, colonIndex));
- _url.setPassword(userinfo.substring(colonIndex + 1));
+ try
+ {
+ _url.setUsername(URLDecoder.decode(userinfo.substring(0, colonIndex), StandardCharsets.UTF_8.name()));
+ _url.setPassword(URLDecoder.decode(userinfo.substring(colonIndex + 1), StandardCharsets.UTF_8.name()));
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw URLHelper.parseError(AMQConnectionURL.AMQ_PROTOCOL.length() + 3, userinfo.length(),
+ e.getLocalizedMessage(), _url.getURL());
+ }
}
}
diff --git a/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java b/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
index c31eb4d..8bafa85 100644
--- a/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
+++ b/client/src/test/java/org/apache/qpid/test/unit/client/connectionurl/ConnectionURLTest.java
@@ -34,6 +34,26 @@
public class ConnectionURLTest extends QpidTestCase
{
+
+ public void testPasswordWithColon() throws URLSyntaxException
+ {
+ String url = "amqp://PQ-RST-UV-W:VPN%3amwrst@/test?brokerlist='tcp://localhost:5672'";
+ ConnectionURL connectionurl = new AMQConnectionURL(url);
+ assertEquals("PQ-RST-UV-W", connectionurl.getUsername());
+ assertEquals("VPN:mwrst", connectionurl.getPassword());
+ assertEquals("/test",connectionurl.getVirtualHost());
+ }
+
+ public void testUsernameWithColon() throws URLSyntaxException
+ {
+ String url = "amqp://PQ%3aRST-UV-W:VPN%3amwrst@/test?brokerlist='tcp://localhost:5672'";
+ ConnectionURL connectionurl = new AMQConnectionURL(url);
+ assertEquals("PQ:RST-UV-W", connectionurl.getUsername());
+ assertEquals("VPN:mwrst", connectionurl.getPassword());
+ assertEquals("/test",connectionurl.getVirtualHost());
+ }
+
+
public void testFailoverURL() throws URLSyntaxException
{
String url = "amqp://ritchiem:bob@/test?brokerlist='tcp://localhost:5672;tcp://fancyserver:3000/',failover='roundrobin?cyclecount='100''";
diff --git a/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/common/src/main/java/org/apache/qpid/framing/FieldTable.java
index a15ef99..ff3cf90 100644
--- a/common/src/main/java/org/apache/qpid/framing/FieldTable.java
+++ b/common/src/main/java/org/apache/qpid/framing/FieldTable.java
@@ -414,6 +414,28 @@
}
}
+ public FieldArray getFieldArray(String string)
+ {
+ return getFieldArray(AMQShortString.valueOf(string));
+ }
+
+ public FieldArray getFieldArray(AMQShortString string)
+ {
+ AMQTypedValue value = getProperty(string);
+
+ if ((value != null) && (value.getType() == AMQType.FIELD_ARRAY))
+ {
+ return (FieldArray) value.getValue();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
+
+
public Object getObject(String string)
{
return getObject(AMQShortString.valueOf(string));
diff --git a/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java b/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
index cb985f5..cfefe59 100644
--- a/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
+++ b/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
@@ -95,4 +95,10 @@
}
processor.receiveHeartbeat();
}
+
+ @Override
+ public String toString()
+ {
+ return "[HeartbeatBody]";
+ }
}