summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2014-10-10 09:59:55 +0000
committerRobert Godfrey <rgodfrey@apache.org>2014-10-10 09:59:55 +0000
commit50512c42bacc8f76d297ab407b6b1b74d92bae91 (patch)
treef392dddc39073700f9c6cc146025f3dc0dd259de
parent89b0cfc3fd36bd8679c3f9343289c3dd98f5394f (diff)
downloadqpid-python-50512c42bacc8f76d297ab407b6b1b74d92bae91.tar.gz
Merge from trunk
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-6125-ProtocolRefactoring@1630749 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java3
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java6
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java14
-rw-r--r--java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java246
-rw-r--r--java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js1
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java235
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java106
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java3
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java5
-rw-r--r--java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java92
-rw-r--r--java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java5
-rw-r--r--java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java4
-rw-r--r--java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java9
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/Broker.java5
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java22
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java18
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java232
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java10
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java26
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java5
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java2
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java22
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java97
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java102
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java5
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java13
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java14
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java4
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java25
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java50
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java19
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java144
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java2
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java19
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java69
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java53
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java30
-rw-r--r--java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java47
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/binding/BindingImplTest.java76
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java2
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java4
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java187
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java14
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImplTest.java117
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java54
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java105
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java123
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java256
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java58
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java36
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/TestLdapDirectoryContext.java38
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java61
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java4
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java247
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java192
-rw-r--r--java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java6
-rw-r--r--java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java31
-rw-r--r--java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java80
-rw-r--r--java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java6
-rw-r--r--java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ChannelMethodProcessor.java25
-rw-r--r--java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java4503
-rw-r--r--java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodProcessor.java957
-rw-r--r--java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java6
-rw-r--r--java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java6
-rw-r--r--java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java2
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/addQueue.html162
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/css/common.css3
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/editQueue.html300
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js38
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js9
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js73
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js29
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editQueue.js232
-rw-r--r--java/broker-plugins/management-http/src/main/java/resources/showQueue.html3
-rw-r--r--java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java47
-rw-r--r--java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java6
-rw-r--r--java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1040-QueueTypes.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef2
-rw-r--r--java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef2
-rw-r--r--java/perftests/etc/testdefs/Latency-MessageSize.json4
-rw-r--r--java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json66
-rw-r--r--java/perftests/etc/testdefs/MessageSize.json4
-rw-r--r--java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js6
-rw-r--r--java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js5
-rw-r--r--java/perftests/pom.xml42
-rw-r--r--java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java49
-rw-r--r--java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java7
-rw-r--r--java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java6
110 files changed, 7121 insertions, 2980 deletions
diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
index 45e0c39274..76e4415d7c 100644
--- a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
+++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java
@@ -27,6 +27,7 @@ import org.apache.qpid.server.jmx.MBeanProvider;
import org.apache.qpid.server.jmx.ManagedObject;
import org.apache.qpid.server.jmx.ManagedObjectRegistry;
import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade;
import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode;
@@ -46,7 +47,7 @@ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider
@Override
public boolean isChildManageableByMBean(ConfiguredObject child)
{
- return child instanceof BDBHAVirtualHostNode;
+ return child instanceof BDBHAVirtualHostNode && ((BDBHAVirtualHostNode)child).getState() != State.ERRORED;
}
@Override
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
index 0fc44605fe..5d65d6e16d 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBSystemConfigImpl.java
@@ -26,6 +26,7 @@ import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.model.AbstractSystemConfig;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.SystemConfigFactoryConstructor;
@@ -48,9 +49,10 @@ public class BDBSystemConfigImpl extends AbstractSystemConfig<BDBSystemConfigImp
public BDBSystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions)
+ final BrokerOptions brokerOptions,
+ final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+ super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
}
@Override
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
index 20dbdc703a..532cffdac8 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java
@@ -1253,7 +1253,7 @@ public class ReplicatedEnvironmentFacade implements EnvironmentFacade, StateChan
{
if (LOGGER.isDebugEnabled())
{
- LOGGER.debug("Setting permitted nodes to " + permittedNodes);
+ LOGGER.debug(_prettyGroupNodeName + " permitted nodes set to " + permittedNodes);
}
_permittedNodes.clear();
@@ -1263,12 +1263,18 @@ public class ReplicatedEnvironmentFacade implements EnvironmentFacade, StateChan
registerAppStateMonitorIfPermittedNodesSpecified();
ReplicationGroupListener listener = _replicationGroupListener.get();
+ int count = 0;
for(ReplicationNode node: _remoteReplicationNodes.values())
{
if (!isNodePermitted(node))
{
onIntruder(listener, node);
}
+ count++;
+ }
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug(_prettyGroupNodeName + " checked " + count + " node(s)");
}
}
}
@@ -1329,7 +1335,7 @@ public class ReplicatedEnvironmentFacade implements EnvironmentFacade, StateChan
}
catch (IOException e)
{
- throw new IllegalConfigurationException(String.format("Cannot connect to '%s'", helperHostPort), e);
+ throw new IllegalConfigurationException(String.format("Cannot connect to existing node '%s' at '%s'", helperNodeName, helperHostPort), e);
}
catch (ServiceConnectFailedException e)
{
@@ -1337,8 +1343,8 @@ public class ReplicatedEnvironmentFacade implements EnvironmentFacade, StateChan
}
catch (Exception e)
{
- throw new RuntimeException(String.format("Unexpected exception on attempt to retrieve state from '%s' at '%s'",
- helperNodeName, helperHostPort), e);
+ throw new RuntimeException(String.format("Cannot retrieve state for node '%s' (%s) from group '%s'",
+ helperNodeName, helperHostPort, groupName), e);
}
if (LOGGER.isDebugEnabled())
diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
index e6109954c0..0003e74dbc 100644
--- a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
+++ b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
@@ -20,7 +20,11 @@
*/
package org.apache.qpid.server.virtualhostnode.berkeleydb;
+import java.io.File;
import java.net.InetSocketAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.ArrayList;
@@ -74,6 +78,7 @@ import org.apache.qpid.server.store.berkeleydb.BDBConfigurationStore;
import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade;
import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory;
import org.apache.qpid.server.store.berkeleydb.replication.ReplicationGroupListener;
+import org.apache.qpid.server.util.PortUtil;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl;
import org.apache.qpid.server.virtualhostnode.AbstractVirtualHostNode;
@@ -255,7 +260,7 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
public String toString()
{
return "BDBHAVirtualHostNodeImpl [id=" + getId() + ", name=" + getName() + ", storePath=" + _storePath + ", groupName=" + _groupName + ", address=" + _address
- + ", state=" + getState() + ", priority=" + _priority + ", designatedPrimary=" + _designatedPrimary + ", quorumOverride=" + _quorumOverride + "]";
+ + ", state=" + getState() + ", priority=" + _priority + ", designatedPrimary=" + _designatedPrimary + ", quorumOverride=" + _quorumOverride + ", role=" + getRole() + "]";
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@@ -282,22 +287,18 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
super.onCreate();
if (!isFirstNodeInAGroup())
{
- try
- {
- int dbPingSocketTimeout = getContextKeys(false).contains("qpid.bdb.ha.db_ping_socket_timeout") ? getContextValue(Integer.class, "qpid.bdb.ha.db_ping_socket_timeout") : 10000 /* JE's own default */;
- Collection<String> permittedNodes = ReplicatedEnvironmentFacade.connectToHelperNodeAndCheckPermittedHosts(getName(), getAddress(), getGroupName(), getHelperNodeName(), getHelperAddress(), dbPingSocketTimeout);
- setAttribute(PERMITTED_NODES, null, new ArrayList<String>(permittedNodes));
- }
- catch(IllegalConfigurationException e)
- {
- deleted();
- throw e;
- }
+ _permittedNodes = new ArrayList<>(getPermittedNodesFromHelper());
}
-
getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.CREATED());
}
+ @Override
+ public void onOpen()
+ {
+ validatePermittedNodesFormat(_permittedNodes);
+ super.onOpen();
+ }
+
protected ReplicatedEnvironmentFacade getReplicatedEnvironmentFacade()
{
return _environmentFacade.get();
@@ -334,6 +335,24 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
throw new IllegalStateException("Environment facade is not created");
}
+ try
+ {
+ Set<ReplicationNode> remoteNodes = environmentFacade.getEnvironment().getGroup().getNodes();
+ for (ReplicationNode node : remoteNodes)
+ {
+ String nodeAddress = node.getHostName() + ":" + node.getPort();
+ if (!_permittedNodes.contains(nodeAddress))
+ {
+ shutdownOnIntruder(nodeAddress);
+ throw new IllegalStateException("Intruder node detected: " + nodeAddress);
+ }
+ }
+ }
+ catch (DatabaseException dbe)
+ {
+ environmentFacade.handleDatabaseException("DB exception while checking for intruder node", dbe);
+ }
+
if (_environmentFacade.compareAndSet(null, environmentFacade))
{
environmentFacade.setStateChangeListener(new EnvironmentStateChangeListener());
@@ -372,9 +391,15 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
@StateTransition( currentState = { State.ACTIVE, State.STOPPED, State.ERRORED}, desiredState = State.DELETED )
protected void doDelete()
{
+ // get helpers before close. on close all children are closed and not available anymore
Set<InetSocketAddress> helpers = getRemoteNodeAddresses();
super.doDelete();
- getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED());
+
+ if (getConfigurationStore() != null)
+ {
+ getEventLogger().message(getVirtualHostNodeLogSubject(), HighAvailabilityMessages.DELETED());
+ }
+
if (getState() == State.DELETED && !helpers.isEmpty())
{
try
@@ -432,20 +457,87 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
}
@Override
- public void onValidate()
+ protected void postResolve()
{
- super.onValidate();
+ super.postResolve();
_virtualHostNodeLogSubject = new BDBHAVirtualHostNodeLogSubject(getGroupName(), getName());
_groupLogSubject = new GroupLogSubject(getGroupName());
_virtualHostNodePrincipalName = MessageFormat.format(VIRTUAL_HOST_PRINCIPAL_NAME_FORMAT, getGroupName(), getName());
}
@Override
- public void onOpen()
+ public void validateOnCreate()
{
- super.onOpen();
+ super.validateOnCreate();
+
+ validateAddress();
- validatePermittedNodes(_permittedNodes);
+ validateStorePath();
+
+ if (!isFirstNodeInAGroup())
+ {
+ getPermittedNodesFromHelper();
+ }
+ }
+
+ private Collection<String> getPermittedNodesFromHelper()
+ {
+ int dbPingSocketTimeout = getContextKeys(false).contains("qpid.bdb.ha.db_ping_socket_timeout") ? getContextValue(Integer.class, "qpid.bdb.ha.db_ping_socket_timeout") : 10000 /* JE's own default */;
+ return ReplicatedEnvironmentFacade.connectToHelperNodeAndCheckPermittedHosts(getName(), getAddress(), getGroupName(), getHelperNodeName(), getHelperAddress(), dbPingSocketTimeout);
+ }
+
+ private void validateStorePath()
+ {
+ File storePath = new File(getStorePath());
+ while (!storePath.exists())
+ {
+ storePath = storePath.getParentFile();
+ if (storePath == null)
+ {
+ throw new IllegalConfigurationException(String.format("Store path '%s' is invalid", getStorePath()));
+ }
+ }
+
+ if (!storePath.isDirectory())
+ {
+ throw new IllegalConfigurationException(String.format("Store path '%s' is not a folder", getStorePath()));
+ }
+
+ if (!Files.isWritable(storePath.toPath()))
+ {
+ throw new IllegalConfigurationException(String.format("Store path '%s' is not writable", getStorePath()));
+ }
+ }
+
+ private void validateAddress()
+ {
+ String address = getAddress();
+
+ URI uri = addressToURI(address);
+
+ if (!PortUtil.isPortAvailable(uri.getHost(), uri.getPort()))
+ {
+ throw new IllegalConfigurationException(String.format("Cannot bind to address '%s'. Address is already in use.", address));
+ }
+ }
+
+ private URI addressToURI(String address)
+ {
+ if (address == null || "".equals(address))
+ {
+ throw new IllegalConfigurationException("Node address is not set");
+ }
+
+ URI uri = null;
+ try
+ {
+ uri = new URI( "tcp://" + address);
+ }
+ catch (URISyntaxException e)
+ {
+ throw new IllegalConfigurationException(String.format("Invalid address specified '%s'. ", address));
+ }
+ return uri;
}
private void onMaster()
@@ -538,7 +630,7 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
private void onDetached()
{
- createReplicaVirtualHost();
+ closeVirtualHostIfExist();
}
private void createReplicaVirtualHost()
@@ -578,7 +670,7 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
if (LOGGER.isInfoEnabled())
{
- LOGGER.info("Received BDB event indicating transition to state " + state);
+ LOGGER.info("Received BDB event indicating transition to state " + state + " for " + getName());
}
NodeRole previousRole = getRole();
try
@@ -728,7 +820,7 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
private boolean isFirstNodeInAGroup()
{
- return getAddress().equals(getHelperAddress());
+ return getHelperNodeName() == null;
}
BDBHAVirtualHostNodeLogSubject getVirtualHostNodeLogSubject()
@@ -761,7 +853,7 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
}
}
- private void validatePermittedNodes(List<String> proposedPermittedNodes)
+ private void validatePermittedNodes(Collection<String> proposedPermittedNodes)
{
if (getRemoteReplicationNodes().size() > 0 && getRole() != NodeRole.MASTER && !(getState() == State.STOPPED || getState() == State.ERRORED))
{
@@ -772,47 +864,48 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
throw new IllegalArgumentException(String.format("Attribute '%s' is mandatory and must be set", PERMITTED_NODES));
}
- String missingNodeAddress = null;
- if (getPermittedNodes().contains(getAddress()) && !proposedPermittedNodes.contains(getAddress()))
+ if (_permittedNodes != null)
{
- missingNodeAddress = getAddress();
- }
- else
- {
- for (final RemoteReplicationNode<?> node : getRemoteReplicationNodes())
+ String missingNodeAddress = null;
+
+ if (_permittedNodes.contains(getAddress()) && !proposedPermittedNodes.contains(getAddress()))
{
- final BDBHARemoteReplicationNode<?> bdbHaRemoteReplicationNode = (BDBHARemoteReplicationNode<?>) node;
- final String remoteNodeAddress = bdbHaRemoteReplicationNode.getAddress();
- if (getPermittedNodes().contains(remoteNodeAddress) && !proposedPermittedNodes.contains(remoteNodeAddress))
+ missingNodeAddress = getAddress();
+ }
+ else
+ {
+ for (final RemoteReplicationNode<?> node : getRemoteReplicationNodes())
{
- missingNodeAddress = remoteNodeAddress;
- break;
+ final BDBHARemoteReplicationNode<?> bdbHaRemoteReplicationNode = (BDBHARemoteReplicationNode<?>) node;
+ final String remoteNodeAddress = bdbHaRemoteReplicationNode.getAddress();
+ if (_permittedNodes.contains(remoteNodeAddress) && !proposedPermittedNodes.contains(remoteNodeAddress))
+ {
+ missingNodeAddress = remoteNodeAddress;
+ break;
+ }
}
}
+
+ if (missingNodeAddress != null)
+ {
+ throw new IllegalArgumentException(String.format("The current group node '%s' cannot be removed from '%s' as its already a group member", missingNodeAddress, PERMITTED_NODES));
+ }
}
- if (missingNodeAddress != null)
+ validatePermittedNodesFormat(proposedPermittedNodes);
+ }
+
+ private void validatePermittedNodesFormat(Collection<String> permittedNodes)
+ {
+ if (permittedNodes == null || permittedNodes.isEmpty())
{
- throw new IllegalArgumentException(String.format("The current group node '%s' cannot be removed from '%s' as its already a group member", missingNodeAddress, PERMITTED_NODES));
+ throw new IllegalConfigurationException("Permitted nodes are not set");
}
- for (String permittedNode: proposedPermittedNodes)
+ for (String permittedNode: permittedNodes)
{
- String[] tokens = permittedNode.split(":");
- if (tokens.length != 2)
- {
- throw new IllegalArgumentException(String.format("Invalid permitted node specified '%s'. ", permittedNode));
- }
- try
- {
- Integer.parseInt(tokens[1]);
- }
- catch(Exception e)
- {
- throw new IllegalArgumentException(String.format("Invalid port is specified in permitted node '%s'. ", permittedNode));
- }
+ addressToURI(permittedNode);
}
-
}
private class RemoteNodesDiscoverer implements ReplicationGroupListener
@@ -931,7 +1024,7 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
{
byte[] applicationState = nodeState.getAppState();
Set<String> permittedNodes = ReplicatedEnvironmentFacade.convertApplicationStateBytesToPermittedNodeList(applicationState);
- if (!_permittedNodes.equals(permittedNodes))
+ if (_permittedNodes.size() != permittedNodes.size() || !_permittedNodes.containsAll(permittedNodes))
{
if (_permittedNodes.contains(remoteNode.getAddress()))
{
@@ -972,7 +1065,7 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
private boolean processIntruderNode(ReplicationNode node)
{
- String hostAndPort = node.getHostName() + ":" + node.getPort();
+ final String hostAndPort = node.getHostName() + ":" + node.getPort();
getEventLogger().message(getGroupLogSubject(), HighAvailabilityMessages.INTRUDER_DETECTED(node.getName(), hostAndPort));
boolean inManagementMode = getParent(Broker.class).isManagementMode();
@@ -994,35 +1087,16 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
BDBHAVirtualHostNodeImpl.this.getName(),
_lastRole.get(),
String.valueOf(BDBHAVirtualHostNodeImpl.this.getPermittedNodes()) ));
-
getTaskExecutor().submit(new Task<Void>()
{
@Override
public Void execute()
{
- State state = getState();
- if (state != State.ERRORED)
- {
- try
- {
- stopAndSetStateTo(State.ERRORED);
- }
- catch(Exception e)
- {
- LOGGER.error("Unexpected exception on closing the node when intruder is detected ", e);
- }
- finally
- {
- closeEnvironment();
-
- _lastRole.set(NodeRole.DETACHED);
- attributeSet(ROLE, _role, NodeRole.DETACHED);
- }
- notifyStateChanged(state, State.ERRORED);
- }
+ shutdownOnIntruder(hostAndPort);
return null;
}
});
+
return false;
}
}
@@ -1044,6 +1118,28 @@ public class BDBHAVirtualHostNodeImpl extends AbstractVirtualHostNode<BDBHAVirtu
}
}
+ protected void shutdownOnIntruder(String intruderHostAndPort)
+ {
+ LOGGER.info("Intruder detected (" + intruderHostAndPort + "), stopping and setting state to ERRORED");
+
+ State initialState = getState();
+ try
+ {
+ stopAndSetStateTo(State.ERRORED);
+ }
+ catch (Exception e)
+ {
+ LOGGER.error("Unexpected exception on closing the node when intruder is detected ", e);
+ }
+ finally
+ {
+ closeEnvironment();
+ _lastRole.set(NodeRole.DETACHED);
+ attributeSet(ROLE, _role, NodeRole.DETACHED);
+ }
+ notifyStateChanged(initialState, State.ERRORED);
+ }
+
private abstract class VirtualHostNodeGroupTask implements Task<Void>
{
@Override
diff --git a/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js b/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
index 18853e63a7..464a01b5b0 100644
--- a/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
+++ b/java/bdbstore/src/main/java/resources/js/qpid/management/virtualhostnode/bdb_ha/add/newgroup/add.js
@@ -106,6 +106,7 @@ define(["dojo/_base/xhr",
_changeAddress: function(address, virtualHostNodeHelperAddress)
{
virtualHostNodeHelperAddress.set("value", address);
+ this._updatePermittedNodesJson();
},
_clickAddPermittedNodeButton: function(e)
{
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
index e9bcc5d754..ee990d3211 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java
@@ -23,13 +23,17 @@ package org.apache.qpid.server.store.berkeleydb;
import static org.mockito.Mockito.when;
import java.io.File;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import com.sleepycat.je.Durability;
@@ -38,12 +42,14 @@ import com.sleepycat.je.rep.ReplicatedEnvironment;
import com.sleepycat.je.rep.ReplicationConfig;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.ConfigurationChangeListener;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.RemoteReplicationNode;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.store.berkeleydb.replication.DatabasePinger;
import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHost;
import org.apache.qpid.server.virtualhost.berkeleydb.BDBHAVirtualHostImpl;
import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHARemoteReplicationNode;
@@ -53,6 +59,8 @@ import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeTes
import org.apache.qpid.server.virtualhostnode.berkeleydb.NodeRole;
import org.apache.qpid.test.utils.PortHelper;
import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
public class BDBHAVirtualHostNodeTest extends QpidTestCase
{
@@ -289,6 +297,7 @@ public class BDBHAVirtualHostNodeTest extends QpidTestCase
_helper.awaitRemoteNodes(master, 2);
BDBHAVirtualHostNode<?> replica = _helper.awaitAndFindNodeInRole(NodeRole.REPLICA);
+ _helper.awaitRemoteNodes(replica, 2);
assertNotNull("Remote node " + replica.getName() + " is not found", _helper.findRemoteNode(master, replica.getName()));
replica.delete();
@@ -481,21 +490,70 @@ public class BDBHAVirtualHostNodeTest extends QpidTestCase
nonMasterNode.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, amendedPermittedNodes));
}
+ public void testIntruderProtection() throws Exception
+ {
+ int nodePortNumber = _portHelper.getNextAvailable();
+ int intruderPortNumber = _portHelper.getNextAvailable();
+
+ String helperAddress = "localhost:" + nodePortNumber;
+ String groupName = "group";
+ String nodeName = "node";
+
+ Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, nodePortNumber, intruderPortNumber);
+ BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(node1Attributes);
+
+ Map<String, Object> intruderAttributes = _helper.createNodeAttributes("intruder", groupName, "localhost:" + intruderPortNumber, helperAddress, nodeName);
+ intruderAttributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
+ BDBHAVirtualHostNode<?> intruder = _helper.createAndStartHaVHN(intruderAttributes);
+
+ final CountDownLatch stopLatch = new CountDownLatch(1);
+ ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
+ {
+ @Override
+ public void stateChanged(ConfiguredObject<?> object, State oldState, State newState)
+ {
+ if (newState == State.ERRORED)
+ {
+ stopLatch.countDown();
+ }
+ }
+ };
+ node.addChangeListener(listener);
+
+ List<String> permittedNodes = new ArrayList<String>();
+ permittedNodes.add(helperAddress);
+ node.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
+
+ assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS));
+
+ // Try top re start the ERRORED node and ensure exception is thrown
+ try
+ {
+ node.start();
+ fail("Restart of node should have thrown exception");
+ }
+ catch (IllegalStateException ise)
+ {
+ assertEquals("Unexpected exception when restarting node post intruder detection", "Intruder node detected: " + "localhost:" + intruderPortNumber, ise.getMessage());
+ }
+ _helper.awaitForAttributeChange(node, AbstractConfiguredObject.STATE, State.ERRORED);
+ }
+
public void testIntruderProtectionInManagementMode() throws Exception
{
- int node1PortNumber = _portHelper.getNextAvailable();
- int node2PortNumber = _portHelper.getNextAvailable();
+ int nodePortNumber = _portHelper.getNextAvailable();
+ int intruderPortNumber = _portHelper.getNextAvailable();
- String helperAddress = "localhost:" + node1PortNumber;
+ String helperAddress = "localhost:" + nodePortNumber;
String groupName = "group";
- String nodeName = "node1";
+ String nodeName = "node";
- Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber);
- BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes);
+ Map<String, Object> nodeAttributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, nodePortNumber, intruderPortNumber);
+ BDBHAVirtualHostNode<?> node = _helper.createAndStartHaVHN(nodeAttributes);
- Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName);
- node2Attributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
- BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes);
+ Map<String, Object> intruderAttributes = _helper.createNodeAttributes("intruder", groupName, "localhost:" + intruderPortNumber, helperAddress, nodeName);
+ intruderAttributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
+ BDBHAVirtualHostNode<?> intruder = _helper.createAndStartHaVHN(intruderAttributes);
final CountDownLatch stopLatch = new CountDownLatch(1);
ConfigurationChangeListener listener = new NoopConfigurationChangeListener()
@@ -509,21 +567,85 @@ public class BDBHAVirtualHostNodeTest extends QpidTestCase
}
}
};
- node1.addChangeListener(listener);
+ node.addChangeListener(listener);
List<String> permittedNodes = new ArrayList<String>();
permittedNodes.add(helperAddress);
- node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
+ node.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(10, TimeUnit.SECONDS));
+ // test that if management mode is enabled then the node can start without exception
when(_helper.getBroker().isManagementMode()).thenReturn(true);
- node1.start();
+ node.start();
+
+ _helper.awaitForAttributeChange(node, AbstractConfiguredObject.STATE, State.ERRORED);
+ }
+
+ public void testPermittedNodesChangedOnReplicaNodeOnlyOnceAfterBeingChangedOnMaster() throws Exception
+ {
+ int node1PortNumber = _portHelper.getNextAvailable();
+ int node2PortNumber = _portHelper.getNextAvailable();
+
+ String helperAddress = "localhost:" + node1PortNumber;
+ String groupName = "group";
+ String nodeName = "node1";
+
+ Map<String, Object> node1Attributes = _helper.createNodeAttributes(nodeName, groupName, helperAddress, helperAddress, nodeName, node1PortNumber, node2PortNumber);
+ BDBHAVirtualHostNode<?> node1 = _helper.createAndStartHaVHN(node1Attributes);
+
+ Map<String, Object> node2Attributes = _helper.createNodeAttributes("node2", groupName, "localhost:" + node2PortNumber, helperAddress, nodeName);
+ node2Attributes.put(BDBHAVirtualHostNode.PRIORITY, 0);
+ BDBHAVirtualHostNode<?> node2 = _helper.createAndStartHaVHN(node2Attributes);
+ assertEquals("Unexpected role", NodeRole.REPLICA, node2.getRole());
+ _helper.awaitRemoteNodes(node2, 1);
+
+ BDBHARemoteReplicationNode<?> remote = _helper.findRemoteNode(node2, node1.getName());
+
+ final AtomicInteger permittedNodesChangeCounter = new AtomicInteger();
+ final CountDownLatch _permittedNodesLatch = new CountDownLatch(1);
+ node2.addChangeListener(new NoopConfigurationChangeListener()
+ {
+ @Override
+ public void attributeSet(ConfiguredObject<?> object, String attributeName, Object oldAttributeValue, Object newAttributeValue)
+ {
+ if (attributeName.equals(BDBHAVirtualHostNode.PERMITTED_NODES))
+ {
+ permittedNodesChangeCounter.incrementAndGet();
+ _permittedNodesLatch.countDown();
+ }
+ }
+ });
+ List<String> permittedNodes = new ArrayList<>(node1.getPermittedNodes());
+ permittedNodes.add("localhost:5000");
+ node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
+
+ assertTrue("Permitted nodes were not changed on Replica", _permittedNodesLatch.await(10, TimeUnit.SECONDS));
+ assertEquals("Not the same permitted nodes", new HashSet<>(node1.getPermittedNodes()), new HashSet<>(node2.getPermittedNodes()));
+ assertEquals("Unexpected counter of changes permitted nodes", 1, permittedNodesChangeCounter.get());
+
+ // change the order of permitted nodes
+ Collections.swap(permittedNodes, 0, 2);
+ node1.setAttributes(Collections.<String, Object>singletonMap(BDBHAVirtualHostNode.PERMITTED_NODES, permittedNodes));
+
+ // make sure that node2 onNodeState was invoked by performing transaction on master and making sure that it was replicated
+ performTransactionAndAwaitForRemoteNodeToGetAware(node1, remote);
+
+ // perform transaction second time because permitted nodes are changed after last transaction id
+ performTransactionAndAwaitForRemoteNodeToGetAware(node1, remote);
+ assertEquals("Unexpected counter of changes permitted nodes", 1, permittedNodesChangeCounter.get());
+ }
- _helper.awaitRemoteNodes(node1, 1);
+ private void performTransactionAndAwaitForRemoteNodeToGetAware(BDBHAVirtualHostNode<?> node1, BDBHARemoteReplicationNode<?> remote) throws InterruptedException
+ {
+ new DatabasePinger().pingDb(((BDBConfigurationStore)node1.getConfigurationStore()).getEnvironmentFacade());
- BDBHARemoteReplicationNode<?> remote = _helper.findRemoteNode(node1, node2.getName());
- remote.delete();
+ int waitCounter = 100;
+ while ( remote.getLastKnownReplicationTransactionId() != node1.getLastKnownReplicationTransactionId() && (waitCounter--) != 0)
+ {
+ Thread.sleep(100l);
+ }
+ assertEquals("Last transaction was not replicated", new Long(remote.getLastKnownReplicationTransactionId()), node1.getLastKnownReplicationTransactionId() );
}
public void testIntruderConnected() throws Exception
@@ -587,4 +709,87 @@ public class BDBHAVirtualHostNodeTest extends QpidTestCase
assertTrue("Intruder protection was not triggered during expected timeout", stopLatch.await(20, TimeUnit.SECONDS));
}
+ public void testValidateOnCreateForNonExistingHelperNode() throws Exception
+ {
+ int node1PortNumber = findFreePort();
+ int node2PortNumber = getNextAvailable(node1PortNumber + 1);
+
+
+ Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber,
+ "localhost:" + node2PortNumber, "node2", node1PortNumber, node1PortNumber, node2PortNumber);
+ try
+ {
+ _helper.createAndStartHaVHN(attributes);
+ fail("Node creation should fail because of invalid helper address");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception on connection to non-existing helper address",
+ String.format("Cannot connect to existing node '%s' at '%s'", "node2", "localhost:" + node2PortNumber), e.getMessage());
+ }
+ }
+
+ public void testValidateOnCreateForAlreadyBoundAddress() throws Exception
+ {
+ int node1PortNumber = findFreePort();
+
+ ServerSocket serverSocket = null;
+ try
+ {
+ serverSocket = new ServerSocket();
+ serverSocket.setReuseAddress(true);
+ serverSocket.bind(new InetSocketAddress("localhost", node1PortNumber));
+
+
+ Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber,
+ "localhost:" + node1PortNumber, "node2", node1PortNumber, node1PortNumber);
+ try
+ {
+ _helper.createAndStartHaVHN(attributes);
+ fail("Node creation should fail because of invalid address");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception on attempt to create node with already bound address",
+ String.format("Cannot bind to address '%s'. Address is already in use.", "localhost:" + node1PortNumber), e.getMessage());
+ }
+ }
+ finally
+ {
+ if (serverSocket != null)
+ {
+ serverSocket.close();
+ }
+ }
+ }
+
+ public void testValidateOnCreateForInvalidStorePath() throws Exception
+ {
+ int node1PortNumber = findFreePort();
+
+ File storeBaseFolder = TestFileUtils.createTestDirectory();
+ File file = new File(storeBaseFolder, getTestName());
+ file.createNewFile();
+ File storePath = new File(file, "test");
+ try
+ {
+ Map<String, Object> attributes = _helper.createNodeAttributes("node1", "group", "localhost:" + node1PortNumber,
+ "localhost:" + node1PortNumber, "node2", node1PortNumber, node1PortNumber);
+ attributes.put(BDBHAVirtualHostNode.STORE_PATH, storePath.getAbsoluteFile());
+ try
+ {
+ _helper.createAndStartHaVHN(attributes);
+ fail("Node creation should fail because of invalid store path");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception on attempt to create environment in invalid location",
+ String.format("Store path '%s' is not a folder", storePath.getAbsoluteFile()), e.getMessage());
+ }
+ }
+ finally
+ {
+ FileUtils.delete(storeBaseFolder, true);
+ }
+ }
}
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java
new file mode 100644
index 0000000000..92da465dbd
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImplTest.java
@@ -0,0 +1,106 @@
+/*
+ *
+ * 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.virtualhost.berkeleydb;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.util.BrokerTestHelper;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
+
+public class BDBVirtualHostImplTest extends QpidTestCase
+{
+ private File _storePath;
+ private VirtualHostNode<?> _node;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ Broker broker = BrokerTestHelper.createBrokerMock();
+
+ TaskExecutor taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+ when(broker.getTaskExecutor()).thenReturn(taskExecutor);
+
+ _storePath = TestFileUtils.createTestDirectory();
+
+ _node = mock(VirtualHostNode.class);
+ when(_node.getParent(Broker.class)).thenReturn(broker);
+ when(_node.getModel()).thenReturn(BrokerModel.getInstance());
+ when(_node.getTaskExecutor()).thenReturn(taskExecutor);
+ when(_node.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class));
+ when(_node.getId()).thenReturn(UUID.randomUUID());
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_storePath != null)
+ {
+ FileUtils.delete(_storePath, true);
+ }
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ public void testValidateOnCreateForInvalidStorePath() throws Exception
+ {
+ String hostName = getTestName();
+ File file = new File(_storePath + File.separator + hostName);
+ assertTrue("Empty file is not created", file.createNewFile());
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(BDBVirtualHost.ID, UUID.randomUUID());
+ attributes.put(BDBVirtualHost.TYPE, BDBVirtualHostImpl.VIRTUAL_HOST_TYPE);
+ attributes.put(BDBVirtualHost.NAME, hostName);
+ attributes.put(BDBVirtualHost.STORE_PATH, file.getAbsoluteFile());
+
+ BDBVirtualHostImpl host = new BDBVirtualHostImpl(attributes, _node);
+ try
+ {
+ host.create();
+ fail("Cannot create DBD virtual host from existing empty file");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open virtual host message store"));
+ }
+ }
+
+}
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
index d71fb8b474..6d740568ab 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeOperationalLoggingTest.java
@@ -87,6 +87,9 @@ public class BDBHAVirtualHostNodeOperationalLoggingTest extends QpidTestCase
_helper.assertNodeRole(node1, NodeRole.MASTER);
+ // stop node to avoid running into race when role change is reported after we performed the check
+ node1.stop();
+
assertEquals("Unexpected VHN log subject", "[grp(/group)/vhn(/node1)] ", node1.getVirtualHostNodeLogSubject().getLogString());
assertEquals("Unexpected group log subject", "[grp(/group)] ", node1.getGroupLogSubject().getLogString());
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
index c12fecece3..0dc72acdb9 100644
--- a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeTestHelper.java
@@ -279,11 +279,14 @@ public class BDBHAVirtualHostNodeTestHelper
node1Attributes.put(BDBHAVirtualHostNode.ADDRESS, address);
node1Attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperAddress);
node1Attributes.put(BDBHAVirtualHostNode.STORE_PATH, getMessageStorePath() + File.separator + nodeName);
- node1Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, helperNodeNode);
if (address.equals(helperAddress))
{
node1Attributes.put(BDBHAVirtualHostNode.PERMITTED_NODES, getPermittedNodes(ports));
}
+ else
+ {
+ node1Attributes.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, helperNodeNode);
+ }
Map<String, String> context = new HashMap<String, String>();
context.put(ReplicationConfig.REPLICA_ACK_TIMEOUT, "2 s");
diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java
new file mode 100644
index 0000000000..6608312088
--- /dev/null
+++ b/java/bdbstore/src/test/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeTest.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.virtualhostnode.berkeleydb;
+
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.util.BrokerTestHelper;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+import org.apache.qpid.util.FileUtils;
+
+public class BDBVirtualHostNodeTest extends QpidTestCase
+{
+ private Broker<?> _broker;
+ private File _storePath;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _broker = BrokerTestHelper.createBrokerMock();
+ when(_broker.getTaskExecutor()).thenReturn(CurrentThreadTaskExecutor.newStartedInstance());
+
+ _storePath = TestFileUtils.createTestDirectory();
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_storePath != null)
+ {
+ FileUtils.delete(_storePath, true);
+ }
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ public void testValidateOnCreateForInvalidStorePath() throws Exception
+ {
+ String nodeName = getTestName();
+ File file = new File(_storePath + File.separator + nodeName);
+ assertTrue("Empty file is not created", file.createNewFile());
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(BDBVirtualHostNode.ID, UUID.randomUUID());
+ attributes.put(BDBVirtualHostNode.TYPE, BDBVirtualHostNodeImpl.VIRTUAL_HOST_NODE_TYPE);
+ attributes.put(BDBVirtualHostNode.NAME, nodeName);
+ attributes.put(BDBVirtualHostNode.STORE_PATH, file.getAbsolutePath());
+
+ BDBVirtualHostNodeImpl node = new BDBVirtualHostNodeImpl(attributes, _broker);
+ try
+ {
+ node.create();
+ fail("Cannot create DBD node from existing empty file");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open node configuration store"));
+ }
+ }
+
+}
diff --git a/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java b/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java
index c0c1b23a34..cfbd030474 100644
--- a/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java
+++ b/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/BDBHAVirtualHostNodeRestTest.java
@@ -326,7 +326,10 @@ public class BDBHAVirtualHostNodeRestTest extends QpidRestTestCase
nodeData.put(BDBHAVirtualHostNode.GROUP_NAME, _hostName);
nodeData.put(BDBHAVirtualHostNode.ADDRESS, "localhost:" + nodePort);
nodeData.put(BDBHAVirtualHostNode.HELPER_ADDRESS, "localhost:" + helperPort);
- nodeData.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, NODE1);
+ if (nodePort != helperPort)
+ {
+ nodeData.put(BDBHAVirtualHostNode.HELPER_NODE_NAME, NODE1);
+ }
Map<String,String> context = new HashMap<>();
nodeData.put(BDBHAVirtualHostNode.CONTEXT, context);
diff --git a/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java b/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
index 9e850714b0..38484b546f 100644
--- a/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
+++ b/java/bdbstore/systests/src/test/java/org/apache/qpid/server/store/berkeleydb/replication/MultiNodeTest.java
@@ -166,8 +166,8 @@ public class MultiNodeTest extends QpidBrokerTestCase
// New connections should now fail as vhost will be unavailable
try
{
- getConnection(_negativeFailoverUrl);
- fail("Exception not thrown");
+ Connection unexpectedConnection = getConnection(_negativeFailoverUrl);
+ fail("Got unexpected connection to node in group without quorum " + unexpectedConnection);
}
catch (JMSException je)
{
diff --git a/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java b/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
index c569bc4641..317e0f7c74 100644
--- a/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
+++ b/java/broker-codegen/src/main/java/org/apache/qpid/server/model/SystemConfigFactoryGenerator.java
@@ -117,9 +117,9 @@ public class SystemConfigFactoryGenerator extends AbstractProcessor
pw.println("import org.apache.qpid.server.configuration.updater.TaskExecutor;");
pw.println("import org.apache.qpid.server.logging.EventLogger;");
pw.println("import org.apache.qpid.server.logging.LogRecorder;");
- pw.println("import org.apache.qpid.server.model.SystemConfig;");
+ pw.println("import org.apache.qpid.server.model.BrokerShutdownProvider;");
pw.println("import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;");
- pw.println();
+ pw.println("import org.apache.qpid.server.model.SystemConfig;");
pw.println("import org.apache.qpid.server.plugin.PluggableService;");
pw.println("import org.apache.qpid.server.plugin.SystemConfigFactory;");
pw.println();
@@ -140,9 +140,10 @@ public class SystemConfigFactoryGenerator extends AbstractProcessor
pw.println(" public "+objectSimpleName+" newInstance(final TaskExecutor taskExecutor,");
pw.println(" final EventLogger eventLogger,");
pw.println(" final LogRecorder logRecorder,");
- pw.println(" final BrokerOptions brokerOptions)");
+ pw.println(" final BrokerOptions brokerOptions,");
+ pw.println(" final BrokerShutdownProvider brokerShutdownProvider)");
pw.println(" {");
- pw.println(" return new "+objectSimpleName+"(taskExecutor, eventLogger, logRecorder, brokerOptions);");
+ pw.println(" return new "+objectSimpleName+"(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);");
pw.println(" }");
pw.println("}");
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
index 0a1979128f..0b925d130c 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
@@ -40,6 +40,7 @@ import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.logging.SystemOutMessageLogger;
import org.apache.qpid.server.logging.log4j.LoggingManagementFacade;
import org.apache.qpid.server.logging.messages.BrokerMessages;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.plugin.PluggableFactoryLoader;
import org.apache.qpid.server.plugin.SystemConfigFactory;
@@ -48,7 +49,7 @@ import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.store.DurableConfigurationStore;
-public class Broker
+public class Broker implements BrokerShutdownProvider
{
private static final Logger LOGGER = Logger.getLogger(Broker.class);
@@ -143,7 +144,7 @@ public class Broker
LogRecorder logRecorder = new LogRecorder();
_taskExecutor.start();
- SystemConfig systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options);
+ SystemConfig systemConfig = configFactory.newInstance(_taskExecutor, _eventLogger, logRecorder, options, this);
systemConfig.open();
DurableConfigurationStore store = systemConfig.getConfigurationStore();
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
index b71d667fe0..6c67a44bb0 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
@@ -29,9 +29,12 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.updater.VoidTask;
import org.apache.qpid.server.exchange.AbstractExchange;
import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.filter.AMQInvalidArgumentException;
+import org.apache.qpid.server.filter.FilterSupport;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.messages.BindingMessages;
import org.apache.qpid.server.logging.subjects.BindingLogSubject;
@@ -269,4 +272,23 @@ public class BindingImpl
);
}
+
+ @Override
+ public void validateOnCreate()
+ {
+ AMQQueue queue = getAMQQueue();
+ Map<String, Object> arguments = getArguments();
+ if (arguments!=null && !arguments.isEmpty() && FilterSupport.argumentsContainFilter(arguments))
+ {
+ try
+ {
+ FilterSupport.createMessageFilter(arguments, queue);
+ }
+ catch (AMQInvalidArgumentException e)
+ {
+ throw new IllegalConfigurationException(e.getMessage(), e);
+ }
+ }
+ }
+
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index fd0333f6e7..989a4abea5 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -118,16 +118,6 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>>
throw new IllegalArgumentException("Unknown attributes provided: " + providedAttributeNames);
}
_virtualHost = vhost;
- // check ACL
- try
- {
- _virtualHost.getSecurityManager().authoriseCreateExchange(this);
- }
- catch (AccessControlException e)
- {
- deleted();
- throw e;
- }
_logSubject = new ExchangeLogSubject(this, this.getVirtualHost());
@@ -145,6 +135,12 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>>
}
@Override
+ public void validateOnCreate()
+ {
+ _virtualHost.getSecurityManager().authoriseCreateExchange(this);
+ }
+
+ @Override
public void onValidate()
{
super.onValidate();
@@ -756,7 +752,7 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>>
final Map<String, Object> oldArguments);
- @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+ @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
private void activate()
{
setState(State.ACTIVE);
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
index d3741cd846..e6f79fef16 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
@@ -47,6 +47,7 @@ import java.util.concurrent.atomic.AtomicReference;
import javax.security.auth.Subject;
+import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
@@ -72,6 +73,8 @@ import org.apache.qpid.util.Strings;
public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> implements ConfiguredObject<X>
{
+ private static final Logger LOGGER = Logger.getLogger(AbstractConfiguredObject.class);
+
private static final Map<Class, Object> SECURE_VALUES;
public static final String SECURED_STRING_VALUE = "********";
@@ -156,9 +159,10 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
private final OwnAttributeResolver _attributeResolver = new OwnAttributeResolver(this);
- @ManagedAttributeField( afterSet = "attainStateIfResolved" )
+ @ManagedAttributeField( afterSet = "attainStateIfOpenedOrReopenFailed" )
private State _desiredState;
private boolean _openComplete;
+ private boolean _openFailed;
private volatile State _state = State.UNINITIALIZED;
protected static Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> parentsMap(ConfiguredObject<?>... parents)
@@ -404,10 +408,19 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
{
if(_dynamicState.compareAndSet(DynamicState.UNINIT, DynamicState.OPENED))
{
- doResolution(true);
- doValidation(true);
- doOpening(true);
- doAttainState();
+ _openFailed = false;
+ OpenExceptionHandler exceptionHandler = new OpenExceptionHandler();
+ try
+ {
+ doResolution(true, exceptionHandler);
+ doValidation(true, exceptionHandler);
+ doOpening(true, exceptionHandler);
+ doAttainState(exceptionHandler);
+ }
+ catch(RuntimeException e)
+ {
+ exceptionHandler.handleException(e, this);
+ }
}
}
@@ -485,18 +498,76 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
_lastUpdatedTime = currentTime;
_createdTime = currentTime;
- doResolution(true);
- doValidation(true);
+ CreateExceptionHandler createExceptionHandler = new CreateExceptionHandler();
+ try
+ {
+ doResolution(true, createExceptionHandler);
+ doValidation(true, createExceptionHandler);
+ validateOnCreate();
+ registerWithParents();
+ }
+ catch(RuntimeException e)
+ {
+ createExceptionHandler.handleException(e, this);
+ }
+
+ AbstractConfiguredObjectExceptionHandler unregisteringExceptionHandler = new CreateExceptionHandler(true);
+ try
+ {
+ doCreation(true, unregisteringExceptionHandler);
+ doOpening(true, unregisteringExceptionHandler);
+ doAttainState(unregisteringExceptionHandler);
+ }
+ catch(RuntimeException e)
+ {
+ unregisteringExceptionHandler.handleException(e, this);
+ }
+ }
+ }
+
+ protected void validateOnCreate()
+ {
+ }
+
+ protected final void handleExceptionOnOpen(RuntimeException e)
+ {
+ if (e instanceof ServerScopedRuntimeException)
+ {
+ throw e;
+ }
+
+ LOGGER.error("Failed to open object with name '" + getName() + "'. Object will be put into ERROR state.", e);
- registerWithParents();
+ try
+ {
+ onExceptionInOpen(e);
+ }
+ catch (RuntimeException re)
+ {
+ LOGGER.error("Unexpected exception while handling exception on open for " + getName(), e);
+ }
- doCreation(true);
- doOpening(true);
- doAttainState();
+ if (!_openComplete)
+ {
+ _openFailed = true;
+ _dynamicState.compareAndSet(DynamicState.OPENED, DynamicState.UNINIT);
}
+
+ //TODO: children of ERRORED CO will continue to remain in ACTIVE state
+ setState(State.ERRORED);
+ }
+
+ /**
+ * Callback method to perform ConfiguredObject specific exception handling on exception in open.
+ * <p/>
+ * The method is not expected to throw any runtime exception.
+ * @param e open exception
+ */
+ protected void onExceptionInOpen(RuntimeException e)
+ {
}
- private void doAttainState()
+ private void doAttainState(final AbstractConfiguredObjectExceptionHandler exceptionHandler)
{
applyToChildren(new Action<ConfiguredObject<?>>()
{
@@ -505,14 +576,25 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
{
if (child instanceof AbstractConfiguredObject)
{
- ((AbstractConfiguredObject) child).doAttainState();
+ AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+ if (configuredObject._dynamicState.get() == DynamicState.OPENED)
+ {
+ try
+ {
+ configuredObject.doAttainState(exceptionHandler);
+ }
+ catch (RuntimeException e)
+ {
+ exceptionHandler.handleException(e, configuredObject);
+ }
+ }
}
}
});
attainState();
}
- protected void doOpening(final boolean skipCheck)
+ protected void doOpening(boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
{
if(skipCheck || _dynamicState.compareAndSet(DynamicState.UNINIT,DynamicState.OPENED))
{
@@ -523,9 +605,17 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
@Override
public void performAction(final ConfiguredObject<?> child)
{
- if (child instanceof AbstractConfiguredObject)
+ if (child.getState() != State.ERRORED && child instanceof AbstractConfiguredObject)
{
- ((AbstractConfiguredObject) child).doOpening(false);
+ AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+ try
+ {
+ configuredObject.doOpening(false, exceptionHandler);
+ }
+ catch (RuntimeException e)
+ {
+ exceptionHandler.handleException(e, configuredObject);
+ }
}
}
});
@@ -533,7 +623,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
}
}
- protected final void doValidation(final boolean skipCheck)
+ protected final void doValidation(final boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
{
if(skipCheck || _dynamicState.get() != DynamicState.OPENED)
{
@@ -542,9 +632,17 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
@Override
public void performAction(final ConfiguredObject<?> child)
{
- if (child instanceof AbstractConfiguredObject)
+ if (child.getState() != State.ERRORED && child instanceof AbstractConfiguredObject)
{
- ((AbstractConfiguredObject) child).doValidation(false);
+ AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+ try
+ {
+ configuredObject.doValidation(false, exceptionHandler);
+ }
+ catch (RuntimeException e)
+ {
+ exceptionHandler.handleException(e, configuredObject);
+ }
}
}
});
@@ -552,20 +650,28 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
}
}
- protected final void doResolution(final boolean skipCheck)
+ protected final void doResolution(boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
{
if(skipCheck || _dynamicState.get() != DynamicState.OPENED)
{
onResolve();
postResolve();
- applyToChildren(new Action<ConfiguredObject<?>>()
+ applyToChildren(new Action()
{
@Override
- public void performAction(final ConfiguredObject<?> child)
+ public void performAction(Object child)
{
if (child instanceof AbstractConfiguredObject)
{
- ((AbstractConfiguredObject) child).doResolution(false);
+ AbstractConfiguredObject configuredObject = (AbstractConfiguredObject) child;
+ try
+ {
+ configuredObject.doResolution(false, exceptionHandler);
+ }
+ catch (RuntimeException e)
+ {
+ exceptionHandler.handleException(e, configuredObject);
+ }
}
}
});
@@ -576,7 +682,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
{
}
- protected final void doCreation(final boolean skipCheck)
+ protected final void doCreation(final boolean skipCheck, final AbstractConfiguredObjectExceptionHandler exceptionHandler)
{
if(skipCheck || _dynamicState.get() != DynamicState.OPENED)
{
@@ -588,7 +694,15 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
{
if (child instanceof AbstractConfiguredObject)
{
- ((AbstractConfiguredObject) child).doCreation(false);
+ AbstractConfiguredObject configuredObject =(AbstractConfiguredObject) child;
+ try
+ {
+ configuredObject.doCreation(false, exceptionHandler);
+ }
+ catch (RuntimeException e)
+ {
+ exceptionHandler.handleException(e, configuredObject);
+ }
}
}
});
@@ -711,12 +825,16 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
}
}
- private void attainStateIfResolved()
+ private void attainStateIfOpenedOrReopenFailed()
{
- if(_openComplete)
+ if (_openComplete || getDesiredState() == State.DELETED)
{
attainState();
}
+ else if (_openFailed)
+ {
+ open();
+ }
}
protected void onOpen()
@@ -830,8 +948,13 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
State state = getState();
if(desiredState == getDesiredState() && desiredState != state)
{
- attainState();
- return getState();
+ attainStateIfOpenedOrReopenFailed();
+ final State currentState = getState();
+ if (currentState != state)
+ {
+ notifyStateChanged(state, currentState);
+ }
+ return currentState;
}
else
{
@@ -1217,7 +1340,6 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
{
if (_childrenByName.get(categoryClass).containsKey(name))
{
- child.delete();
throw new DuplicateNameException(child);
}
_childrenByName.get(categoryClass).put(name, child);
@@ -1756,4 +1878,54 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
return _name;
}
}
+
+ interface AbstractConfiguredObjectExceptionHandler
+ {
+ void handleException(RuntimeException exception, AbstractConfiguredObject<?> source);
+ }
+
+ private static class OpenExceptionHandler implements AbstractConfiguredObjectExceptionHandler
+ {
+ @Override
+ public void handleException(RuntimeException exception, AbstractConfiguredObject<?> source)
+ {
+ source.handleExceptionOnOpen(exception);
+ }
+ }
+
+ private static class CreateExceptionHandler implements AbstractConfiguredObjectExceptionHandler
+ {
+ private final boolean _unregister;
+
+ private CreateExceptionHandler()
+ {
+ this(false);
+ }
+
+ private CreateExceptionHandler(boolean unregister)
+ {
+ _unregister = unregister;
+ }
+
+ @Override
+
+ public void handleException(RuntimeException exception, AbstractConfiguredObject<?> source)
+ {
+ try
+ {
+ if (source.getState() != State.DELETED)
+ {
+ source.delete();
+ }
+ }
+ finally
+ {
+ if (_unregister)
+ {
+ source.unregister(false);
+ }
+ throw exception;
+ }
+ }
+ }
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
index 19f6139387..f8dac7cbe9 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
@@ -49,13 +49,15 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>>
private final EventLogger _eventLogger;
private final LogRecorder _logRecorder;
private final BrokerOptions _brokerOptions;
+ private final BrokerShutdownProvider _brokerShutdownProvider;
private DurableConfigurationStore _configurationStore;
public AbstractSystemConfig(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions)
+ final BrokerOptions brokerOptions,
+ final BrokerShutdownProvider brokerShutdownProvider)
{
super(parentsMap(),
updateAttributes(brokerOptions.convertToSystemAttributes()),
@@ -64,6 +66,7 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>>
getTaskExecutor().start();
_logRecorder = logRecorder;
_brokerOptions = brokerOptions;
+ _brokerShutdownProvider = brokerShutdownProvider;
}
private static Map<String, Object> updateAttributes(Map<String, Object> attributes)
@@ -212,4 +215,9 @@ public abstract class AbstractSystemConfig<X extends SystemConfig<X>>
}
+ @Override
+ public BrokerShutdownProvider getBrokerShutdownProvider()
+ {
+ return _brokerShutdownProvider;
+ }
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java
new file mode 100644
index 0000000000..5c8ab3e850
--- /dev/null
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerShutdownProvider.java
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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;
+
+public interface BrokerShutdownProvider
+{
+ void shutdown();
+}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
index 1763aca524..c9a828e7e4 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/JsonSystemConfigImpl.java
@@ -38,9 +38,10 @@ public class JsonSystemConfigImpl extends AbstractSystemConfig<JsonSystemConfigI
public JsonSystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions)
+ final BrokerOptions brokerOptions,
+ final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+ super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
}
public String getStorePath()
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
index 7943c32c42..ec063142b4 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/SystemConfig.java
@@ -37,4 +37,6 @@ public interface SystemConfig<X extends SystemConfig<X>> extends ConfiguredObjec
LogRecorder getLogRecorder();
DurableConfigurationStore getConfigurationStore();
+
+ BrokerShutdownProvider getBrokerShutdownProvider();
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
index 92ac43e629..109aaff5bd 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java
@@ -943,6 +943,28 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple
_eventLogger = eventLogger;
}
+ @Override
+ protected void onExceptionInOpen(RuntimeException e)
+ {
+ SystemConfig systemConfig = getParent(SystemConfig.class);
+ if (systemConfig != null)
+ {
+ BrokerShutdownProvider shutdownProvider = systemConfig.getBrokerShutdownProvider();
+ if (shutdownProvider != null)
+ {
+ shutdownProvider.shutdown();
+ }
+ else
+ {
+ throw new IllegalStateException("Shutdown provider is not found in system config");
+ }
+ }
+ else
+ {
+ throw new IllegalStateException("SystemConfig is not found among broker parents");
+ }
+ }
+
public void registerMessageDelivered(long messageSize)
{
_messagesDelivered.registerEvent(1L);
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
index c96f4c0849..1b3d0591c0 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
@@ -114,22 +114,27 @@ public class FileBasedGroupProviderImpl
throw new IllegalArgumentException("Cannot change the path");
}
}
+
+ @Override
protected void onOpen()
{
super.onOpen();
- if(_groupDatabase == null)
+ FileGroupDatabase groupDatabase = new FileGroupDatabase();
+ try
{
- _groupDatabase = new FileGroupDatabase();
- try
- {
- _groupDatabase.setGroupFile(getPath());
- }
- catch (IOException e)
+ groupDatabase.setGroupFile(getPath());
+ }
+ catch(IOException | RuntimeException e)
+ {
+ if (e instanceof IllegalConfigurationException)
{
- setState(State.ERRORED);
- LOGGER.warn(("Unable to open preferences file at " + _path));
+ throw (IllegalConfigurationException) e;
}
+ throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", getPath()), e);
}
+
+ _groupDatabase = groupDatabase;
+
Set<Principal> groups = getGroupPrincipals();
Collection<Group> principals = new ArrayList<Group>(groups.size());
for (Principal group : groups)
@@ -150,43 +155,47 @@ public class FileBasedGroupProviderImpl
protected void onCreate()
{
super.onCreate();
- _groupDatabase = new FileGroupDatabase();
-
File file = new File(_path);
if (!file.exists())
{
File parent = file.getParentFile();
- if (!parent.exists())
+ if (!parent.exists() && !file.getParentFile().mkdirs())
{
- parent.mkdirs();
+ throw new IllegalConfigurationException(String.format("Cannot create groups file at '%s'",_path));
}
- if (parent.exists())
+ try
{
- try
- {
- file.createNewFile();
- }
- catch (IOException e)
- {
- throw new IllegalConfigurationException("Cannot create group file");
- }
+ file.createNewFile();
}
- else
+ catch (IOException e)
{
- throw new IllegalConfigurationException("Cannot create group file");
+ throw new IllegalConfigurationException(String.format("Cannot create groups file at '%s'", _path), e);
}
}
- try
- {
- _groupDatabase.setGroupFile(getPath());
- }
- catch (IOException e)
- {
- setState(State.ERRORED);
- LOGGER.warn(("Unable to open preferences file at " + _path));
- }
+ }
+ @Override
+ protected void validateOnCreate()
+ {
+ super.validateOnCreate();
+ File groupsFile = new File(_path);
+ if (groupsFile.exists())
+ {
+ if (!groupsFile.canRead())
+ {
+ throw new IllegalConfigurationException(String.format("Cannot read groups file '%s'. Please check permissions.", _path));
+ }
+ FileGroupDatabase groupDatabase = new FileGroupDatabase();
+ try
+ {
+ groupDatabase.setGroupFile(_path);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", _path), e);
+ }
+ }
}
@Override
@@ -205,6 +214,11 @@ public class FileBasedGroupProviderImpl
getSecurityManager().authoriseGroupOperation(Operation.CREATE, groupName);
+ if (getState() != State.ACTIVE)
+ {
+ throw new IllegalConfigurationException(String.format("Group provider '%s' is not activated. Cannot create a group.", getName()));
+ }
+
_groupDatabase.createGroup(groupName);
Map<String,Object> attrMap = new HashMap<String, Object>();
@@ -247,20 +261,22 @@ public class FileBasedGroupProviderImpl
return _broker.getSecurityManager();
}
- @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED }, desiredState = State.ACTIVE )
+ @StateTransition( currentState = { State.UNINITIALIZED, State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
private void activate()
{
- try
+ if (_groupDatabase != null)
{
- _groupDatabase.setGroupFile(getPath());
setState(State.ACTIVE);
}
- catch(IOException | RuntimeException e)
+ else
{
- setState(State.ERRORED);
if (_broker.isManagementMode())
{
- LOGGER.warn("Failed to activate group provider: " + getName(), e);
+ LOGGER.warn("Failed to activate group provider: " + getName());
+ }
+ else
+ {
+ throw new IllegalConfigurationException(String.format("Cannot load groups from '%s'", getPath()));
}
}
}
@@ -268,6 +284,7 @@ public class FileBasedGroupProviderImpl
@StateTransition( currentState = { State.QUIESCED, State.ACTIVE, State.ERRORED}, desiredState = State.DELETED )
private void doDelete()
{
+ close();
File file = new File(getPath());
if (file.exists())
{
@@ -289,7 +306,7 @@ public class FileBasedGroupProviderImpl
public Set<Principal> getGroupPrincipalsForUser(String username)
{
- Set<String> groups = _groupDatabase.getGroupsForUser(username);
+ Set<String> groups = _groupDatabase == null ? Collections.<String>emptySet(): _groupDatabase.getGroupsForUser(username);
if (groups.isEmpty())
{
return Collections.emptySet();
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
index f2be4fd861..e3ded3006d 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderImpl.java
@@ -76,20 +76,64 @@ public class FileSystemPreferencesProviderImpl
_authenticationProvider = authenticationProvider;
}
- @StateTransition( currentState = State.UNINITIALIZED, desiredState = State.ACTIVE )
+ @Override
+ protected void validateOnCreate()
+ {
+ super.validateOnCreate();
+ File storeFile = new File(_path);
+ if (storeFile.exists() )
+ {
+ if (!storeFile.canRead())
+ {
+ throw new IllegalConfigurationException(String.format("Cannot read preferences file '%s'. Please check permissions.", _path));
+ }
+
+ FileSystemPreferencesStore store = null;
+ try
+ {
+ store = new FileSystemPreferencesStore(storeFile);
+ store.open();
+ }
+ catch (RuntimeException e)
+ {
+ if (e instanceof IllegalConfigurationException)
+ {
+ throw e;
+ }
+ throw new IllegalConfigurationException(String.format("Cannot open preferences store at '%s'", _path), e);
+ }
+ finally
+ {
+ if (store != null)
+ {
+ store.close();
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onOpen()
+ {
+ FileSystemPreferencesStore store = new FileSystemPreferencesStore(new File(_path));
+
+ // we need to check and create file if it does not exist every time on open
+ store.createIfNotExist();
+ store.open();
+ _store = store;
+ _open = true;
+ }
+
+ @StateTransition( currentState = {State.UNINITIALIZED, State.ERRORED}, desiredState = State.ACTIVE )
private void activate()
{
- try
+ if (_store != null)
{
- _store = new FileSystemPreferencesStore(new File(_path));
- createStoreIfNotExist();
- _store.open();
- _open = true;
setState(State.ACTIVE);
}
- catch( RuntimeException e )
+ else
{
- setState(State.ERRORED);
+ throw new IllegalStateException("Cannot open preferences provider " + getName() + " in state " + getState() );
}
}
@@ -148,9 +192,14 @@ public class FileSystemPreferencesProviderImpl
setState(State.DELETED);
}
- @StateTransition(currentState = { State.QUIESCED, State.ERRORED }, desiredState = State.ACTIVE )
+ @StateTransition(currentState = State.QUIESCED, desiredState = State.ACTIVE )
private void restart()
{
+ if (_store == null)
+ {
+ throw new IllegalStateException("Cannot open preferences provider " + getName() + " in state " + getState() );
+ }
+
_store.open();
setState(State.ACTIVE);
}
@@ -158,24 +207,39 @@ public class FileSystemPreferencesProviderImpl
@Override
public Map<String, Object> getPreferences(String userId)
{
- return _store.getPreferences(userId);
+ return _store == null? Collections.<String, Object>emptyMap() : _store.getPreferences(userId);
}
@Override
public Map<String, Object> setPreferences(String userId, Map<String, Object> preferences)
{
+ if (_store == null)
+ {
+ throw new IllegalStateException("Cannot set preferences with preferences provider " + getName() + " in state " + getState() );
+ }
+
return _store.setPreferences(userId, preferences);
}
@Override
public String[] deletePreferences(String... userIDs)
{
+ if (_store == null)
+ {
+ throw new IllegalStateException("Cannot delete preferences with preferences provider " + getName() + " in state " + getState() );
+ }
+
return _store.deletePreferences(userIDs);
}
@Override
public Set<String> listUserIDs()
{
+ if (_store == null)
+ {
+ return Collections.emptySet();
+ }
+
return _store.listUserIDs();
}
@@ -215,9 +279,10 @@ public class FileSystemPreferencesProviderImpl
}
else
{
- _store = new FileSystemPreferencesStore(new File(_path));
- createStoreIfNotExist();
- _store.open();
+ FileSystemPreferencesStore store = new FileSystemPreferencesStore(new File(_path));
+ store.createIfNotExist();
+ store.open();
+ _store = store;
}
}
}
@@ -265,11 +330,6 @@ public class FileSystemPreferencesProviderImpl
}
- private void createStoreIfNotExist()
- {
- _store.createIfNotExist();
- }
-
public static class FileSystemPreferencesStore
{
private final ObjectMapper _objectMapper;
@@ -294,18 +354,18 @@ public class FileSystemPreferencesProviderImpl
File parent = _storeFile.getParentFile();
if (!parent.exists() && !parent.mkdirs())
{
- throw new IllegalConfigurationException("Cannot create preferences store folders");
+ throw new IllegalConfigurationException(String.format("Cannot create preferences store folder at '%s'", _storeFile.getAbsolutePath()));
}
try
{
if (_storeFile.createNewFile() && !_storeFile.exists())
{
- throw new IllegalConfigurationException("Preferences store file was not created:" + _storeFile.getAbsolutePath());
+ throw new IllegalConfigurationException(String.format("Cannot create preferences store file at '%s'", _storeFile.getAbsolutePath()));
}
}
catch (IOException e)
{
- throw new IllegalConfigurationException("Cannot create preferences store file");
+ throw new IllegalConfigurationException(String.format("Cannot create preferences store file at '%s'", _storeFile.getAbsolutePath()), e);
}
}
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
index c0aa99a7d6..e2e7eff322 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
@@ -317,7 +317,7 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo
setState(State.DELETED);
}
- @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED}, desiredState = State.ACTIVE )
+ @StateTransition( currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE )
protected void activate()
{
try
@@ -327,8 +327,7 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo
catch (RuntimeException e)
{
setState(State.ERRORED);
- LOGGER.error("Unable to active port '" + getName() + "'of type " + getType() + " on port " + getPort(),
- e);
+ throw new IllegalConfigurationException("Unable to active port '" + getName() + "'of type " + getType() + " on " + getPort(), e);
}
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
index fe7d419c78..afe3c9a44e 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
@@ -34,6 +34,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
+import org.apache.qpid.server.util.PortUtil;
import org.codehaus.jackson.map.ObjectMapper;
import org.apache.qpid.server.configuration.BrokerProperties;
@@ -187,6 +188,18 @@ public class AmqpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider<
}
}
+ @Override
+ public void validateOnCreate()
+ {
+ super.validateOnCreate();
+ String bindingAddress = getBindingAddress();
+ if (!PortUtil.isPortAvailable(bindingAddress, getPort()))
+ {
+ throw new IllegalConfigurationException(String.format("Cannot bind to port %d and binding address '%s'. Port is already is use.",
+ getPort(), bindingAddress == null || "".equals(bindingAddress) ? "*" : bindingAddress));
+ }
+ }
+
private SSLContext createSslContext()
{
KeyStore keyStore = getKeyStore();
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
index 1774f16ab6..3be5854645 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
@@ -22,10 +22,12 @@ package org.apache.qpid.server.model.port;
import java.util.Map;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.util.PortUtil;
public class HttpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider<HttpPortImpl> implements HttpPort<HttpPortImpl>
{
@@ -65,4 +67,16 @@ public class HttpPortImpl extends AbstractClientAuthCapablePortWithAuthProvider<
return State.QUIESCED;
}
}
+
+ @Override
+ public void validateOnCreate()
+ {
+ super.validateOnCreate();
+ String bindingAddress = getBindingAddress();
+ if (!PortUtil.isPortAvailable(bindingAddress, getPort()))
+ {
+ throw new IllegalConfigurationException(String.format("Cannot bind to port %d and binding address '%s'. Port is already is use.",
+ getPort(), bindingAddress == null || "".equals(bindingAddress) ? "*" : bindingAddress));
+ }
+ }
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
index 9162f9e095..885194d939 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/plugin/SystemConfigFactory.java
@@ -24,6 +24,7 @@ import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.SystemConfig;
public interface SystemConfigFactory<X extends SystemConfig<X>> extends Pluggable
@@ -31,5 +32,6 @@ public interface SystemConfigFactory<X extends SystemConfig<X>> extends Pluggabl
public X newInstance(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions);
+ final BrokerOptions brokerOptions,
+ final BrokerShutdownProvider brokerShutdownProvider);
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
index a5156c9073..53e446ba2d 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
@@ -254,6 +254,12 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>>
}
@Override
+ protected void validateOnCreate()
+ {
+ _virtualHost.getSecurityManager().authoriseCreateQueue(this);
+ }
+
+ @Override
protected void onCreate()
{
super.onCreate();
@@ -304,6 +310,7 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>>
}
}
+ @Override
protected void onOpen()
{
super.onOpen();
@@ -319,17 +326,6 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>>
_logSubject = new QueueLogSubject(this);
- try
- {
-
- _virtualHost.getSecurityManager().authoriseCreateQueue(this);
- }
- catch(AccessControlException e)
- {
- deleted();
- throw e;
- }
-
Subject activeSubject = Subject.getSubject(AccessController.getContext());
Set<SessionPrincipal> sessionPrincipals = activeSubject == null ? Collections.<SessionPrincipal>emptySet() : activeSubject.getPrincipals(SessionPrincipal.class);
AMQSessionModel<?,?> sessionModel;
@@ -2798,7 +2794,7 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>>
//=============
- @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+ @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
private void activate()
{
setState(State.ACTIVE);
@@ -2965,7 +2961,10 @@ public abstract class AbstractQueue<X extends AbstractQueue<X>>
{
throw new IllegalConfigurationException("Flow resume size can't be greater than flow control size");
}
-
+ else if (changedAttributes.contains(DURABLE) && proxyForValidation.isDurable() != isDurable())
+ {
+ throw new IllegalConfigurationException("Message durability cannot be modified after queue creation");
+ }
for (String attrName : NON_NEGATIVE_NUMBERS)
{
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
index a6a2ea8d34..192a096d12 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java
@@ -76,25 +76,32 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal
}
@Override
+ protected void validateOnCreate()
+ {
+ super.validateOnCreate();
+ File passwordFile = new File(_path);
+ if (passwordFile.exists() && !passwordFile.canRead())
+ {
+ throw new IllegalConfigurationException(String.format("Cannot read password file '%s'. Please check permissions.", _path));
+ }
+ }
+
+ @Override
protected void onCreate()
{
super.onCreate();
- try
+ File passwordFile = new File(_path);
+ if (!passwordFile.exists())
{
- File passwordFile = new File(_path);
- if (!passwordFile.exists())
+ try
{
passwordFile.createNewFile();
}
- else if (!passwordFile.canRead())
+ catch (IOException e)
{
- throw new IllegalConfigurationException("Cannot read password file" + _path + ". Check permissions.");
+ throw new IllegalConfigurationException(String.format("Cannot create password file at '%s'", _path), e);
}
}
- catch (IOException e)
- {
- throw new IllegalConfigurationException("Cannot use password database at :" + _path, e);
- }
}
@Override
@@ -102,23 +109,14 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal
{
super.onOpen();
_principalDatabase = createDatabase();
- try
+ initialise();
+ List<Principal> users = _principalDatabase == null ? Collections.<Principal>emptyList() : _principalDatabase.getUsers();
+ for (Principal user : users)
{
- initialise();
- List<Principal> users =
- _principalDatabase == null ? Collections.<Principal>emptyList() : _principalDatabase.getUsers();
- for (Principal user : users)
- {
- PrincipalAdapter principalAdapter = new PrincipalAdapter(user);
- principalAdapter.registerWithParents();
- principalAdapter.open();
- _userMap.put(user, principalAdapter);
- }
- }
- catch(IllegalConfigurationException e)
- {
- setState(State.ERRORED);
-
+ PrincipalAdapter principalAdapter = new PrincipalAdapter(user);
+ principalAdapter.registerWithParents();
+ principalAdapter.open();
+ _userMap.put(user, principalAdapter);
}
}
@@ -457,7 +455,7 @@ public abstract class PrincipalDatabaseAuthenticationManager<T extends Principal
return super.changeAttribute(name, expected, desired);
}
- @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+ @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
private void activate()
{
setState(State.ACTIVE);
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
index 4e285df384..260fdfd1c6 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.security.auth.manager;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedContextDefault;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.TrustStore;
@@ -29,24 +30,34 @@ import org.apache.qpid.server.model.TrustStore;
public interface SimpleLDAPAuthenticationManager<X extends SimpleLDAPAuthenticationManager<X>> extends AuthenticationProvider<X>
{
String PROVIDER_TYPE = "SimpleLDAP";
+ String PROVIDER_URL = "providerUrl";
+ String PROVIDER_AUTH_URL = "providerAuthUrl";
+ String SEARCH_CONTEXT = "searchContext";
+ String LDAP_CONTEXT_FACTORY = "ldapContextFactory";
+ String SEARCH_USERNAME = "getSearchUsername";
+ String SEARCH_PASSWORD = "getSearchPassword";
String TRUST_STORE = "trustStore";
- @ManagedAttribute( description = "LDAP server URL" )
+
+ @ManagedAttribute( description = "LDAP server URL", mandatory = true)
String getProviderUrl();
@ManagedAttribute( description = "LDAP authentication URL")
String getProviderAuthUrl();
- @ManagedAttribute( description = "Search context")
+ @ManagedAttribute( description = "Search context", mandatory = true)
String getSearchContext();
- @ManagedAttribute( description = "Search filter")
+ @ManagedAttribute( description = "Search filter", mandatory = true)
String getSearchFilter();
@ManagedAttribute( description = "Bind without search")
boolean isBindWithoutSearch();
- @ManagedAttribute( description = "LDAP context factory")
+ @ManagedContextDefault( name = "ldap.context.factory")
+ String DEFAULT_LDAP_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
+
+ @ManagedAttribute( description = "LDAP context factory", defaultValue = "${ldap.context.factory}")
String getLdapContextFactory();
@ManagedAttribute( description = "Trust store name")
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
index a0ba4518c8..6a0b83eb94 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerImpl.java
@@ -19,15 +19,18 @@
package org.apache.qpid.server.security.auth.manager;
+import static java.util.Collections.disjoint;
+import static java.util.Collections.unmodifiableList;
+import static java.util.Collections.singletonList;
+
import java.io.IOException;
import java.security.GeneralSecurityException;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
import java.security.Principal;
-import java.util.Collections;
+import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import javax.naming.AuthenticationException;
import javax.naming.Context;
@@ -48,7 +51,9 @@ import javax.security.sasl.SaslServer;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
import org.apache.qpid.server.model.TrustStore;
@@ -59,7 +64,6 @@ import org.apache.qpid.server.security.auth.manager.ldap.AbstractLDAPSSLSocketFa
import org.apache.qpid.server.security.auth.manager.ldap.LDAPSSLSocketFactoryGenerator;
import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback;
import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer;
-import org.apache.qpid.server.util.ServerScopedRuntimeException;
import org.apache.qpid.server.util.StringUtil;
import org.apache.qpid.ssl.SSLContextFactory;
@@ -68,6 +72,14 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
{
private static final Logger _logger = Logger.getLogger(SimpleLDAPAuthenticationManagerImpl.class);
+ private static final List<String> CONNECTIVITY_ATTRS = unmodifiableList(Arrays.asList(PROVIDER_URL,
+ PROVIDER_AUTH_URL,
+ SEARCH_CONTEXT,
+ LDAP_CONTEXT_FACTORY,
+ SEARCH_USERNAME,
+ SEARCH_PASSWORD,
+ TRUST_STORE));
+
/**
* Environment key to instruct {@link InitialDirContext} to override the socket factory.
*/
@@ -111,15 +123,37 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
super(attributes, broker);
}
+ @Override
+ protected void validateOnCreate()
+ {
+ super.validateOnCreate();
+
+ Class<? extends SocketFactory> sslSocketFactoryOverrideClass = _trustStore == null ? null : createSslSocketFactoryOverrideClass(_trustStore);
+ validateInitialDirContext(sslSocketFactoryOverrideClass, _providerUrl, _searchUsername, _searchPassword);
+ }
+
+ @Override
+ protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes)
+ {
+ super.validateChange(proxyForValidation, changedAttributes);
+
+ if (!disjoint(changedAttributes, CONNECTIVITY_ATTRS))
+ {
+ SimpleLDAPAuthenticationManager changed = (SimpleLDAPAuthenticationManager)proxyForValidation;
+ TrustStore changedTruststore = changed.getTrustStore();
+ Class<? extends SocketFactory> sslSocketFactoryOverrideClass = changedTruststore == null ? null : createSslSocketFactoryOverrideClass(
+ changedTruststore);
+ validateInitialDirContext(sslSocketFactoryOverrideClass, changed.getProviderUrl(), changed.getSearchUsername(),
+ changed.getSearchPassword());
+ }
+ }
@Override
protected void onOpen()
{
super.onOpen();
- _sslSocketFactoryOverrideClass = createSslSocketFactoryOverrideClass();
-
- // validateInitialDirContext();
+ _sslSocketFactoryOverrideClass = _trustStore == null ? null : createSslSocketFactoryOverrideClass(_trustStore);
}
@Override
@@ -174,7 +208,7 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
@Override
public List<String> getMechanisms()
{
- return Collections.singletonList(PlainSaslServer.MECHANISM);
+ return singletonList(PlainSaslServer.MECHANISM);
}
@Override
@@ -259,7 +293,7 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
InitialDirContext ctx = null;
try
{
- ctx = createInitialDirContext(env);
+ ctx = createInitialDirContext(env, _sslSocketFactoryOverrideClass);
//Authentication succeeded
return new AuthenticationResult(new UsernamePrincipal(name));
@@ -291,7 +325,8 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
return env;
}
- private InitialDirContext createInitialDirContext(Hashtable<String, Object> env) throws NamingException
+ private InitialDirContext createInitialDirContext(Hashtable<String, Object> env,
+ Class<? extends SocketFactory> sslSocketFactoryOverrideClass) throws NamingException
{
ClassLoader existingContextClassLoader = null;
@@ -300,11 +335,11 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
boolean revertContentClassLoader = false;
try
{
- if (isLdaps && _sslSocketFactoryOverrideClass != null)
+ if (isLdaps && sslSocketFactoryOverrideClass != null)
{
existingContextClassLoader = Thread.currentThread().getContextClassLoader();
- env.put(JAVA_NAMING_LDAP_FACTORY_SOCKET, _sslSocketFactoryOverrideClass.getName());
- Thread.currentThread().setContextClassLoader(_sslSocketFactoryOverrideClass.getClassLoader());
+ env.put(JAVA_NAMING_LDAP_FACTORY_SOCKET, sslSocketFactoryOverrideClass.getName());
+ Thread.currentThread().setContextClassLoader(sslSocketFactoryOverrideClass.getClassLoader());
revertContentClassLoader = true;
}
return new InitialDirContext(env);
@@ -323,59 +358,59 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
* associated with the {@link SSLContext} generated from that trust store.
*
* @return generated socket factory class
+ * @param trustStore
*/
- private Class<? extends SocketFactory> createSslSocketFactoryOverrideClass()
+ private Class<? extends SocketFactory> createSslSocketFactoryOverrideClass(final TrustStore trustStore)
{
- if (_trustStore != null)
+ String clazzName = new StringUtil().createUniqueJavaName(getName() + "_" + trustStore.getName());
+ SSLContext sslContext = null;
+ try
{
- String clazzName = new StringUtil().createUniqueJavaName(getName());
- SSLContext sslContext = null;
- try
- {
- sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, _trustStore.getTrustManagers(), null);
- }
- catch (NoSuchAlgorithmException e)
- {
- _logger.error("Exception creating SSLContext", e);
- throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e);
- }
- catch (KeyManagementException e)
- {
- _logger.error("Exception creating SSLContext", e);
- throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e);
- }
- catch (GeneralSecurityException e)
- {
- _logger.error("Exception creating SSLContext", e);
- throw new ServerScopedRuntimeException("Error creating SSLContext for trust store : " + _trustStore.getName() , e);
- }
+ sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(null, trustStore.getTrustManagers(), null);
+ }
+ catch (GeneralSecurityException e)
+ {
+ _logger.error("Exception creating SSLContext", e);
+ throw new IllegalConfigurationException("Error creating SSLContext with trust store : " + trustStore.getName() , e);
+ }
- Class<? extends AbstractLDAPSSLSocketFactory> clazz = LDAPSSLSocketFactoryGenerator.createSubClass(clazzName, sslContext.getSocketFactory());
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Connection to Directory will use custom SSL socket factory : " + clazz);
- }
- return clazz;
+ Class<? extends AbstractLDAPSSLSocketFactory> clazz = LDAPSSLSocketFactoryGenerator.createSubClass(clazzName, sslContext.getSocketFactory());
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Connection to Directory will use custom SSL socket factory : " + clazz);
}
+ return clazz;
+ }
- return null;
+ @Override
+ public String toString()
+ {
+ return "SimpleLDAPAuthenticationManagerImpl [id=" + getId() + ", name=" + getName() +
+ ", providerUrl=" + _providerUrl + ", providerAuthUrl=" + _providerAuthUrl +
+ ", searchContext=" + _searchContext + ", state=" + getState() +
+ ", searchFilter=" + _searchFilter + ", ldapContextFactory=" + _ldapContextFactory +
+ ", bindWithoutSearch=" + _bindWithoutSearch + ", trustStore=" + _trustStore +
+ ", searchUsername=" + _searchUsername + "]";
}
- private void validateInitialDirContext()
+ private void validateInitialDirContext(Class<? extends SocketFactory> sslSocketFactoryOverrideClass,
+ final String providerUrl,
+ final String searchUsername, final String searchPassword)
{
- Hashtable<String,Object> env = createInitialDirContextEnvironment(_providerUrl);
+ Hashtable<String,Object> env = createInitialDirContextEnvironment(providerUrl);
- setupSearchContext(env);
+ setupSearchContext(env, searchUsername, searchPassword);
InitialDirContext ctx = null;
try
{
- ctx = createInitialDirContext(env);
+ ctx = createInitialDirContext(env, sslSocketFactoryOverrideClass);
}
catch (NamingException e)
{
- throw new ServerScopedRuntimeException("Unable to establish connection to the ldap server at " + _providerUrl, e);
+ _logger.error("Failed to establish connectivity to the ldap server for " + providerUrl, e);
+ throw new IllegalConfigurationException("Failed to establish connectivity to the ldap server." , e);
}
finally
{
@@ -383,13 +418,14 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
}
}
- private void setupSearchContext(final Hashtable<String, Object> env)
+ private void setupSearchContext(final Hashtable<String, Object> env,
+ final String searchUsername, final String searchPassword)
{
if(_searchUsername != null && _searchUsername.trim().length()>0)
{
env.put(Context.SECURITY_AUTHENTICATION, "simple");
- env.put(Context.SECURITY_PRINCIPAL, _searchUsername);
- env.put(Context.SECURITY_CREDENTIALS, _searchPassword);
+ env.put(Context.SECURITY_PRINCIPAL, searchUsername);
+ env.put(Context.SECURITY_CREDENTIALS, searchPassword);
}
else
{
@@ -454,9 +490,9 @@ public class SimpleLDAPAuthenticationManagerImpl extends AbstractAuthenticationM
{
Hashtable<String, Object> env = createInitialDirContextEnvironment(_providerUrl);
- setupSearchContext(env);
+ setupSearchContext(env, _searchUsername, _searchPassword);
- InitialDirContext ctx = createInitialDirContext(env);
+ InitialDirContext ctx = createInitialDirContext(env, _sslSocketFactoryOverrideClass);
try
{
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java
index 52072678e8..4fbfdfdd2d 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCConfigurationStore.java
@@ -572,7 +572,7 @@ public abstract class AbstractJDBCConfigurationStore implements MessageStoreProv
}
catch (SQLException e)
{
- throw new StoreException("Error creating ConfiguredObject " + object);
+ throw new StoreException("Error creating ConfiguredObject " + object, e);
}
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
index 9633e32408..4dfaa716cf 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
@@ -133,7 +133,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore
}
catch (SQLException e)
{
- throw new StoreException(e);
+ throw new StoreException("Failed to determine maximum ids", e);
}
}
@@ -816,7 +816,6 @@ public abstract class AbstractJDBCMessageStore implements MessageStore
private void commitTran(ConnectionWrapper connWrapper) throws StoreException
{
-
try
{
Connection conn = connWrapper.getConnection();
@@ -833,10 +832,6 @@ public abstract class AbstractJDBCMessageStore implements MessageStore
{
throw new StoreException("Error commit tx: " + e.getMessage(), e);
}
- finally
- {
-
- }
}
private StoreFuture commitTranAsync(ConnectionWrapper connWrapper) throws StoreException
@@ -1448,7 +1443,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore
}
catch (SQLException e)
{
- throw new StoreException(e);
+ throw new StoreException("Failed to get metadata for message id: " + _messageId, e);
}
}
@@ -1507,7 +1502,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore
}
catch (SQLException e)
{
- throw new StoreException(e);
+ throw new StoreException("Failed to get content for message id " + _messageId, e);
}
}
else
@@ -1551,7 +1546,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore
}
catch (SQLException e)
{
- throw new StoreException(e);
+ throw new StoreException("Failed to get content for message id: " + _messageId, e);
}
}
else
@@ -1598,11 +1593,7 @@ public abstract class AbstractJDBCMessageStore implements MessageStore
}
catch (SQLException e)
{
- throw new StoreException(e);
- }
- finally
- {
-
+ throw new StoreException("Failed to flow to disk", e);
}
return true;
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java b/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.java
new file mode 100644
index 0000000000..5d093bd3d5
--- /dev/null
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/util/PortUtil.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.util;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+
+public class PortUtil
+{
+ public static boolean isPortAvailable(String hostName, int port)
+ {
+ InetSocketAddress socketAddress = null;
+ if ( hostName == null || "".equals(hostName) || "*".equals(hostName) )
+ {
+ socketAddress = new InetSocketAddress(port);
+ }
+ else
+ {
+ socketAddress = new InetSocketAddress(hostName, port);
+ }
+
+ ServerSocket serverSocket = null;
+ try
+ {
+ serverSocket = new ServerSocket();
+ serverSocket.setReuseAddress(true);
+ serverSocket.bind(socketAddress);
+ return true;
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ finally
+ {
+ if (serverSocket != null)
+ {
+ try
+ {
+ serverSocket.close();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Couldn't close port " + port + " that was created to check its availability", e);
+ }
+ }
+ }
+ }
+}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index f52c1967f8..48077ba503 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -37,7 +37,6 @@ import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
import javax.security.auth.Subject;
@@ -231,6 +230,47 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte
}
@Override
+ public void validateOnCreate()
+ {
+ super.validateOnCreate();
+ validateMessageStoreCreation();
+ }
+
+ private void validateMessageStoreCreation()
+ {
+ MessageStore store = createMessageStore();
+ if (store != null)
+ {
+ try
+ {
+ store.openMessageStore(this);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalConfigurationException("Cannot open virtual host message store:" + e.getMessage(), e);
+ }
+ finally
+ {
+ try
+ {
+ store.closeMessageStore();
+ }
+ catch(Exception e)
+ {
+ _logger.warn("Failed to close database", e);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected void onExceptionInOpen(RuntimeException e)
+ {
+ super.onExceptionInOpen(e);
+ closeMessageStore();
+ }
+
+ @Override
protected void onOpen()
{
super.onOpen();
@@ -638,6 +678,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte
protected void onClose()
{
+ setState(State.UNAVAILABLE);
//Stop Connections
_connectionRegistry.close();
_dtxRegistry.close();
@@ -659,11 +700,11 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte
{
_logger.error("Failed to close message store", e);
}
- }
- if (!(_virtualHostNode.getConfigurationStore() instanceof MessageStoreProvider))
- {
- getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CLOSED());
+ if (!(_virtualHostNode.getConfigurationStore() instanceof MessageStoreProvider))
+ {
+ getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CLOSED());
+ }
}
}
@@ -1355,7 +1396,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte
getDurableConfigurationStore().create(new ConfiguredObjectRecordImpl(record.getId(), record.getType(), record.getAttributes()));
}
- @StateTransition( currentState = { State.UNINITIALIZED }, desiredState = State.ACTIVE )
+ @StateTransition( currentState = { State.UNINITIALIZED,State.ERRORED }, desiredState = State.ACTIVE )
private void onActivate()
{
_houseKeepingTasks = new ScheduledThreadPoolExecutor(getHousekeepingThreadCount());
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
index ce97502124..03c30a9cd4 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
@@ -41,6 +41,7 @@ import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
+import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer;
public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandardVirtualHostNode<X>> extends AbstractVirtualHostNode<X>
@@ -169,4 +170,33 @@ public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandard
{
return Collections.emptyList();
}
+
+ @Override
+ public void validateOnCreate()
+ {
+ super.validateOnCreate();
+ DurableConfigurationStore store = createConfigurationStore();
+ if (store != null)
+ {
+ try
+ {
+ store.openConfigurationStore(this, false);
+ }
+ catch (Exception e)
+ {
+ throw new IllegalConfigurationException("Cannot open node configuration store:" + e.getMessage(), e);
+ }
+ finally
+ {
+ try
+ {
+ store.closeConfigurationStore();
+ }
+ catch(Exception e)
+ {
+ LOGGER.warn("Failed to close database", e);
+ }
+ }
+ }
+ }
}
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
index 5cbfb0942a..aea07e3ed3 100644
--- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
+++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
@@ -36,7 +36,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import java.util.concurrent.atomic.AtomicReference;
import org.apache.log4j.Logger;
@@ -100,8 +99,6 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<
{
super.onOpen();
_durableConfigurationStore = createConfigurationStore();
- _configurationStoreLogSubject = new MessageStoreLogSubject(getName(), _durableConfigurationStore.getClass().getSimpleName());
-
}
@Override
@@ -167,11 +164,6 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<
return _eventLogger;
}
- protected DurableConfigurationStore getDurableConfigurationStore()
- {
- return _durableConfigurationStore;
- }
-
protected MessageStoreLogSubject getConfigurationStoreLogSubject()
{
return _configurationStoreLogSubject;
@@ -184,7 +176,11 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<
deleteVirtualHostIfExists();
close();
deleted();
- getConfigurationStore().onDelete(this);
+ DurableConfigurationStore configurationStore = getConfigurationStore();
+ if (configurationStore != null)
+ {
+ configurationStore.onDelete(this);
+ }
}
protected void deleteVirtualHostIfExists()
@@ -205,11 +201,30 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<
protected void stopAndSetStateTo(State stoppedState)
{
closeChildren();
- closeConfigurationStore();
+ closeConfigurationStoreSafely();
setState(stoppedState);
}
@Override
+ protected void onExceptionInOpen(RuntimeException e)
+ {
+ super.onExceptionInOpen(e);
+ closeConfigurationStoreSafely();
+ }
+
+ @Override
+ protected void postResolve()
+ {
+ super.postResolve();
+ DurableConfigurationStore store = getConfigurationStore();
+ if (store == null)
+ {
+ store = createConfigurationStore();
+ }
+ _configurationStoreLogSubject = new MessageStoreLogSubject(getName(), store.getClass().getSimpleName());
+ }
+
+ @Override
protected void onClose()
{
closeConfigurationStore();
@@ -262,6 +277,18 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<
}
}
+ private void closeConfigurationStoreSafely()
+ {
+ try
+ {
+ closeConfigurationStore();
+ }
+ catch(Exception e)
+ {
+ LOGGER.warn("Unexpected exception on close of configuration store", e);
+ }
+ }
+
@Override
public String getVirtualHostInitialConfiguration()
{
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/binding/BindingImplTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/binding/BindingImplTest.java
new file mode 100644
index 0000000000..93fa9114fb
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/binding/BindingImplTest.java
@@ -0,0 +1,76 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.binding;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.common.AMQPFilterTypes;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class BindingImplTest extends QpidTestCase
+{
+ private TaskExecutor _taskExecutor;
+ private Model _model;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+ _model = BrokerModel.getInstance();
+ }
+
+ public void testBindingValidationOnCreateWithInvalidSelector()
+ {
+ Map<String, String> arguments = new HashMap<>();
+ arguments.put(AMQPFilterTypes.JMS_SELECTOR.toString(), "test in (");
+ Map<String,Object> attributes = new HashMap<>();
+ attributes.put(Binding.ARGUMENTS, arguments);
+ attributes.put(Binding.NAME, getTestName());
+ AMQQueue queue = mock(AMQQueue.class);
+ when(queue.getTaskExecutor()).thenReturn(_taskExecutor);
+ when(queue.getModel()).thenReturn(_model);
+ ExchangeImpl exchange = mock(ExchangeImpl.class);
+ when(exchange.getTaskExecutor()).thenReturn(_taskExecutor);
+ when(exchange.getModel()).thenReturn(_model);
+ BindingImpl binding = new BindingImpl(attributes, queue, exchange);
+ try
+ {
+ binding.create();
+ fail("Exception is expected on validation with invalid selector");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertTrue("Unexpected exception message " + e.getMessage(), e.getMessage().startsWith("Cannot parse JMS selector"));
+ }
+ }
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java
index 4b4891d838..b4f92990eb 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/FileKeyStoreCreationTest.java
@@ -63,7 +63,7 @@ public class FileKeyStoreCreationTest extends TestCase
Map<String, Object> attributesCopy = new HashMap<String, Object>(attributes);
Broker broker = mock(Broker.class);
- TaskExecutor executor = new CurrentThreadTaskExecutor();
+ TaskExecutor executor = CurrentThreadTaskExecutor.newStartedInstance();
when(broker.getObjectFactory()).thenReturn(_factory);
when(broker.getModel()).thenReturn(_factory.getModel());
when(broker.getTaskExecutor()).thenReturn(executor);
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
index 36353f0dba..fbb08cdd2a 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ManagementModeStoreHandlerTest.java
@@ -34,6 +34,7 @@ import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.mockito.ArgumentCaptor;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -78,7 +79,8 @@ public class ManagementModeStoreHandlerTest extends QpidTestCase
_taskExecutor.start();
_systemConfig = new JsonSystemConfigImpl(_taskExecutor, mock(EventLogger.class),
- mock(LogRecorder.class), new BrokerOptions());
+ mock(LogRecorder.class), new BrokerOptions(),
+ mock(BrokerShutdownProvider.class));
ConfiguredObjectRecord systemContextRecord = _systemConfig.asObjectRecord();
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
index e5c5a89c10..a1a363d5fe 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
@@ -26,7 +26,9 @@ import java.util.Map;
import junit.framework.TestCase;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.testmodel.TestChildCategory;
+import org.apache.qpid.server.model.testmodel.TestConfiguredObject;
import org.apache.qpid.server.model.testmodel.TestModel;
import org.apache.qpid.server.model.testmodel.TestRootCategory;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
@@ -257,4 +259,189 @@ public class AbstractConfiguredObjectTest extends TestCase
parent.getChildren(TestChildCategory.class).isEmpty());
}
+ public void testOpeningResultsInErroredStateWhenResolutionFails() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnPostResolve(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.setThrowExceptionOnPostResolve(false);
+ object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
+ assertTrue("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ACTIVE, object.getState());
+ }
+
+ public void testOpeningInERROREDStateAfterFailedOpenOnDesiredStateChangeToActive() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.setThrowExceptionOnOpen(false);
+ object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.ACTIVE));
+ assertTrue("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ACTIVE, object.getState());
+ }
+
+ public void testOpeningInERROREDStateAfterFailedOpenOnStart() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.setThrowExceptionOnOpen(false);
+ object.start();
+ assertTrue("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ACTIVE, object.getState());
+ }
+
+ public void testDeletionERROREDStateAfterFailedOpenOnDelete() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.delete();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.DELETED, object.getState());
+ }
+
+ public void testDeletionInERROREDStateAfterFailedOpenOnDesiredStateChangeToDelete() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ object.open();
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ERRORED, object.getState());
+
+ object.setAttributes(Collections.<String, Object>singletonMap(Port.DESIRED_STATE, State.DELETED));
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.DELETED, object.getState());
+ }
+
+
+ public void testCreationWithExceptionThrownFromValidationOnCreate() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnValidationOnCreate(true);
+ try
+ {
+ object.create();
+ fail("IllegalConfigurationException is expected to be thrown");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ //pass
+ }
+ assertFalse("Unexpected opened", object.isOpened());
+ }
+
+ public void testCreationWithoutExceptionThrownFromValidationOnCreate() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnValidationOnCreate(false);
+ object.create();
+ assertTrue("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.ACTIVE, object.getState());
+ }
+
+ public void testCreationWithExceptionThrownFromOnOpen() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnOpen(true);
+ try
+ {
+ object.create();
+ fail("Exception should have been re-thrown");
+ }
+ catch (RuntimeException re)
+ {
+ // pass
+ }
+
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.DELETED, object.getState());
+ }
+
+ public void testCreationWithExceptionThrownFromOnCreate() throws Exception
+ {
+ TestConfiguredObject object = new TestConfiguredObject(getName());
+ object.setThrowExceptionOnCreate(true);
+ try
+ {
+ object.create();
+ fail("Exception should have been re-thrown");
+ }
+ catch (RuntimeException re)
+ {
+ // pass
+ }
+
+ assertFalse("Unexpected opened", object.isOpened());
+ assertEquals("Unexpected state", State.DELETED, object.getState());
+ }
+
+ public void testUnresolvedChildInERROREDStateIsNotValidatedOrOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
+ {
+ TestConfiguredObject parent = new TestConfiguredObject("parent");
+ TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
+ child1.registerWithParents();
+ TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
+ child2.registerWithParents();
+
+ child1.setThrowExceptionOnPostResolve(true);
+
+ parent.open();
+
+ assertTrue("Parent should be resolved", parent.isResolved());
+ assertTrue("Parent should be validated", parent.isValidated());
+ assertTrue("Parent should be opened", parent.isOpened());
+ assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());
+
+ assertTrue("Child2 should be resolved", child2.isResolved());
+ assertTrue("Child2 should be validated", child2.isValidated());
+ assertTrue("Child2 should be opened", child2.isOpened());
+ assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());
+
+ assertFalse("Child2 should not be resolved", child1.isResolved());
+ assertFalse("Child1 should not be validated", child1.isValidated());
+ assertFalse("Child1 should not be opened", child1.isOpened());
+ assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
+ }
+
+ public void testUnvalidatedChildInERROREDStateIsNotOpenedOrAttainedDesiredStateOnParentOpen() throws Exception
+ {
+ TestConfiguredObject parent = new TestConfiguredObject("parent");
+ TestConfiguredObject child1 = new TestConfiguredObject("child1", parent, parent.getTaskExecutor());
+ child1.registerWithParents();
+ TestConfiguredObject child2 = new TestConfiguredObject("child2", parent, parent.getTaskExecutor());
+ child2.registerWithParents();
+
+ child1.setThrowExceptionOnValidate(true);
+
+ parent.open();
+
+ assertTrue("Parent should be resolved", parent.isResolved());
+ assertTrue("Parent should be validated", parent.isValidated());
+ assertTrue("Parent should be opened", parent.isOpened());
+ assertEquals("Unexpected parent state", State.ACTIVE, parent.getState());
+
+ assertTrue("Child2 should be resolved", child2.isResolved());
+ assertTrue("Child2 should be validated", child2.isValidated());
+ assertTrue("Child2 should be opened", child2.isOpened());
+ assertEquals("Unexpected child2 state", State.ACTIVE, child2.getState());
+
+ assertTrue("Child1 should be resolved", child1.isResolved());
+ assertFalse("Child1 should not be validated", child1.isValidated());
+ assertFalse("Child1 should not be opened", child1.isOpened());
+ assertEquals("Unexpected child1 state", State.ERRORED, child1.getState());
+ }
}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
index db5cf1a7ba..ba6b0d95f3 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java
@@ -65,6 +65,7 @@ public class VirtualHostTest extends QpidTestCase
private TaskExecutor _taskExecutor;
private VirtualHostNode<?> _virtualHostNode;
private DurableConfigurationStore _configStore;
+ private VirtualHost<?, ?, ?> _virtualHost;
@Override
protected void setUp() throws Exception
@@ -94,7 +95,17 @@ public class VirtualHostTest extends QpidTestCase
{
try
{
- _taskExecutor.stopImmediately();
+ try
+ {
+ _taskExecutor.stopImmediately();
+ }
+ finally
+ {
+ if (_virtualHost != null)
+ {
+ _virtualHost.close();
+ }
+ }
}
finally
{
@@ -386,6 +397,7 @@ public class VirtualHostTest extends QpidTestCase
TestMemoryVirtualHost host = new TestMemoryVirtualHost(attributes, _virtualHostNode);
host.create();
+ _virtualHost = host;
return host;
}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImplTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImplTest.java
new file mode 100644
index 0000000000..50a4e5a86e
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImplTest.java
@@ -0,0 +1,117 @@
+/*
+ *
+ * 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.adapter;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.apache.qpid.test.utils.TestFileUtils;
+
+public class FileBasedGroupProviderImplTest extends QpidTestCase
+{
+ private TaskExecutor _taskExecutor;
+ private Broker _broker;
+ private File _groupFile;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+
+ _broker = mock(Broker.class);
+ when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+ when(_broker.getModel()).thenReturn(BrokerModel.getInstance());
+ when(_broker.getId()).thenReturn(UUID.randomUUID());
+ when(_broker.getSecurityManager()).thenReturn(new SecurityManager(_broker, false));
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_groupFile.exists())
+ {
+ _groupFile.delete();
+ }
+ _taskExecutor.stop();
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ public void testValidationOnCreateWithInvalidPath()
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ _groupFile = TestFileUtils.createTempFile(this, "groups");
+
+ String groupsFile = _groupFile.getAbsolutePath() + File.separator + "groups";
+ assertFalse("File should not exist", new File(groupsFile).exists());
+ attributes.put(FileBasedGroupProvider.PATH, groupsFile);
+ attributes.put(FileBasedGroupProvider.NAME, getTestName());
+
+ FileBasedGroupProviderImpl groupsProvider = new FileBasedGroupProviderImpl(attributes, _broker);
+ try
+ {
+ groupsProvider.create();
+ fail("Exception is expected on validation of groups provider with invalid path");
+ } catch (IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot create groups file at '%s'", groupsFile), e.getMessage());
+ }
+ }
+
+ public void testValidationOnCreateWithInvalidGroups()
+ {
+ _groupFile = TestFileUtils.createTempFile(this, "groups", "=blah");
+ Map<String, Object> attributes = new HashMap<>();
+ String groupsFile = _groupFile.getAbsolutePath();
+ attributes.put(FileBasedGroupProvider.PATH, groupsFile);
+ attributes.put(FileBasedGroupProvider.NAME, getTestName());
+
+ FileBasedGroupProviderImpl groupsProvider = new FileBasedGroupProviderImpl(attributes, _broker);
+ try
+ {
+ groupsProvider.create();
+ fail("Exception is expected on validation of groups provider with invalid group file");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot load groups from '%s'", groupsFile), e.getMessage());
+ }
+ }
+
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java
index 9bb004e4c2..f532a9325b 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java
@@ -31,6 +31,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.model.AuthenticationProvider;
@@ -109,7 +110,7 @@ public class FileSystemPreferencesProviderTest extends QpidTestCase
attributes.put(ConfiguredObject.ID, UUID.randomUUID());
attributes.put(ConfiguredObject.NAME, getTestName());
_preferencesProvider = new FileSystemPreferencesProviderImpl(attributes, _authenticationProvider);
- _preferencesProvider.open();
+ _preferencesProvider.create();
assertEquals(State.ACTIVE, _preferencesProvider.getState());
assertTrue("Preferences file was not created", nonExistingFile.exists());
@@ -120,6 +121,57 @@ public class FileSystemPreferencesProviderTest extends QpidTestCase
}
}
+ public void testValidationOnCreateForInvalidPath() throws Exception
+ {
+ File file = new File(TMP_FOLDER + File.separator + getTestName() + System.nanoTime() );
+ file.createNewFile();
+ String path = file.getAbsolutePath() + File.separator + "users";
+
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(FileSystemPreferencesProvider.PATH, path);
+ attributes.put(ConfiguredObject.ID, UUID.randomUUID());
+ attributes.put(ConfiguredObject.NAME, getTestName());
+ _preferencesProvider = new FileSystemPreferencesProviderImpl(attributes, _authenticationProvider);
+
+ try
+ {
+
+ _preferencesProvider.create();
+
+ fail("Creation of preferences provider with invalid path should have failed");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot create preferences store file at '%s'", path), e.getMessage());
+ }
+ }
+
+ public void testValidationOnCreateWithInvalidPreferences()
+ {
+ File tmp = TestFileUtils.createTempFile(this, "preferences", "{blah:=boo}");
+ try
+ {
+ Map<String, Object> attributes = new HashMap<String, Object>();
+ attributes.put(FileSystemPreferencesProvider.PATH, tmp.getAbsolutePath());
+ attributes.put(ConfiguredObject.ID, UUID.randomUUID());
+ attributes.put(ConfiguredObject.NAME, getTestName());
+ _preferencesProvider = new FileSystemPreferencesProviderImpl(attributes, _authenticationProvider);
+ try
+ {
+ _preferencesProvider.create();
+ fail("Exception is expected on validation of groups provider with invalid preferences format");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception message:" + e.getMessage(), "Cannot parse preferences json in " + tmp.getName(), e.getMessage());
+ }
+ }
+ finally
+ {
+ tmp.delete();
+ }
+ }
+
public void testConstructionWithEmptyFile() throws Exception
{
File emptyPrefsFile = new File(TMP_FOLDER, "preferences-" + getTestName() + ".json");
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
index 523203c756..642ea06ede 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/adapter/PortFactoryTest.java
@@ -54,7 +54,7 @@ import org.apache.qpid.test.utils.QpidTestCase;
public class PortFactoryTest extends QpidTestCase
{
private UUID _portId = UUID.randomUUID();
- private int _portNumber = 123;
+ private int _portNumber;
private Set<String> _tcpStringSet = Collections.singleton(Transport.TCP.name());
private Set<Transport> _tcpTransports = Collections.singleton(Transport.TCP);
private Set<String> _sslStringSet = Collections.singleton(Transport.SSL.name());
@@ -68,11 +68,13 @@ public class PortFactoryTest extends QpidTestCase
private String _authProviderName = "authProvider";
private AuthenticationProvider _authProvider = mock(AuthenticationProvider.class);
private ConfiguredObjectFactoryImpl _factory;
+ private Port<?> _port;
@Override
protected void setUp() throws Exception
{
+ _portNumber = findFreePort();
TaskExecutor executor = CurrentThreadTaskExecutor.newStartedInstance();
when(_authProvider.getName()).thenReturn(_authProviderName);
when(_broker.getChildren(eq(AuthenticationProvider.class))).thenReturn(Collections.singleton(_authProvider));
@@ -109,30 +111,45 @@ public class PortFactoryTest extends QpidTestCase
_attributes.put(Port.BINDING_ADDRESS, "127.0.0.1");
}
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_port != null)
+ {
+ _port.close();
+ }
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
public void testCreatePortWithMinimumAttributes()
{
Map<String, Object> attributes = new HashMap<String, Object>();
- attributes.put(Port.PORT, 1);
+ attributes.put(Port.PORT, _portNumber);
attributes.put(Port.NAME, getName());
attributes.put(Port.AUTHENTICATION_PROVIDER, _authProviderName);
attributes.put(Port.DESIRED_STATE, State.QUIESCED);
- Port<?> port = _factory.create(Port.class, attributes, _broker);
+ _port = _factory.create(Port.class, attributes, _broker);
- assertNotNull(port);
- assertTrue(port instanceof AmqpPort);
- assertEquals("Unexpected port", 1, port.getPort());
- assertEquals("Unexpected transports", Collections.singleton(PortFactory.DEFAULT_TRANSPORT), port.getTransports());
+ assertNotNull(_port);
+ assertTrue(_port instanceof AmqpPort);
+ assertEquals("Unexpected _port", _portNumber, _port.getPort());
+ assertEquals("Unexpected transports", Collections.singleton(PortFactory.DEFAULT_TRANSPORT), _port.getTransports());
assertEquals("Unexpected send buffer size", PortFactory.DEFAULT_AMQP_SEND_BUFFER_SIZE,
- port.getAttribute(AmqpPort.SEND_BUFFER_SIZE));
+ _port.getAttribute(AmqpPort.SEND_BUFFER_SIZE));
assertEquals("Unexpected receive buffer size", PortFactory.DEFAULT_AMQP_RECEIVE_BUFFER_SIZE,
- port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE));
+ _port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE));
assertEquals("Unexpected need client auth", PortFactory.DEFAULT_AMQP_NEED_CLIENT_AUTH,
- port.getAttribute(Port.NEED_CLIENT_AUTH));
+ _port.getAttribute(Port.NEED_CLIENT_AUTH));
assertEquals("Unexpected want client auth", PortFactory.DEFAULT_AMQP_WANT_CLIENT_AUTH,
- port.getAttribute(Port.WANT_CLIENT_AUTH));
- assertEquals("Unexpected tcp no delay", PortFactory.DEFAULT_AMQP_TCP_NO_DELAY, port.getAttribute(Port.TCP_NO_DELAY));
- assertEquals("Unexpected binding", PortFactory.DEFAULT_AMQP_BINDING, port.getAttribute(Port.BINDING_ADDRESS));
+ _port.getAttribute(Port.WANT_CLIENT_AUTH));
+ assertEquals("Unexpected tcp no delay", PortFactory.DEFAULT_AMQP_TCP_NO_DELAY, _port.getAttribute(Port.TCP_NO_DELAY));
+ assertEquals("Unexpected binding", PortFactory.DEFAULT_AMQP_BINDING, _port.getAttribute(Port.BINDING_ADDRESS));
}
public void testCreateAmqpPort()
@@ -256,27 +273,27 @@ public class PortFactoryTest extends QpidTestCase
_attributes.put(Port.DESIRED_STATE, State.QUIESCED);
- Port<?> port = _factory.create(Port.class, _attributes, _broker);
+ _port = _factory.create(Port.class, _attributes, _broker);
- assertNotNull(port);
- assertTrue(port instanceof AmqpPort);
- assertEquals(_portId, port.getId());
- assertEquals(_portNumber, port.getPort());
+ assertNotNull(_port);
+ assertTrue(_port instanceof AmqpPort);
+ assertEquals(_portId, _port.getId());
+ assertEquals(_portNumber, _port.getPort());
if(useSslTransport)
{
- assertEquals(_sslTransports, port.getTransports());
+ assertEquals(_sslTransports, _port.getTransports());
}
else
{
- assertEquals(_tcpTransports, port.getTransports());
+ assertEquals(_tcpTransports, _port.getTransports());
}
- assertEquals(amqp010ProtocolSet, port.getProtocols());
- assertEquals("Unexpected send buffer size", 2, port.getAttribute(AmqpPort.SEND_BUFFER_SIZE));
- assertEquals("Unexpected receive buffer size", 1, port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE));
- assertEquals("Unexpected need client auth", needClientAuth, port.getAttribute(Port.NEED_CLIENT_AUTH));
- assertEquals("Unexpected want client auth", wantClientAuth, port.getAttribute(Port.WANT_CLIENT_AUTH));
- assertEquals("Unexpected tcp no delay", true, port.getAttribute(Port.TCP_NO_DELAY));
- assertEquals("Unexpected binding", "127.0.0.1", port.getAttribute(Port.BINDING_ADDRESS));
+ assertEquals(amqp010ProtocolSet, _port.getProtocols());
+ assertEquals("Unexpected send buffer size", 2, _port.getAttribute(AmqpPort.SEND_BUFFER_SIZE));
+ assertEquals("Unexpected receive buffer size", 1, _port.getAttribute(AmqpPort.RECEIVE_BUFFER_SIZE));
+ assertEquals("Unexpected need client auth", needClientAuth, _port.getAttribute(Port.NEED_CLIENT_AUTH));
+ assertEquals("Unexpected want client auth", wantClientAuth, _port.getAttribute(Port.WANT_CLIENT_AUTH));
+ assertEquals("Unexpected tcp no delay", true, _port.getAttribute(Port.TCP_NO_DELAY));
+ assertEquals("Unexpected binding", "127.0.0.1", _port.getAttribute(Port.BINDING_ADDRESS));
}
public void testCreateNonAmqpPort()
@@ -291,14 +308,14 @@ public class PortFactoryTest extends QpidTestCase
_attributes.put(Port.NAME, getName());
_attributes.put(Port.ID, _portId);
- Port<?> port = _factory.create(Port.class, _attributes, _broker);
+ _port = _factory.create(Port.class, _attributes, _broker);
- assertNotNull(port);
- assertFalse("Port should not be an AMQP-specific subclass", port instanceof AmqpPort);
- assertEquals(_portId, port.getId());
- assertEquals(_portNumber, port.getPort());
- assertEquals(_tcpTransports, port.getTransports());
- assertEquals(nonAmqpProtocolSet, port.getProtocols());
+ assertNotNull(_port);
+ assertFalse("Port should not be an AMQP-specific subclass", _port instanceof AmqpPort);
+ assertEquals(_portId, _port.getId());
+ assertEquals(_portNumber, _port.getPort());
+ assertEquals(_tcpTransports, _port.getTransports());
+ assertEquals(nonAmqpProtocolSet, _port.getProtocols());
}
public void testCreateNonAmqpPortWithPartiallySetAttributes()
@@ -312,14 +329,14 @@ public class PortFactoryTest extends QpidTestCase
_attributes.put(Port.NAME, getName());
_attributes.put(Port.ID, _portId);
- Port<?> port = _factory.create(Port.class, _attributes, _broker);
+ _port = _factory.create(Port.class, _attributes, _broker);
- assertNotNull(port);
- assertFalse("Port not be an AMQP-specific port subclass", port instanceof AmqpPort);
- assertEquals(_portId, port.getId());
- assertEquals(_portNumber, port.getPort());
- assertEquals(Collections.singleton(PortFactory.DEFAULT_TRANSPORT), port.getTransports());
- assertEquals(nonAmqpProtocolSet, port.getProtocols());
+ assertNotNull(_port);
+ assertFalse("Port not be an AMQP-specific _port subclass", _port instanceof AmqpPort);
+ assertEquals(_portId, _port.getId());
+ assertEquals(_portNumber, _port.getPort());
+ assertEquals(Collections.singleton(PortFactory.DEFAULT_TRANSPORT), _port.getTransports());
+ assertEquals(nonAmqpProtocolSet, _port.getProtocols());
}
@@ -330,7 +347,7 @@ public class PortFactoryTest extends QpidTestCase
try
{
- Port<?> port = _factory.create(Port.class, _attributes, _broker);
+ _port = _factory.create(Port.class, _attributes, _broker);
fail("Exception not thrown");
}
catch (IllegalConfigurationException e)
@@ -353,7 +370,7 @@ public class PortFactoryTest extends QpidTestCase
try
{
- Port<?> port = _factory.create(Port.class, attributes, _broker);
+ _port = _factory.create(Port.class, attributes, _broker);
fail("RMI port creation should fail as another one already exist");
}
catch(IllegalConfigurationException e)
@@ -377,7 +394,7 @@ public class PortFactoryTest extends QpidTestCase
try
{
- Port<?> port = _factory.create(Port.class, attributes, _broker);
+ _port = _factory.create(Port.class, attributes, _broker);
fail("RMI port creation should fail due to requesting SSL");
}
catch(IllegalConfigurationException e)
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
new file mode 100644
index 0000000000..1a993f8967
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/port/AmqpPortImplTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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.port;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class AmqpPortImplTest extends QpidTestCase
+{
+ private static final String AUTHENTICATION_PROVIDER_NAME = "test";
+ private TaskExecutor _taskExecutor;
+ private Broker _broker;
+ private ServerSocket _socket;
+ private AmqpPortImpl _port;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+ Model model = BrokerModel.getInstance();
+
+ _broker = mock(Broker.class);
+ when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+ when(_broker.getModel()).thenReturn(model);
+ when(_broker.getId()).thenReturn(UUID.randomUUID());
+ when(_broker.getSecurityManager()).thenReturn(new SecurityManager(_broker, false));
+ when(_broker.getCategoryClass()).thenReturn(Broker.class);
+ when(_broker.getEventLogger()).thenReturn(new EventLogger());
+ AuthenticationProvider<?> provider = mock(AuthenticationProvider.class);
+ when(provider.getName()).thenReturn(AUTHENTICATION_PROVIDER_NAME);
+ when(provider.getParent(Broker.class)).thenReturn(_broker);
+ when(_broker.getChildren(AuthenticationProvider.class)).thenReturn(Collections.<AuthenticationProvider>singleton(provider));
+ when(_broker.getChildByName(AuthenticationProvider.class, AUTHENTICATION_PROVIDER_NAME)).thenReturn(provider);
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_socket != null)
+ {
+ _socket.close();
+ }
+ _taskExecutor.stop();
+ }
+ finally
+ {
+ if (_port != null)
+ {
+ _port.close();
+ }
+ super.tearDown();
+ }
+ }
+
+ public void testValidateOnCreate() throws Exception
+ {
+ _socket = openSocket();
+
+ Map<String, Object> attributes = new HashMap<>();
+ attributes.put(AmqpPort.PORT, _socket.getLocalPort());
+ attributes.put(AmqpPort.NAME, getTestName());
+ attributes.put(AmqpPort.AUTHENTICATION_PROVIDER, AUTHENTICATION_PROVIDER_NAME);
+ _port = new AmqpPortImpl(attributes, _broker);
+ try
+ {
+ _port.create();
+ fail("Creation should fail due to validation check");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception message",
+ String.format("Cannot bind to port %d and binding address '%s'. Port is already is use.",
+ _socket.getLocalPort(), "*"), e.getMessage());
+ }
+ }
+
+ private ServerSocket openSocket() throws IOException
+ {
+ ServerSocket serverSocket = new ServerSocket();
+ serverSocket.setReuseAddress(true);
+ serverSocket.bind(new InetSocketAddress(findFreePort()));
+ return serverSocket;
+ }
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java
new file mode 100644
index 0000000000..5c04db0cd6
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestConfiguredObject.java
@@ -0,0 +1,256 @@
+/*
+ * 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.testmodel;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObjectFactory;
+import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl;
+import org.apache.qpid.server.model.ConfiguredObjectTypeRegistry;
+import org.apache.qpid.server.model.ManagedObject;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.StateTransition;
+import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
+
+@ManagedObject
+public class TestConfiguredObject extends AbstractConfiguredObject
+{
+ private boolean _opened;
+ private boolean _validated;
+ private boolean _resolved;
+ private boolean _throwExceptionOnOpen;
+ private boolean _throwExceptionOnValidationOnCreate;
+ private boolean _throwExceptionOnPostResolve;
+ private boolean _throwExceptionOnCreate;
+ private boolean _throwExceptionOnValidate;
+
+ public final static Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> createParents(ConfiguredObject<?> parent)
+ {
+ return Collections.<Class<? extends ConfiguredObject>, ConfiguredObject<?>>singletonMap(parent.getCategoryClass(), parent);
+ }
+
+ public TestConfiguredObject(String name)
+ {
+ this(name, mock(ConfiguredObject.class), CurrentThreadTaskExecutor.newStartedInstance());
+ }
+
+ public TestConfiguredObject(String name, ConfiguredObject<?> parent, TaskExecutor taskExecutor)
+ {
+ this(createParents(parent), Collections.<String, Object>singletonMap(ConfiguredObject.NAME, name), taskExecutor, TestConfiguredObjectModel.INSTANCE);
+ }
+
+ public TestConfiguredObject(Map parents, Map<String, Object> attributes, TaskExecutor taskExecutor, Model model)
+ {
+ super(parents, attributes, taskExecutor, model);
+ _opened = false;
+ }
+
+ @Override
+ protected void postResolve()
+ {
+ if (_throwExceptionOnPostResolve)
+ {
+ throw new IllegalConfigurationException("Cannot resolve");
+ }
+ _resolved = true;
+ }
+
+ @Override
+ protected void onCreate()
+ {
+ if (_throwExceptionOnCreate)
+ {
+ throw new IllegalConfigurationException("Cannot create");
+ }
+ }
+
+ @Override
+ protected void onOpen()
+ {
+ if (_throwExceptionOnOpen)
+ {
+ throw new IllegalConfigurationException("Cannot open");
+ }
+ _opened = true;
+ }
+
+ @Override
+ protected void validateOnCreate()
+ {
+ if (_throwExceptionOnValidationOnCreate)
+ {
+ throw new IllegalConfigurationException("Cannot validate on create");
+ }
+ }
+
+ @Override
+ public void onValidate()
+ {
+ if (_throwExceptionOnValidate)
+ {
+ throw new IllegalConfigurationException("Cannot validate");
+ }
+ _validated = true;
+ }
+
+ @StateTransition( currentState = {State.ERRORED, State.UNINITIALIZED}, desiredState = State.ACTIVE )
+ protected void activate()
+ {
+ setState(State.ACTIVE);
+ }
+
+ @StateTransition( currentState = {State.ERRORED, State.UNINITIALIZED}, desiredState = State.DELETED )
+ protected void doDelete()
+ {
+ setState(State.DELETED);
+ }
+
+ public boolean isOpened()
+ {
+ return _opened;
+ }
+
+ public void setThrowExceptionOnOpen(boolean throwException)
+ {
+ _throwExceptionOnOpen = throwException;
+ }
+
+ public void setThrowExceptionOnValidationOnCreate(boolean throwException)
+ {
+ _throwExceptionOnValidationOnCreate = throwException;
+ }
+
+ public void setThrowExceptionOnPostResolve(boolean throwException)
+ {
+ _throwExceptionOnPostResolve = throwException;
+ }
+
+ public void setThrowExceptionOnCreate(boolean throwExceptionOnCreate)
+ {
+ _throwExceptionOnCreate = throwExceptionOnCreate;
+ }
+
+ public void setThrowExceptionOnValidate(boolean throwException)
+ {
+ _throwExceptionOnValidate= throwException;
+ }
+
+ public boolean isValidated()
+ {
+ return _validated;
+ }
+
+ public boolean isResolved()
+ {
+ return _resolved;
+ }
+
+ public static class TestConfiguredObjectModel extends Model
+ {
+
+ private Collection<Class<? extends ConfiguredObject>> CATEGORIES = Collections.<Class<? extends ConfiguredObject>>singleton(TestConfiguredObject.class);
+ private ConfiguredObjectFactoryImpl _configuredObjectFactory;
+
+ private static TestConfiguredObjectModel INSTANCE = new TestConfiguredObjectModel();
+ private ConfiguredObjectTypeRegistry _configuredObjectTypeRegistry;
+
+ private TestConfiguredObjectModel()
+ {
+ _configuredObjectFactory = new ConfiguredObjectFactoryImpl(this);
+ ConfiguredObjectRegistration configuredObjectRegistration = new ConfiguredObjectRegistration()
+ {
+ @Override
+ public Collection<Class<? extends ConfiguredObject>> getConfiguredObjectClasses()
+ {
+ return CATEGORIES;
+ }
+
+ @Override
+ public String getType()
+ {
+ return TestConfiguredObjectModel.class.getSimpleName();
+ }
+ };
+ _configuredObjectTypeRegistry = new ConfiguredObjectTypeRegistry(Arrays.asList(configuredObjectRegistration), CATEGORIES);
+ }
+
+ @Override
+ public Collection<Class<? extends ConfiguredObject>> getSupportedCategories()
+ {
+ return CATEGORIES;
+ }
+
+ @Override
+ public Collection<Class<? extends ConfiguredObject>> getChildTypes(Class<? extends ConfiguredObject> parent)
+ {
+ return TestConfiguredObject.class.isAssignableFrom(parent)
+ ? CATEGORIES
+ : Collections.<Class<? extends ConfiguredObject>>emptySet();
+ }
+
+ @Override
+ public Class<? extends ConfiguredObject> getRootCategory()
+ {
+ return TestConfiguredObject.class;
+ }
+
+ @Override
+ public Collection<Class<? extends ConfiguredObject>> getParentTypes(final Class<? extends ConfiguredObject> child)
+ {
+ return TestConfiguredObject.class.isAssignableFrom(child)
+ ? CATEGORIES
+ : Collections.<Class<? extends ConfiguredObject>>emptySet();
+ }
+
+ @Override
+ public int getMajorVersion()
+ {
+ return 99;
+ }
+
+ @Override
+ public int getMinorVersion()
+ {
+ return 99;
+ }
+
+ @Override
+ public ConfiguredObjectFactory getObjectFactory()
+ {
+ return _configuredObjectFactory;
+ }
+
+ @Override
+ public ConfiguredObjectTypeRegistry getTypeRegistry()
+ {
+ return _configuredObjectTypeRegistry;
+ }
+ }
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
index 703a8d43c9..84ba7a3822 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java
@@ -90,31 +90,28 @@ public class PrincipalDatabaseAuthenticationManagerTest extends QpidTestCase
private void setupMocks() throws Exception
{
- _principalDatabase = mock(PrincipalDatabase.class);
-
- when(_principalDatabase.getMechanisms()).thenReturn(Collections.singletonList(MOCK_MECH_NAME));
- when(_principalDatabase.createSaslServer(MOCK_MECH_NAME, LOCALHOST, null)).thenReturn(new MySaslServer(false, true));
+ setUpPrincipalDatabase();
setupManager(false);
_manager.initialise();
}
+ private void setUpPrincipalDatabase() throws SaslException
+ {
+ _principalDatabase = mock(PrincipalDatabase.class);
+
+ when(_principalDatabase.getMechanisms()).thenReturn(Collections.singletonList(MOCK_MECH_NAME));
+ when(_principalDatabase.createSaslServer(MOCK_MECH_NAME, LOCALHOST, null)).thenReturn(new MySaslServer(false, true));
+ }
+
private void setupManager(final boolean recovering)
{
Map<String,Object> attrs = new HashMap<String, Object>();
attrs.put(ConfiguredObject.ID, UUID.randomUUID());
attrs.put(ConfiguredObject.NAME, getTestName());
attrs.put("path", _passwordFileLocation);
- _manager = new PrincipalDatabaseAuthenticationManager(attrs, BrokerTestHelper.createBrokerMock())
- {
- @Override
- protected PrincipalDatabase createDatabase()
- {
- return _principalDatabase;
- }
-
- };
+ _manager = getPrincipalDatabaseAuthenticationManager(attrs);
if(recovering)
{
_manager.open();
@@ -273,6 +270,41 @@ public class PrincipalDatabaseAuthenticationManagerTest extends QpidTestCase
assertFalse("Password file was not deleted", new File(_passwordFileLocation).exists());
}
+ public void testCreateForInvalidPath() throws Exception
+ {
+ setUpPrincipalDatabase();
+
+ Map<String,Object> attrs = new HashMap<>();
+ attrs.put(ConfiguredObject.ID, UUID.randomUUID());
+ attrs.put(ConfiguredObject.NAME, getTestName());
+ String path = TMP_FOLDER + File.separator + getTestName() + System.nanoTime() + File.separator + "users";
+ attrs.put("path", path);
+
+ _manager = getPrincipalDatabaseAuthenticationManager(attrs);
+ try
+ {
+ _manager.create();
+ fail("Creation with invalid path should have failed");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception message:" + e.getMessage(), String.format("Cannot create password file at '%s'", path), e.getMessage());
+ }
+ }
+
+ PrincipalDatabaseAuthenticationManager getPrincipalDatabaseAuthenticationManager(final Map<String, Object> attrs)
+ {
+ return new PrincipalDatabaseAuthenticationManager(attrs, BrokerTestHelper.createBrokerMock())
+ {
+ @Override
+ protected PrincipalDatabase createDatabase()
+ {
+ return _principalDatabase;
+ }
+
+ };
+ }
+
private void deletePasswordFileIfExists()
{
File passwordFile = new File(_passwordFileLocation);
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
index 6001ed1750..9e580d3157 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
@@ -57,40 +57,15 @@ public class SimpleLDAPAuthenticationManagerFactoryTest extends TestCase
_configuration.put(AuthenticationProvider.NAME, getName());
}
- public void testLdapInstanceCreated() throws Exception
+ public void testLdapCreated() throws Exception
{
_configuration.put(AuthenticationProvider.TYPE, SimpleLDAPAuthenticationManager.PROVIDER_TYPE);
- _configuration.put("providerUrl", "ldap://example.com:389/");
- _configuration.put("searchContext", "dc=example");
-
- AuthenticationProvider manager = _factory.create(AuthenticationProvider.class, _configuration, _broker);
- assertNotNull(manager);
-
- }
-
- public void testLdapsInstanceCreated() throws Exception
- {
- _configuration.put(AuthenticationProvider.TYPE, SimpleLDAPAuthenticationManager.PROVIDER_TYPE);
- _configuration.put("providerUrl", "ldaps://example.com:636/");
- _configuration.put("searchContext", "dc=example");
-
- AuthenticationProvider manager = _factory.create(AuthenticationProvider.class, _configuration, _broker);
- assertNotNull(manager);
-
- }
-
- public void testLdapsWithTrustStoreInstanceCreated() throws Exception
- {
- when(_broker.getChildren(eq(TrustStore.class))).thenReturn(Collections.singletonList(_trustStore));
-
-
- _configuration.put(AuthenticationProvider.TYPE, SimpleLDAPAuthenticationManager.PROVIDER_TYPE);
_configuration.put("providerUrl", "ldaps://example.com:636/");
_configuration.put("searchContext", "dc=example");
- _configuration.put("trustStore", "mytruststore");
+ _configuration.put("searchFilter", "(uid={0})");
+ _configuration.put("ldapContextFactory", TestLdapDirectoryContext.class.getName());
- AuthenticationProvider manager = _factory.create(AuthenticationProvider.class, _configuration, _broker);
- assertNotNull(manager);
+ _factory.create(AuthenticationProvider.class, _configuration, _broker);
}
public void testLdapsWhenTrustStoreNotFound() throws Exception
@@ -100,6 +75,7 @@ public class SimpleLDAPAuthenticationManagerFactoryTest extends TestCase
_configuration.put(AuthenticationProvider.TYPE, SimpleLDAPAuthenticationManager.PROVIDER_TYPE);
_configuration.put("providerUrl", "ldaps://example.com:636/");
_configuration.put("searchContext", "dc=example");
+ _configuration.put("searchFilter", "(uid={0})");
_configuration.put("trustStore", "notfound");
try
@@ -110,7 +86,7 @@ public class SimpleLDAPAuthenticationManagerFactoryTest extends TestCase
catch(IllegalArgumentException e)
{
// PASS
- assertTrue("Message does not include underlying issue", e.getMessage().contains("name 'notfound'"));
+ assertTrue("Message does not include underlying issue ", e.getMessage().contains("name 'notfound'"));
assertTrue("Message does not include the attribute name", e.getMessage().contains("trustStore"));
assertTrue("Message does not include the expected type", e.getMessage().contains("TrustStore"));
}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/TestLdapDirectoryContext.java b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/TestLdapDirectoryContext.java
new file mode 100644
index 0000000000..87b73c8373
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/TestLdapDirectoryContext.java
@@ -0,0 +1,38 @@
+/*
+ * 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.security.auth.manager;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.Hashtable;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+
+public class TestLdapDirectoryContext implements javax.naming.spi.InitialContextFactory
+{
+ @Override
+ public Context getInitialContext(final Hashtable<?, ?> environment) throws NamingException
+ {
+ return (DirContext)mock(DirContext.class);
+ }
+
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
index 52f70e7fd6..c220876a23 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerRecovererTest.java
@@ -21,7 +21,9 @@
package org.apache.qpid.server.store;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.verify;
import java.util.Arrays;
import java.util.Collections;
@@ -40,6 +42,7 @@ import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.GroupProvider;
import org.apache.qpid.server.model.JsonSystemConfigImpl;
@@ -55,6 +58,7 @@ public class BrokerRecovererTest extends TestCase
private UUID _authenticationProvider1Id = UUID.randomUUID();
private SystemConfig<?> _systemConfig;
private TaskExecutor _taskExecutor;
+ private BrokerShutdownProvider _brokerShutdownProvider;
@Override
protected void setUp() throws Exception
@@ -63,8 +67,11 @@ public class BrokerRecovererTest extends TestCase
_taskExecutor = new CurrentThreadTaskExecutor();
_taskExecutor.start();
+ _brokerShutdownProvider = mock(BrokerShutdownProvider.class);
_systemConfig = new JsonSystemConfigImpl(_taskExecutor,
- mock(EventLogger.class), mock(LogRecorder.class), new BrokerOptions());
+ mock(EventLogger.class), mock(LogRecorder.class),
+ new BrokerOptions(),
+ _brokerShutdownProvider);
when(_brokerEntry.getId()).thenReturn(_brokerId);
when(_brokerEntry.getType()).thenReturn(Broker.class.getSimpleName());
@@ -251,18 +258,10 @@ public class BrokerRecovererTest extends TestCase
brokerAttributes.put(Broker.NAME, getName());
when(_brokerEntry.getAttributes()).thenReturn(brokerAttributes);
- try
- {
- resolveObjects(_brokerEntry);
- Broker<?> broker = _systemConfig.getBroker();
- broker.open();
- fail("The broker creation should fail due to unsupported model version");
- }
- catch (IllegalConfigurationException e)
- {
- assertEquals("The model version '" + incompatibleVersion
- + "' in configuration is incompatible with the broker model version '" + BrokerModel.MODEL_VERSION + "'", e.getMessage());
- }
+ resolveObjects(_brokerEntry);
+ Broker<?> broker = _systemConfig.getBroker();
+ broker.open();
+ verify(_brokerShutdownProvider).shutdown();
}
}
@@ -276,20 +275,12 @@ public class BrokerRecovererTest extends TestCase
when(_brokerEntry.getAttributes()).thenReturn(brokerAttributes);
- try
- {
- UnresolvedConfiguredObject<? extends ConfiguredObject> recover =
- _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig);
+ UnresolvedConfiguredObject<? extends ConfiguredObject> recover =
+ _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig);
- Broker<?> broker = (Broker<?>) recover.resolve();
- broker.open();
- fail("The broker creation should fail due to unsupported model version");
- }
- catch (IllegalConfigurationException e)
- {
- assertEquals("The model version '" + incompatibleVersion
- + "' in configuration is incompatible with the broker model version '" + BrokerModel.MODEL_VERSION + "'", e.getMessage());
- }
+ Broker<?> broker = (Broker<?>) recover.resolve();
+ broker.open();
+ verify(_brokerShutdownProvider).shutdown();
}
public void testIncorrectModelVersion() throws Exception
@@ -303,18 +294,12 @@ public class BrokerRecovererTest extends TestCase
brokerAttributes.put(Broker.MODEL_VERSION, modelVersion);
when(_brokerEntry.getAttributes()).thenReturn(brokerAttributes);
- try
- {
- UnresolvedConfiguredObject<? extends ConfiguredObject> recover =
- _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig);
- Broker<?> broker = (Broker<?>) recover.resolve();
- broker.open();
- fail("The broker creation should fail due to unsupported model version");
- }
- catch (IllegalConfigurationException e)
- {
- // pass
- }
+ UnresolvedConfiguredObject<? extends ConfiguredObject> recover =
+ _systemConfig.getObjectFactory().recover(_brokerEntry, _systemConfig);
+ Broker<?> broker = (Broker<?>) recover.resolve();
+ broker.open();
+ verify(_brokerShutdownProvider).shutdown();
+ reset(_brokerShutdownProvider);
}
}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
index c94a0ef9c4..45b595b62e 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/store/BrokerStoreUpgraderAndRecovererTest.java
@@ -32,6 +32,7 @@ import org.apache.qpid.server.BrokerOptions;
import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.JsonSystemConfigImpl;
import org.apache.qpid.server.model.SystemConfig;
@@ -60,7 +61,8 @@ public class BrokerStoreUpgraderAndRecovererTest extends QpidTestCase
_systemConfig = new JsonSystemConfigImpl(_taskExecutor,
mock(EventLogger.class),
mock(LogRecorder.class),
- new BrokerOptions());
+ new BrokerOptions(),
+ mock(BrokerShutdownProvider.class));
}
public void testUpgradeVirtualHostWithJDBCStoreAndBoneCPPool()
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java
new file mode 100644
index 0000000000..889097f850
--- /dev/null
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/AbstractVirtualHostTest.java
@@ -0,0 +1,247 @@
+/*
+ *
+ * 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.virtualhost;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verifyZeroInteractions;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.doThrow;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutorImpl;
+import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.SystemConfig;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.test.utils.QpidTestCase;
+import org.mockito.verification.VerificationMode;
+
+public class AbstractVirtualHostTest extends QpidTestCase
+{
+ private TaskExecutor _taskExecutor;
+ private VirtualHostNode<?> _node;
+ private MessageStore _failingStore;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+
+ SystemConfig systemConfig = mock(SystemConfig.class);
+ when(systemConfig.getEventLogger()).thenReturn(mock(EventLogger.class));
+ Broker<?> broker = mock(Broker.class);
+ when(broker.getParent(SystemConfig.class)).thenReturn(systemConfig);
+ when(broker.getSecurityManager()).thenReturn(new SecurityManager(broker, false));
+
+ _taskExecutor = new TaskExecutorImpl();
+ _taskExecutor.start();
+ when(broker.getTaskExecutor()).thenReturn(_taskExecutor);
+
+ _node = mock(VirtualHostNode.class);
+ when(_node.getParent(Broker.class)).thenReturn(broker);
+ when(_node.getModel()).thenReturn(BrokerModel.getInstance());
+ when(_node.getTaskExecutor()).thenReturn(_taskExecutor);
+ when(_node.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class));
+
+ _failingStore = mock(MessageStore.class);
+ doThrow(new RuntimeException("Cannot open store")).when(_failingStore).openMessageStore(any(ConfiguredObject.class));
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ try
+ {
+ if (_taskExecutor != null)
+ {
+ _taskExecutor.stopImmediately();
+ }
+ }
+ finally
+ {
+ super.tearDown();
+ }
+ }
+
+ public void testValidateOnCreateFails()
+ {
+ Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+
+ AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+ {
+ @Override
+ protected MessageStore createMessageStore()
+ {
+ return _failingStore;
+ }
+ };
+
+ try
+ {
+ host.validateOnCreate();
+ fail("Validation on creation should fail");
+ }
+ catch(IllegalConfigurationException e)
+ {
+ assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open virtual host message store"));
+ }
+ }
+
+ public void testValidateOnCreateSucceeds()
+ {
+ Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+ final MessageStore store = mock(MessageStore.class);
+ AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+ {
+ @Override
+ protected MessageStore createMessageStore()
+ {
+ return store;
+ }
+ };
+
+ host.validateOnCreate();
+ verify(store).openMessageStore(host);
+ verify(store).closeMessageStore();
+ }
+
+ public void testOpenFails()
+ {
+ Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+
+ AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+ {
+ @Override
+ protected MessageStore createMessageStore()
+ {
+ return _failingStore;
+ }
+ };
+
+ host.open();
+ assertEquals("Unexpected host state", State.ERRORED, host.getState());
+ }
+
+ public void testOpenSucceeds()
+ {
+ Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+ final MessageStore store = mock(MessageStore.class);
+ AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+ {
+ @Override
+ protected MessageStore createMessageStore()
+ {
+ return store;
+ }
+ };
+
+ host.open();
+ assertEquals("Unexpected host state", State.ACTIVE, host.getState());
+ verify(store).openMessageStore(host);
+
+ // make sure that method AbstractVirtualHost.onExceptionInOpen was not called
+ verify(store, times(0)).closeMessageStore();
+ }
+
+ public void testDeleteInErrorStateAfterOpen()
+ {
+ Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+ AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+ {
+ @Override
+ protected MessageStore createMessageStore()
+ {
+ return _failingStore;
+ }
+ };
+
+ host.open();
+
+ assertEquals("Unexpected state", State.ERRORED, host.getState());
+
+ host.delete();
+ assertEquals("Unexpected state", State.DELETED, host.getState());
+ }
+
+ public void testActivateInErrorStateAfterOpen() throws Exception
+ {
+ Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+ final MessageStore store = mock(MessageStore.class);
+ doThrow(new RuntimeException("Cannot open store")).when(store).openMessageStore(any(ConfiguredObject.class));
+ AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+ {
+ @Override
+ protected MessageStore createMessageStore()
+ {
+ return store;
+ }
+ };
+
+ host.open();
+ assertEquals("Unexpected state", State.ERRORED, host.getState());
+
+ doNothing().when(store).openMessageStore(any(ConfiguredObject.class));
+
+ host.setAttributes(Collections.<String, Object>singletonMap(VirtualHost.DESIRED_STATE, State.ACTIVE));
+ assertEquals("Unexpected state", State.ACTIVE, host.getState());
+ }
+
+ public void testStartInErrorStateAfterOpen() throws Exception
+ {
+ Map<String,Object> attributes = Collections.<String, Object>singletonMap(AbstractVirtualHost.NAME, getTestName());
+ final MessageStore store = mock(MessageStore.class);
+ doThrow(new RuntimeException("Cannot open store")).when(store).openMessageStore(any(ConfiguredObject.class));
+ AbstractVirtualHost host = new AbstractVirtualHost(attributes, _node)
+ {
+ @Override
+ protected MessageStore createMessageStore()
+ {
+ return store;
+ }
+ };
+
+ host.open();
+ assertEquals("Unexpected state", State.ERRORED, host.getState());
+
+ doNothing().when(store).openMessageStore(any(ConfiguredObject.class));
+
+ host.start();
+ assertEquals("Unexpected state", State.ACTIVE, host.getState());
+ }
+}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
index 971c96b2ff..b17f383217 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
@@ -20,22 +20,30 @@
*/
package org.apache.qpid.server.virtualhostnode;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import java.security.AccessControlException;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl;
import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.model.RemoteReplicationNode;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.model.VirtualHost;
@@ -348,6 +356,132 @@ public class AbstractStandardVirtualHostNodeTest extends QpidTestCase
assertEquals("Virtual host node state changed unexpectedly", State.ACTIVE, node.getState());
}
+ public void testValidateOnCreateFails() throws Exception
+ {
+ String nodeName = getTestName();
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+ final DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+ doThrow(new RuntimeException("Cannot open store")).when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+ AbstractStandardVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+
+ try
+ {
+ node.validateOnCreate();
+ fail("Cannot create node");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertTrue("Unexpected exception " + e.getMessage(), e.getMessage().startsWith("Cannot open node configuration store"));
+ }
+ }
+
+ public void testValidateOnCreateSucceeds() throws Exception
+ {
+ String nodeName = getTestName();
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+ final DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+ AbstractStandardVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+
+ node.validateOnCreate();
+ verify(store).openConfigurationStore(node, false);
+ verify(store).closeConfigurationStore();
+ }
+
+ public void testOpenFails() throws Exception
+ {
+ String nodeName = getTestName();
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+ DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+ AbstractVirtualHostNode node = new TestAbstractVirtualHostNode( _broker, attributes, store);
+ node.open();
+ assertEquals("Unexpected node state", State.ERRORED, node.getState());
+ }
+
+ public void testOpenSucceeds() throws Exception
+ {
+ String nodeName = getTestName();
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+ final AtomicBoolean onFailureFlag = new AtomicBoolean();
+ DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+ AbstractVirtualHostNode node = new TestAbstractVirtualHostNode( _broker, attributes, store)
+ {
+ @Override
+ public void onValidate()
+ {
+ // no op
+ }
+
+ @Override
+ protected void onExceptionInOpen(RuntimeException e)
+ {
+ try
+ {
+ super.onExceptionInOpen(e);
+ }
+ finally
+ {
+ onFailureFlag.set(true);
+ }
+ }
+ };
+
+ node.open();
+ assertEquals("Unexpected node state", State.ACTIVE, node.getState());
+ assertFalse("onExceptionInOpen was called", onFailureFlag.get());
+ }
+
+
+ public void testDeleteInErrorStateAfterOpen()
+ {
+ String nodeName = getTestName();
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+ final DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+ doThrow(new RuntimeException("Cannot open store")).when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+ AbstractStandardVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+ node.open();
+ assertEquals("Unexpected node state", State.ERRORED, node.getState());
+
+ node.delete();
+ assertEquals("Unexpected state", State.DELETED, node.getState());
+ }
+
+ public void testActivateInErrorStateAfterOpen() throws Exception
+ {
+ String nodeName = getTestName();
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+ DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+ doThrow(new RuntimeException("Cannot open store")).when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+ AbstractVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+ node.open();
+ assertEquals("Unexpected node state", State.ERRORED, node.getState());
+ doNothing().when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+
+ node.setAttributes(Collections.<String, Object>singletonMap(VirtualHostNode.DESIRED_STATE, State.ACTIVE));
+ assertEquals("Unexpected state", State.ACTIVE, node.getState());
+ }
+
+ public void testStartInErrorStateAfterOpen() throws Exception
+ {
+ String nodeName = getTestName();
+ Map<String, Object> attributes = Collections.<String, Object>singletonMap(TestVirtualHostNode.NAME, nodeName);
+
+ DurableConfigurationStore store = mock(DurableConfigurationStore.class);
+ doThrow(new RuntimeException("Cannot open store")).when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+ AbstractVirtualHostNode node = createAbstractStandardVirtualHostNode(attributes, store);
+ node.open();
+ assertEquals("Unexpected node state", State.ERRORED, node.getState());
+ doNothing().when(store).openConfigurationStore(any(ConfiguredObject.class), any(boolean.class));
+
+ node.start();
+ assertEquals("Unexpected state", State.ACTIVE, node.getState());
+ }
+
private ConfiguredObjectRecord createVirtualHostConfiguredObjectRecord(UUID virtualHostId)
{
Map<String, Object> virtualHostAttributes = new HashMap<>();
@@ -384,4 +518,62 @@ public class AbstractStandardVirtualHostNodeTest extends QpidTestCase
return configStoreThatProduces(null);
}
+
+ private AbstractStandardVirtualHostNode createAbstractStandardVirtualHostNode(final Map<String, Object> attributes, final DurableConfigurationStore store)
+ {
+ return new AbstractStandardVirtualHostNode(attributes, _broker){
+
+ @Override
+ protected void writeLocationEventLog()
+ {
+
+ }
+
+ @Override
+ protected DurableConfigurationStore createConfigurationStore()
+ {
+ return store;
+ }
+ };
+ }
+
+ private class TestAbstractVirtualHostNode extends AbstractVirtualHostNode
+ {
+ private DurableConfigurationStore _store;
+
+ public TestAbstractVirtualHostNode(Broker parent, Map attributes, DurableConfigurationStore store)
+ {
+ super(parent, attributes);
+ _store = store;
+ }
+
+ @Override
+ public void onValidate()
+ {
+ throw new RuntimeException("Cannot validate");
+ }
+
+ @Override
+ protected DurableConfigurationStore createConfigurationStore()
+ {
+ return _store;
+ }
+
+ @Override
+ protected void activate()
+ {
+ }
+
+ @Override
+ protected ConfiguredObjectRecord enrichInitialVirtualHostRootRecord(ConfiguredObjectRecord vhostRecord)
+ {
+ return null;
+ }
+
+ @Override
+ public Collection<? extends RemoteReplicationNode> getRemoteReplicationNodes()
+ {
+ return null;
+ }
+ }
}
diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java
index 277ef8b400..4fe8136624 100644
--- a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java
+++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java
@@ -53,6 +53,12 @@ public class TestVirtualHostNode extends AbstractStandardVirtualHostNode<TestVir
}
@Override
+ public DurableConfigurationStore getConfigurationStore()
+ {
+ return _store;
+ }
+
+ @Override
protected void writeLocationEventLog()
{
}
diff --git a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
index f0edc59025..1adc6561c7 100644
--- a/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
+++ b/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImpl.java
@@ -25,10 +25,10 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.Broker;
@@ -83,6 +83,29 @@ public class ACLFileAccessControlProviderImpl
}
@Override
+ protected void validateOnCreate()
+ {
+ DefaultAccessControl accessControl = null;
+ try
+ {
+ accessControl = new DefaultAccessControl(getPath(), _broker);
+ accessControl.validate();
+ accessControl.open();
+ }
+ catch(RuntimeException e)
+ {
+ throw new IllegalConfigurationException(e.getMessage(), e);
+ }
+ finally
+ {
+ if (accessControl != null)
+ {
+ accessControl.close();
+ }
+ }
+ }
+
+ @Override
protected void onOpen()
{
super.onOpen();
@@ -105,6 +128,7 @@ public class ACLFileAccessControlProviderImpl
@StateTransition(currentState = {State.UNINITIALIZED, State.QUIESCED, State.ERRORED}, desiredState = State.ACTIVE)
private void activate()
{
+
if(_broker.isManagementMode())
{
@@ -136,7 +160,10 @@ public class ACLFileAccessControlProviderImpl
protected void onClose()
{
super.onClose();
- _accessControl.close();
+ if (_accessControl != null)
+ {
+ _accessControl.close();
+ }
}
@StateTransition(currentState = State.UNINITIALIZED, desiredState = State.QUIESCED)
diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java
new file mode 100644
index 0000000000..005d2a95bc
--- /dev/null
+++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/ACLFileAccessControlProviderImplTest.java
@@ -0,0 +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.
+ *
+ */
+
+package org.apache.qpid.server.security.access.plugins;
+
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.CurrentThreadTaskExecutor;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.Model;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class ACLFileAccessControlProviderImplTest extends QpidTestCase
+{
+ private TaskExecutor _taskExecutor;
+ private Model _model;
+ private Broker _broker;
+
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _taskExecutor = CurrentThreadTaskExecutor.newStartedInstance();
+ _model = BrokerModel.getInstance();
+
+ _broker = mock(Broker.class);
+ when(_broker.getTaskExecutor()).thenReturn(_taskExecutor);
+ when(_broker.getModel()).thenReturn(_model);
+ when(_broker.getId()).thenReturn(UUID.randomUUID());
+ }
+
+ public void testValidationOnCreateWithNonExistingACLFile()
+ {
+ Map<String,Object> attributes = new HashMap<>();
+ String aclFilePath = new File(TMP_FOLDER, "test_" + getTestName() + System.nanoTime() + ".acl").getAbsolutePath();
+
+ attributes.put("path", aclFilePath);
+ attributes.put(ACLFileAccessControlProvider.NAME, getTestName());
+
+
+ ACLFileAccessControlProviderImpl aclProvider = new ACLFileAccessControlProviderImpl(attributes, _broker);
+ try
+ {
+ aclProvider.create();
+ fail("Exception is expected on validation with non-existing ACL file");
+ }
+ catch (IllegalConfigurationException e)
+ {
+ assertEquals("Unexpected exception message:" + e.getMessage(), String.format("ACL file '%s' is not found", aclFilePath ), e.getMessage());
+ }
+ }
+
+}
diff --git a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
index 79f73b5ca9..7574cc3533 100644
--- a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
+++ b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
@@ -1322,6 +1322,12 @@ public class AMQChannel<T extends AMQProtocolSession<T>>
return _subject;
}
+ public ChannelMethodProcessor getMethodProcessor()
+ {
+ // TODO
+ return null;
+ }
+
private class ImmediateAction implements Action<MessageInstance>
{
diff --git a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ChannelMethodProcessor.java b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ChannelMethodProcessor.java
new file mode 100644
index 0000000000..d8c7115316
--- /dev/null
+++ b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ChannelMethodProcessor.java
@@ -0,0 +1,25 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.protocol.v0_8;
+
+public interface ChannelMethodProcessor
+{
+}
diff --git a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java
index d8300709f2..6f4c1d91d5 100644
--- a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java
+++ b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodDispatcherImpl.java
@@ -1,2237 +1,2266 @@
-/*
- *
- * 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 java.security.AccessControlException;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.UUID;
-
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.AMQConnectionException;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.exchange.ExchangeDefaults;
-import org.apache.qpid.framing.*;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.exchange.ExchangeImpl;
-import org.apache.qpid.server.filter.AMQInvalidArgumentException;
-import org.apache.qpid.server.flow.FlowCreditManager;
-import org.apache.qpid.server.flow.MessageOnlyCreditManager;
-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;
-import org.apache.qpid.server.model.ExclusivityPolicy;
-import org.apache.qpid.server.model.LifetimePolicy;
-import org.apache.qpid.server.model.NoFactoryForTypeException;
-import org.apache.qpid.server.model.Queue;
-import org.apache.qpid.server.model.State;
-import org.apache.qpid.server.model.UnknownConfiguredObjectException;
-import org.apache.qpid.server.model.port.AmqpPort;
-import org.apache.qpid.server.protocol.AMQSessionModel;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.QueueArgumentsConverter;
-import org.apache.qpid.server.security.SubjectCreator;
-import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
-import org.apache.qpid.server.virtualhost.ExchangeExistsException;
-import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;
-import org.apache.qpid.server.virtualhost.QueueExistsException;
-import org.apache.qpid.server.virtualhost.RequiredExchangeException;
-import org.apache.qpid.server.virtualhost.ReservedExchangeNameException;
-import org.apache.qpid.server.virtualhost.VirtualHostImpl;
-
-public class ServerMethodDispatcherImpl implements MethodDispatcher
-{
- private static final Logger _logger = Logger.getLogger(ServerMethodDispatcherImpl.class);
-
- private final AMQProtocolSession<?> _connection;
-
-
- public static MethodDispatcher createMethodDispatcher(AMQProtocolSession<?> connection)
- {
- return new ServerMethodDispatcherImpl(connection);
- }
-
-
- public ServerMethodDispatcherImpl(AMQProtocolSession<?> connection)
- {
- _connection = connection;
- }
-
-
- protected final AMQProtocolSession<?> getConnection()
- {
- return _connection;
- }
-
- public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
- {
- final AMQChannel channel = _connection.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
-
- if(ProtocolVersion.v0_91.equals(_connection.getProtocolVersion()) )
- {
- throw new AMQException(AMQConstant.COMMAND_INVALID, "AccessRequest not present in AMQP versions other than 0-8, 0-9");
- }
-
- // We don't implement access control class, but to keep clients happy that expect it
- // always use the "0" ticket.
- AccessRequestOkBody response = methodRegistry.createAccessRequestOkBody(0);
- channel.sync();
- _connection.writeFrame(response.generateFrame(channelId));
- return true;
- }
-
- public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
- {
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Ack(Tag:" + body.getDeliveryTag() + ":Mult:" + body.getMultiple() + ") received on channel " + channelId);
- }
-
- final AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- // this method throws an AMQException if the delivery tag is not known
- channel.acknowledgeMessage(body.getDeliveryTag(), body.getMultiple());
- return true;
- }
-
- public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
- {
- final AMQChannel channel = _connection.getChannel(channelId);
-
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("BasicCancel: for:" + body.getConsumerTag() +
- " nowait:" + body.getNowait());
- }
-
- channel.unsubscribeConsumer(body.getConsumerTag());
- if (!body.getNowait())
- {
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- BasicCancelOkBody cancelOkBody = methodRegistry.createBasicCancelOkBody(body.getConsumerTag());
- channel.sync();
- _connection.writeFrame(cancelOkBody.generateFrame(channelId));
- }
- return true;
- }
-
- public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
- {
- AMQChannel channel = _connection.getChannel(channelId);
- VirtualHostImpl<?,?,?> vHost = _connection.getVirtualHost();
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
- else
- {
- channel.sync();
- String queueName = body.getQueue() == null ? null : body.getQueue().asString();
- if (_logger.isDebugEnabled())
- {
- _logger.debug("BasicConsume: from '" + queueName +
- "' for:" + body.getConsumerTag() +
- " nowait:" + body.getNowait() +
- " args:" + body.getArguments());
- }
-
- MessageSource queue = queueName == null ? channel.getDefaultQueue() : vHost.getQueue(queueName);
- final Collection<MessageSource> sources = new HashSet<>();
- if(queue != null)
- {
- sources.add(queue);
- }
- else if(vHost.getContextValue(Boolean.class, "qpid.enableMultiQueueConsumers")
- && body.getArguments() != null
- && body.getArguments().get("x-multiqueue") instanceof Collection)
- {
- for(Object object : (Collection<Object>) body.getArguments().get("x-multiqueue"))
- {
- String sourceName = String.valueOf(object);
- sourceName = sourceName.trim();
- if(sourceName.length() != 0)
- {
- MessageSource source = vHost.getMessageSource(sourceName);
- if(source == null)
- {
- sources.clear();
- break;
- }
- else
- {
- sources.add(source);
- }
- }
- }
- queueName = body.getArguments().get("x-multiqueue").toString();
- }
-
- if (sources.isEmpty())
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("No queue for '" + queueName + "'");
- }
- if (queueName != null)
- {
- String msg = "No such queue, '" + queueName + "'";
- throw body.getChannelException(AMQConstant.NOT_FOUND, msg, _connection.getMethodRegistry());
- }
- else
- {
- String msg = "No queue name provided, no default queue defined.";
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED, msg, _connection.getMethodRegistry());
- }
- }
- else
- {
- final AMQShortString consumerTagName;
-
- if (body.getConsumerTag() != null)
- {
- consumerTagName = body.getConsumerTag().intern(false);
- }
- else
- {
- consumerTagName = null;
- }
-
- try
- {
- if(consumerTagName == null || channel.getSubscription(consumerTagName) == null)
- {
-
- AMQShortString consumerTag = channel.consumeFromSource(consumerTagName,
- sources,
- !body.getNoAck(),
- body.getArguments(),
- body.getExclusive(),
- body.getNoLocal());
- if (!body.getNowait())
- {
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag);
- _connection.writeFrame(responseBody.generateFrame(channelId));
-
- }
- }
- else
- {
- AMQShortString msg = AMQShortString.validValueOf("Non-unique consumer tag, '" + body.getConsumerTag() + "'");
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode
- msg, // replytext
- body.getClazz(),
- body.getMethod());
- _connection.writeFrame(responseBody.generateFrame(0));
- }
-
- }
- catch (AMQInvalidArgumentException ise)
- {
- _logger.debug("Closing connection due to invalid selector");
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.ARGUMENT_INVALID.getCode(),
- AMQShortString.validValueOf(ise.getMessage()),
- body.getClazz(),
- body.getMethod());
- _connection.writeFrame(responseBody.generateFrame(channelId));
-
-
- }
- catch (AMQQueue.ExistingExclusiveConsumer e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- "Cannot subscribe to queue "
- + queue.getName()
- + " as it already has an existing exclusive consumer",
- _connection.getMethodRegistry());
- }
- catch (AMQQueue.ExistingConsumerPreventsExclusive e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- "Cannot subscribe to queue "
- + queue.getName()
- + " exclusively as it already has a consumer",
- _connection.getMethodRegistry());
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- "Cannot subscribe to queue "
- + queue.getName()
- + " permission denied", _connection.getMethodRegistry());
- }
- catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- "Cannot subscribe to queue "
- + queue.getName()
- + " as it already has an incompatible exclusivity policy",
- _connection.getMethodRegistry());
- }
-
- }
- }
- return true;
- }
-
- public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
- {
-
- VirtualHostImpl vHost = _connection.getVirtualHost();
-
- AMQChannel channel = _connection.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
- else
- {
- channel.sync();
- AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueue(body.getQueue().toString());
- if (queue == null)
- {
- _logger.info("No queue for '" + body.getQueue() + "'");
- if(body.getQueue()!=null)
- {
- throw body.getConnectionException(AMQConstant.NOT_FOUND,
- "No such queue, '" + body.getQueue() + "'",
- _connection.getMethodRegistry());
- }
- else
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "No queue name provided, no default queue defined.",
- _connection.getMethodRegistry());
- }
- }
- else
- {
-
- try
- {
- if (!performGet(queue, _connection, channel, !body.getNoAck()))
- {
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
-
- BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null);
-
-
- _connection.writeFrame(responseBody.generateFrame(channelId));
- }
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(), _connection.getMethodRegistry());
- }
- catch (MessageSource.ExistingExclusiveConsumer e)
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Queue has an exclusive consumer",
- _connection.getMethodRegistry());
- }
- catch (MessageSource.ExistingConsumerPreventsExclusive e)
- {
- throw body.getConnectionException(AMQConstant.INTERNAL_ERROR,
- "The GET request has been evaluated as an exclusive consumer, " +
- "this is likely due to a programming error in the Qpid broker",
- _connection.getMethodRegistry());
- }
- catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Queue has an incompatible exclusivit policy",
- _connection.getMethodRegistry());
- }
- }
- }
- return true;
- }
-
- public static boolean performGet(final AMQQueue queue,
- final AMQProtocolSession session,
- final AMQChannel channel,
- final boolean acks)
- throws AMQException, MessageSource.ExistingConsumerPreventsExclusive,
- MessageSource.ExistingExclusiveConsumer, MessageSource.ConsumerAccessRefused
- {
-
- final FlowCreditManager singleMessageCredit = new MessageOnlyCreditManager(1L);
-
- final GetDeliveryMethod getDeliveryMethod =
- new GetDeliveryMethod(singleMessageCredit, session, channel, queue);
- final RecordDeliveryMethod getRecordMethod = new RecordDeliveryMethod()
- {
-
- public void recordMessageDelivery(final ConsumerImpl sub, final MessageInstance entry, final long deliveryTag)
- {
- channel.addUnacknowledgedMessage(entry, deliveryTag, null);
- }
- };
-
- ConsumerTarget_0_8 target;
- EnumSet<ConsumerImpl.Option> options = EnumSet.of(ConsumerImpl.Option.TRANSIENT, ConsumerImpl.Option.ACQUIRES,
- ConsumerImpl.Option.SEES_REQUEUES);
- if(acks)
- {
-
- target = ConsumerTarget_0_8.createAckTarget(channel,
- AMQShortString.EMPTY_STRING, null,
- singleMessageCredit, getDeliveryMethod, getRecordMethod);
- }
- else
- {
- target = ConsumerTarget_0_8.createGetNoAckTarget(channel,
- AMQShortString.EMPTY_STRING, null,
- singleMessageCredit, getDeliveryMethod, getRecordMethod);
- }
-
- ConsumerImpl sub = queue.addConsumer(target, null, AMQMessage.class, "", options);
- sub.flush();
- sub.close();
- return(getDeliveryMethod.hasDeliveredMessage());
-
-
- }
-
-
- private static class GetDeliveryMethod implements ClientDeliveryMethod
- {
-
- private final FlowCreditManager _singleMessageCredit;
- private final AMQProtocolSession _session;
- private final AMQChannel _channel;
- private final AMQQueue _queue;
- private boolean _deliveredMessage;
-
- public GetDeliveryMethod(final FlowCreditManager singleMessageCredit,
- final AMQProtocolSession session,
- final AMQChannel channel, final AMQQueue queue)
- {
- _singleMessageCredit = singleMessageCredit;
- _session = session;
- _channel = channel;
- _queue = queue;
- }
-
- @Override
- public long deliverToClient(final ConsumerImpl sub, final ServerMessage message,
- final InstanceProperties props, final long deliveryTag)
- {
- _singleMessageCredit.useCreditForMessage(message.getSize());
- long size =_session.getProtocolOutputConverter().writeGetOk(message,
- props,
- _channel.getChannelId(),
- deliveryTag,
- _queue.getQueueDepthMessages());
-
- _deliveredMessage = true;
- return size;
- }
-
- public boolean hasDeliveredMessage()
- {
- return _deliveredMessage;
- }
- }
-
- public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Publish received on channel " + channelId);
- }
-
- AMQShortString exchangeName = body.getExchange();
- VirtualHostImpl vHost = _connection.getVirtualHost();
-
- // TODO: check the delivery tag field details - is it unique across the broker or per subscriber?
-
- MessageDestination destination;
-
- if (exchangeName == null || AMQShortString.EMPTY_STRING.equals(exchangeName))
- {
- destination = vHost.getDefaultDestination();
- }
- else
- {
- destination = vHost.getMessageDestination(exchangeName.toString());
- }
-
- // if the exchange does not exist we raise a channel exception
- if (destination == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange name",
- _connection.getMethodRegistry());
- }
- else
- {
- // The partially populated BasicDeliver frame plus the received route body
- // is stored in the channel. Once the final body frame has been received
- // it is routed to the exchange.
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- MessagePublishInfo info = new MessagePublishInfo(body.getExchange(),
- body.getImmediate(),
- body.getMandatory(),
- body.getRoutingKey());
- info.setExchange(exchangeName);
- try
- {
- channel.setPublishFrame(info, destination);
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- _connection.getMethodRegistry());
- }
- }
- return true;
- }
-
- public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
- {
- AMQChannel channel = _connection.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
- channel.sync();
- channel.setCredit(body.getPrefetchSize(), body.getPrefetchCount());
-
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createBasicQosOkBody();
- _connection.writeFrame(responseBody.generateFrame(channelId));
-
- return true;
- }
-
- public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
- {
- _logger.debug("Recover received on protocol session " + _connection
- + " and channel " + channelId);
- AMQChannel channel = _connection.getChannel(channelId);
-
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- channel.resend();
-
- // Qpid 0-8 hacks a synchronous -ok onto recover.
- // In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
- if(_connection.getProtocolVersion().equals(ProtocolVersion.v8_0))
- {
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
- channel.sync();
- _connection.writeFrame(recoverOk.generateFrame(channelId));
-
- }
-
- return true;
- }
-
- public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
- {
-
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Rejecting:" + body.getDeliveryTag() +
- ": Requeue:" + body.getRequeue() +
- " on channel:" + channel.debugIdentity());
- }
-
- long deliveryTag = body.getDeliveryTag();
-
- MessageInstance message = channel.getUnacknowledgedMessageMap().get(deliveryTag);
-
- if (message == null)
- {
- _logger.warn("Dropping reject request as message is null for tag:" + deliveryTag);
- }
- else
- {
-
- if (message.getMessage() == null)
- {
- _logger.warn("Message has already been purged, unable to Reject.");
- }
- else
- {
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Rejecting: DT:" + deliveryTag + "-" + message.getMessage() +
- ": Requeue:" + body.getRequeue() +
- " on channel:" + channel.debugIdentity());
- }
-
- if (body.getRequeue())
- {
- //this requeue represents a message rejected from the pre-dispatch queue
- //therefore we need to amend the delivery counter.
- message.decrementDeliveryCount();
-
- channel.requeue(deliveryTag);
- }
- else
- {
- // Since the Java client abuses the reject flag for requeing after rollback, we won't set reject here
- // as it would prevent redelivery
- // message.reject();
-
- final boolean maxDeliveryCountEnabled = channel.isMaxDeliveryCountEnabled(deliveryTag);
- _logger.debug("maxDeliveryCountEnabled: "
- + maxDeliveryCountEnabled
- + " deliveryTag "
- + deliveryTag);
- if (maxDeliveryCountEnabled)
- {
- final boolean deliveredTooManyTimes = channel.isDeliveredTooManyTimes(deliveryTag);
- _logger.debug("deliveredTooManyTimes: "
- + deliveredTooManyTimes
- + " deliveryTag "
- + deliveryTag);
- if (deliveredTooManyTimes)
- {
- channel.deadLetter(body.getDeliveryTag());
- }
- else
- {
- //this requeue represents a message rejected because of a recover/rollback that we
- //are not ready to DLQ. We rely on the reject command to resend from the unacked map
- //and therefore need to increment the delivery counter so we cancel out the effect
- //of the AMQChannel#resend() decrement.
- message.incrementDeliveryCount();
- }
- }
- else
- {
- channel.requeue(deliveryTag);
- }
- }
- }
- }
- return true;
- }
-
- public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
- {
- VirtualHostImpl virtualHost = _connection.getVirtualHost();
-
- // Protect the broker against out of order frame request.
- if (virtualHost == null)
- {
- throw new AMQException(AMQConstant.COMMAND_INVALID, "Virtualhost has not yet been set. ConnectionOpen has not been called.", null);
- }
- _logger.info("Connecting to: " + virtualHost.getName());
-
- final AMQChannel channel = new AMQChannel(_connection, channelId, virtualHost.getMessageStore());
-
- _connection.addChannel(channel);
-
- ChannelOpenOkBody response;
-
-
- response = _connection.getMethodRegistry().createChannelOpenOkBody();
-
-
- _connection.writeFrame(response.generateFrame(channelId));
- return true;
- }
-
-
- public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
-
- public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
- {
-
- if (_logger.isInfoEnabled())
- {
- _logger.info("Received channel close for id " + channelId
- + " citing class " + body.getClassId() +
- " and method " + body.getMethodId());
- }
-
-
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getConnectionException(AMQConstant.CHANNEL_ERROR,
- "Trying to close unknown channel",
- _connection.getMethodRegistry());
- }
- channel.sync();
- _connection.closeChannel(channelId);
- // Client requested closure so we don't wait for ok we send it
- _connection.closeChannelOk(channelId);
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- ChannelCloseOkBody responseBody = methodRegistry.createChannelCloseOkBody();
- _connection.writeFrame(responseBody.generateFrame(channelId));
- return true;
- }
-
-
- public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
- {
-
- _logger.info("Received channel-close-ok for channel-id " + channelId);
-
- // Let the Protocol Session know the channel is now closed.
- _connection.closeChannelOk(channelId);
- return true;
- }
-
-
- public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
- {
- final AMQProtocolSession<?> connection = getConnection();
-
-
- AMQChannel channel = connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
- }
- channel.sync();
- channel.setSuspended(!body.getActive());
- _logger.debug("Channel.Flow for channel " + channelId + ", active=" + body.getActive());
-
- MethodRegistry methodRegistry = connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createChannelFlowOkBody(body.getActive());
- connection.writeFrame(responseBody.generateFrame(channelId));
- return true;
- }
-
- public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
-
- public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
- {
-
- //ignore leading '/'
- String virtualHostName;
- if ((body.getVirtualHost() != null) && body.getVirtualHost().charAt(0) == '/')
- {
- virtualHostName = new StringBuilder(body.getVirtualHost().subSequence(1, body.getVirtualHost().length())).toString();
- }
- else
- {
- virtualHostName = body.getVirtualHost() == null ? null : String.valueOf(body.getVirtualHost());
- }
-
- VirtualHostImpl virtualHost = ((AmqpPort) _connection.getPort()).getVirtualHost(virtualHostName);
-
- if (virtualHost == null)
- {
- throw body.getConnectionException(AMQConstant.NOT_FOUND, "Unknown virtual host: '" + virtualHostName + "'",
- _connection.getMethodRegistry());
- }
- else
- {
- // Check virtualhost access
- if (virtualHost.getState() != State.ACTIVE)
- {
- throw body.getConnectionException(AMQConstant.CONNECTION_FORCED,
- "Virtual host '" + virtualHost.getName() + "' is not active",
- _connection.getMethodRegistry());
- }
-
- _connection.setVirtualHost(virtualHost);
- try
- {
- virtualHost.getSecurityManager().authoriseCreateConnection(_connection);
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- _connection.getMethodRegistry());
- }
-
- // See Spec (0.8.2). Section 3.1.2 Virtual Hosts
- if (_connection.getContextKey() == null)
- {
- _connection.setContextKey(new AMQShortString(Long.toString(System.currentTimeMillis())));
- }
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createConnectionOpenOkBody(body.getVirtualHost());
-
- _connection.writeFrame(responseBody.generateFrame(channelId));
- }
- return true;
- }
-
-
- public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException
- {
- if (_logger.isInfoEnabled())
- {
- _logger.info("ConnectionClose received with reply code/reply text " + body.getReplyCode() + "/" +
- body.getReplyText() + " for " + _connection);
- }
- try
- {
- _connection.closeSession();
- }
- catch (Exception e)
- {
- _logger.error("Error closing protocol session: " + e, e);
- }
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- ConnectionCloseOkBody responseBody = methodRegistry.createConnectionCloseOkBody();
- _connection.writeFrame(responseBody.generateFrame(channelId));
-
- _connection.closeProtocolSession();
-
- return true;
- }
-
-
- public boolean dispatchConnectionCloseOk(ConnectionCloseOkBody body, int channelId) throws AMQException
- {
- _logger.info("Received Connection-close-ok");
-
- try
- {
- _connection.closeSession();
- }
- catch (Exception e)
- {
- _logger.error("Error closing protocol session: " + e, e);
- }
- return true;
- }
-
- public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
-
- public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
-
- public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
- {
- Broker<?> broker = _connection.getBroker();
-
- SubjectCreator subjectCreator = _connection.getSubjectCreator();
-
- SaslServer ss = _connection.getSaslServer();
- if (ss == null)
- {
- throw new AMQException("No SASL context set up in session");
- }
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse());
- switch (authResult.getStatus())
- {
- case ERROR:
- Exception cause = authResult.getCause();
-
- _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
-
- ConnectionCloseBody connectionCloseBody =
- methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),
- AMQConstant.NOT_ALLOWED.getName(),
- body.getClazz(),
- body.getMethod());
-
- _connection.writeFrame(connectionCloseBody.generateFrame(0));
- disposeSaslServer(_connection);
- break;
- case SUCCESS:
- if (_logger.isInfoEnabled())
- {
- _logger.info("Connected as: " + authResult.getSubject());
- }
-
- int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
-
- if(frameMax <= 0)
- {
- frameMax = Integer.MAX_VALUE;
- }
-
- ConnectionTuneBody tuneBody =
- methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),
- frameMax,
- broker.getConnection_heartBeatDelay());
- _connection.writeFrame(tuneBody.generateFrame(0));
- _connection.setAuthorizedSubject(authResult.getSubject());
- disposeSaslServer(_connection);
- break;
- case CONTINUE:
-
- ConnectionSecureBody
- secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
- _connection.writeFrame(secureBody.generateFrame(0));
- }
- return true;
- }
-
- private void disposeSaslServer(AMQProtocolSession ps)
- {
- SaslServer ss = ps.getSaslServer();
- if (ss != null)
- {
- ps.setSaslServer(null);
- try
- {
- ss.dispose();
- }
- catch (SaslException e)
- {
- _logger.error("Error disposing of Sasl server: " + e);
- }
- }
- }
-
- public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
- {
- Broker<?> broker = _connection.getBroker();
-
- _logger.info("SASL Mechanism selected: " + body.getMechanism());
- _logger.info("Locale selected: " + body.getLocale());
-
- SubjectCreator subjectCreator = _connection.getSubjectCreator();
- SaslServer ss = null;
- try
- {
- ss = subjectCreator.createSaslServer(String.valueOf(body.getMechanism()),
- _connection.getLocalFQDN(),
- _connection.getPeerPrincipal());
-
- if (ss == null)
- {
- throw body.getConnectionException(AMQConstant.RESOURCE_ERROR,
- "Unable to create SASL Server:" + body.getMechanism(),
- _connection.getMethodRegistry());
- }
-
- _connection.setSaslServer(ss);
-
- final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse());
- //save clientProperties
- _connection.setClientProperties(body.getClientProperties());
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
-
- switch (authResult.getStatus())
- {
- case ERROR:
- Exception cause = authResult.getCause();
-
- _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
-
- ConnectionCloseBody closeBody =
- methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode
- AMQConstant.NOT_ALLOWED.getName(),
- body.getClazz(),
- body.getMethod());
-
- _connection.writeFrame(closeBody.generateFrame(0));
- disposeSaslServer(_connection);
- break;
-
- case SUCCESS:
- if (_logger.isInfoEnabled())
- {
- _logger.info("Connected as: " + authResult.getSubject());
- }
- _connection.setAuthorizedSubject(authResult.getSubject());
-
- int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
-
- if(frameMax <= 0)
- {
- frameMax = Integer.MAX_VALUE;
- }
-
- ConnectionTuneBody
- tuneBody = methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),
- frameMax,
- broker.getConnection_heartBeatDelay());
- _connection.writeFrame(tuneBody.generateFrame(0));
- break;
- case CONTINUE:
- ConnectionSecureBody
- secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
- _connection.writeFrame(secureBody.generateFrame(0));
- }
- }
- catch (SaslException e)
- {
- disposeSaslServer(_connection);
- throw new AMQException("SASL error: " + e, e);
- }
- return true;
- }
-
- public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
- {
- final AMQProtocolSession<?> connection = getConnection();
-
- if (_logger.isDebugEnabled())
- {
- _logger.debug(body);
- }
-
- connection.initHeartbeats(body.getHeartbeat());
-
- int brokerFrameMax = connection.getBroker().getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
- if(brokerFrameMax <= 0)
- {
- brokerFrameMax = Integer.MAX_VALUE;
- }
-
- if(body.getFrameMax() > (long) brokerFrameMax)
- {
- throw new AMQConnectionException(AMQConstant.SYNTAX_ERROR,
- "Attempt to set max frame size to " + body.getFrameMax()
- + " greater than the broker will allow: "
- + brokerFrameMax,
- body.getClazz(), body.getMethod(),
- connection.getMethodRegistry(),null);
- }
- else if(body.getFrameMax() > 0 && body.getFrameMax() < AMQConstant.FRAME_MIN_SIZE.getCode())
- {
- throw new AMQConnectionException(AMQConstant.SYNTAX_ERROR,
- "Attempt to set max frame size to " + body.getFrameMax()
- + " which is smaller than the specification definined minimum: "
- + AMQConstant.FRAME_MIN_SIZE.getCode(),
- body.getClazz(), body.getMethod(),
- connection.getMethodRegistry(),null);
- }
- int frameMax = body.getFrameMax() == 0 ? brokerFrameMax : (int) body.getFrameMax();
- connection.setMaxFrameSize(frameMax);
-
- long maxChannelNumber = body.getChannelMax();
- //0 means no implied limit, except that forced by protocol limitations (0xFFFF)
- connection.setMaximumNumberOfChannels(maxChannelNumber == 0 ? 0xFFFFL : maxChannelNumber);
- return true;
- }
-
- public static final int OK = 0;
- public static final int EXCHANGE_NOT_FOUND = 1;
- public static final int QUEUE_NOT_FOUND = 2;
- public static final int NO_BINDINGS = 3;
- public static final int QUEUE_NOT_BOUND = 4;
- public static final int NO_QUEUE_BOUND_WITH_RK = 5;
- public static final int SPECIFIC_QUEUE_NOT_BOUND_WITH_RK = 6;
-
- public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
- {
- VirtualHostImpl virtualHost = _connection.getVirtualHost();
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
-
- final AMQChannel channel = _connection.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
- channel.sync();
-
-
- AMQShortString exchangeName = body.getExchange();
- AMQShortString queueName = body.getQueue();
- AMQShortString routingKey = body.getRoutingKey();
- ExchangeBoundOkBody response;
-
- if(isDefaultExchange(exchangeName))
- {
- if(routingKey == null)
- {
- if(queueName == null)
- {
- response = methodRegistry.createExchangeBoundOkBody(virtualHost.getQueues().isEmpty() ? NO_BINDINGS : OK, null);
- }
- else
- {
- AMQQueue queue = virtualHost.getQueue(queueName.toString());
- if (queue == null)
- {
-
- response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode
- AMQShortString.validValueOf("Queue '" + queueName + "' not found")); // replyText
- }
- else
- {
- response = methodRegistry.createExchangeBoundOkBody(OK, null);
- }
- }
- }
- else
- {
- if(queueName == null)
- {
- response = methodRegistry.createExchangeBoundOkBody(virtualHost.getQueue(routingKey.toString()) == null ? NO_QUEUE_BOUND_WITH_RK : OK, null);
- }
- else
- {
- AMQQueue queue = virtualHost.getQueue(queueName.toString());
- if (queue == null)
- {
-
- response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode
- AMQShortString.validValueOf("Queue '" + queueName + "' not found")); // replyText
- }
- else
- {
- response = methodRegistry.createExchangeBoundOkBody(queueName.equals(routingKey) ? OK : SPECIFIC_QUEUE_NOT_BOUND_WITH_RK, null);
- }
- }
- }
- }
- else
- {
- ExchangeImpl exchange = virtualHost.getExchange(exchangeName.toString());
- if (exchange == null)
- {
-
-
- response = methodRegistry.createExchangeBoundOkBody(EXCHANGE_NOT_FOUND,
- AMQShortString.validValueOf("Exchange '" + exchangeName + "' not found"));
- }
- else if (routingKey == null)
- {
- if (queueName == null)
- {
- if (exchange.hasBindings())
- {
- response = methodRegistry.createExchangeBoundOkBody(OK, null);
- }
- else
- {
-
- response = methodRegistry.createExchangeBoundOkBody(NO_BINDINGS, // replyCode
- null); // replyText
- }
- }
- else
- {
-
- AMQQueue queue = virtualHost.getQueue(queueName.toString());
- if (queue == null)
- {
-
- response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode
- AMQShortString.validValueOf("Queue '" + queueName + "' not found")); // replyText
- }
- else
- {
- if (exchange.isBound(queue))
- {
-
- response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode
- null); // replyText
- }
- else
- {
-
- response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_BOUND, // replyCode
- AMQShortString.validValueOf("Queue '" + queueName + "' not bound to exchange '" + exchangeName + "'")); // replyText
- }
- }
- }
- }
- else if (queueName != null)
- {
- AMQQueue queue = virtualHost.getQueue(queueName.toString());
- if (queue == null)
- {
-
- response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode
- AMQShortString.validValueOf("Queue '" + queueName + "' not found")); // replyText
- }
- else
- {
- String bindingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().asString();
- if (exchange.isBound(bindingKey, queue))
- {
-
- response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode
- null); // replyText
- }
- else
- {
-
- String message = "Queue '" + queueName + "' not bound with routing key '" +
- body.getRoutingKey() + "' to exchange '" + exchangeName + "'";
-
- response = methodRegistry.createExchangeBoundOkBody(SPECIFIC_QUEUE_NOT_BOUND_WITH_RK, // replyCode
- AMQShortString.validValueOf(message)); // replyText
- }
- }
- }
- else
- {
- if (exchange.isBound(body.getRoutingKey() == null ? "" : body.getRoutingKey().asString()))
- {
-
- response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode
- null); // replyText
- }
- else
- {
-
- response = methodRegistry.createExchangeBoundOkBody(NO_QUEUE_BOUND_WITH_RK, // replyCode
- AMQShortString.validValueOf("No queue bound with routing key '" + body.getRoutingKey() +
- "' to exchange '" + exchangeName + "'")); // replyText
- }
- }
- }
- _connection.writeFrame(response.generateFrame(channelId));
- return true;
- }
-
- public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
- {
- VirtualHostImpl virtualHost = _connection.getVirtualHost();
- final AMQChannel channel = _connection.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- final AMQShortString exchangeName = body.getExchange();
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + exchangeName);
- }
-
- ExchangeImpl exchange;
-
- if(isDefaultExchange(exchangeName))
- {
- if(!new AMQShortString(ExchangeDefaults.DIRECT_EXCHANGE_CLASS).equals(body.getType()))
- {
- throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare default exchange: "
- + " of type "
- + ExchangeDefaults.DIRECT_EXCHANGE_CLASS
- + " to " + body.getType() +".",
- body.getClazz(), body.getMethod(),
- _connection.getMethodRegistry(),null);
- }
- }
- else
- {
- if (body.getPassive())
- {
- exchange = virtualHost.getExchange(exchangeName.toString());
- if(exchange == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName,
- _connection.getMethodRegistry());
- }
- else if (!(body.getType() == null || body.getType().length() ==0) && !exchange.getType().equals(body.getType().asString()))
- {
-
- throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " +
- exchangeName + " of type " + exchange.getType()
- + " to " + body.getType() +".",
- body.getClazz(), body.getMethod(),
- _connection.getMethodRegistry(),null);
- }
-
- }
- else
- {
- try
- {
- String name = exchangeName == null ? null : exchangeName.intern().toString();
- String type = body.getType() == null ? null : body.getType().intern().toString();
-
- Map<String,Object> attributes = new HashMap<String, Object>();
- if(body.getArguments() != null)
- {
- attributes.putAll(FieldTable.convertToMap(body.getArguments()));
- }
- attributes.put(org.apache.qpid.server.model.Exchange.ID, null);
- attributes.put(org.apache.qpid.server.model.Exchange.NAME,name);
- attributes.put(org.apache.qpid.server.model.Exchange.TYPE,type);
- attributes.put(org.apache.qpid.server.model.Exchange.DURABLE, body.getDurable());
- attributes.put(org.apache.qpid.server.model.Exchange.LIFETIME_POLICY,
- body.getAutoDelete() ? LifetimePolicy.DELETE_ON_NO_LINKS : LifetimePolicy.PERMANENT);
- if(!attributes.containsKey(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE))
- {
- attributes.put(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE, null);
- }
- exchange = virtualHost.createExchange(attributes);
-
- }
- catch(ReservedExchangeNameException e)
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Attempt to declare exchange: " + exchangeName +
- " which begins with reserved prefix.",
- _connection.getMethodRegistry());
-
- }
- catch(ExchangeExistsException e)
- {
- exchange = e.getExistingExchange();
- if(!new AMQShortString(exchange.getType()).equals(body.getType()))
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: "
- + exchangeName + " of type "
- + exchange.getType()
- + " to " + body.getType() + ".",
- _connection.getMethodRegistry());
- }
- }
- catch(NoFactoryForTypeException e)
- {
- throw body.getConnectionException(AMQConstant.COMMAND_INVALID,
- "Unknown exchange type '"
- + e.getType()
- + "' for exchange '"
- + exchangeName
- + "'",
- _connection.getMethodRegistry());
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- _connection.getMethodRegistry());
- }
- catch (UnknownConfiguredObjectException e)
- {
- // note - since 0-8/9/9-1 can't set the alt. exchange this exception should never occur
- throw body.getConnectionException(AMQConstant.NOT_FOUND,
- "Unknown alternate exchange "
- + (e.getName() != null
- ? "name: \"" + e.getName() + "\""
- : "id: " + e.getId()),
- _connection.getMethodRegistry());
- }
- catch (IllegalArgumentException e)
- {
- throw body.getConnectionException(AMQConstant.COMMAND_INVALID,
- "Error creating exchange '"
- + exchangeName
- + "': "
- + e.getMessage(),
- _connection.getMethodRegistry());
- }
- }
- }
-
- if(!body.getNowait())
- {
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createExchangeDeclareOkBody();
- channel.sync();
- _connection.writeFrame(responseBody.generateFrame(channelId));
- }
- return true;
- }
-
- public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
- {
- VirtualHostImpl virtualHost = _connection.getVirtualHost();
- final AMQChannel channel = _connection.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
- channel.sync();
- try
- {
-
- if(isDefaultExchange(body.getExchange()))
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Default Exchange cannot be deleted",
- _connection.getMethodRegistry());
- }
-
- final String exchangeName = body.getExchange().toString();
-
- final ExchangeImpl exchange = virtualHost.getExchange(exchangeName);
- if(exchange == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "No such exchange: " + body.getExchange(),
- _connection.getMethodRegistry());
- }
-
- virtualHost.removeExchange(exchange, !body.getIfUnused());
-
- ExchangeDeleteOkBody responseBody = _connection.getMethodRegistry().createExchangeDeleteOkBody();
-
- _connection.writeFrame(responseBody.generateFrame(channelId));
- }
-
- catch (ExchangeIsAlternateException e)
- {
- throw body.getChannelException(AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange",
- _connection.getMethodRegistry());
-
- }
- catch (RequiredExchangeException e)
- {
- throw body.getChannelException(AMQConstant.NOT_ALLOWED,
- "Exchange '" + body.getExchange() + "' cannot be deleted",
- _connection.getMethodRegistry());
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- _connection.getMethodRegistry());
- }
- return true;
- }
-
- private boolean isDefaultExchange(final AMQShortString exchangeName)
- {
- return exchangeName == null || exchangeName.equals(AMQShortString.EMPTY_STRING);
- }
-
- public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
- {
- VirtualHostImpl virtualHost = _connection.getVirtualHost();
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- final AMQQueue queue;
- final AMQShortString routingKey;
-
- final AMQShortString queueName = body.getQueue();
-
- if (queueName == null)
- {
-
- queue = channel.getDefaultQueue();
-
- if (queue == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND,
- "No default queue defined on channel and queue was null",
- _connection.getMethodRegistry());
- }
-
- if (body.getRoutingKey() == null)
- {
- routingKey = AMQShortString.valueOf(queue.getName());
- }
- else
- {
- routingKey = body.getRoutingKey().intern();
- }
- }
- else
- {
- queue = virtualHost.getQueue(queueName.toString());
- routingKey = body.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : body.getRoutingKey().intern();
- }
-
- if (queue == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist.",
- _connection.getMethodRegistry());
- }
-
- if(isDefaultExchange(body.getExchange()))
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Cannot bind the queue " + queueName + " to the default exchange",
- _connection.getMethodRegistry());
- }
-
- final String exchangeName = body.getExchange().toString();
-
- final ExchangeImpl exch = virtualHost.getExchange(exchangeName);
- if (exch == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + exchangeName + " does not exist.",
- _connection.getMethodRegistry());
- }
-
-
- try
- {
-
- Map<String,Object> arguments = FieldTable.convertToMap(body.getArguments());
- String bindingKey = String.valueOf(routingKey);
-
- if (!exch.isBound(bindingKey, arguments, queue))
- {
-
- if(!exch.addBinding(bindingKey, queue, arguments) && ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(exch.getType()))
- {
- exch.replaceBinding(bindingKey, queue, arguments);
- }
- }
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- _connection.getMethodRegistry());
- }
-
- if (_logger.isInfoEnabled())
- {
- _logger.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey);
- }
- if (!body.getNowait())
- {
- channel.sync();
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createQueueBindOkBody();
- _connection.writeFrame(responseBody.generateFrame(channelId));
-
- }
- return true;
- }
-
- public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
- {
- final AMQSessionModel session = _connection.getChannel(channelId);
- VirtualHostImpl virtualHost = _connection.getVirtualHost();
-
- final AMQShortString queueName;
-
- // if we aren't given a queue name, we create one which we return to the client
- if ((body.getQueue() == null) || (body.getQueue().length() == 0))
- {
- queueName = new AMQShortString("tmp_" + UUID.randomUUID());
- }
- else
- {
- queueName = body.getQueue().intern();
- }
-
- AMQQueue queue;
-
- //TODO: do we need to check that the queue already exists with exactly the same "configuration"?
-
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- if(body.getPassive())
- {
- queue = virtualHost.getQueue(queueName.toString());
- if (queue == null)
- {
- String msg = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ").";
- throw body.getChannelException(AMQConstant.NOT_FOUND, msg, _connection.getMethodRegistry());
- }
- else
- {
- if (!queue.verifySessionAccess(channel))
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Queue "
- + queue.getName()
- + " is exclusive, but not created on this Connection.",
- _connection.getMethodRegistry());
- }
-
- //set this as the default queue on the channel:
- channel.setDefaultQueue(queue);
- }
- }
- else
- {
-
- try
- {
-
- queue = createQueue(channel, queueName, body, virtualHost, _connection);
-
- }
- catch(QueueExistsException qe)
- {
-
- queue = qe.getExistingQueue();
-
- if (!queue.verifySessionAccess(channel))
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Queue "
- + queue.getName()
- + " is exclusive, but not created on this Connection.",
- _connection.getMethodRegistry());
- }
- else if(queue.isExclusive() != body.getExclusive())
- {
-
- throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
- "Cannot re-declare queue '"
- + queue.getName()
- + "' with different exclusivity (was: "
- + queue.isExclusive()
- + " requested "
- + body.getExclusive()
- + ")",
- _connection.getMethodRegistry());
- }
- else if((body.getAutoDelete() && queue.getLifetimePolicy() != LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS)
- || (!body.getAutoDelete() && queue.getLifetimePolicy() != ((body.getExclusive() && !body.getDurable()) ? LifetimePolicy.DELETE_ON_CONNECTION_CLOSE : LifetimePolicy.PERMANENT)))
- {
- throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
- "Cannot re-declare queue '"
- + queue.getName()
- + "' with different lifetime policy (was: "
- + queue.getLifetimePolicy()
- + " requested autodelete: "
- + body.getAutoDelete()
- + ")",
- _connection.getMethodRegistry());
- }
- else if(queue.isDurable() != body.getDurable())
- {
- throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
- "Cannot re-declare queue '"
- + queue.getName()
- + "' with different durability (was: "
- + queue.isDurable()
- + " requested "
- + body.getDurable()
- + ")",
- _connection.getMethodRegistry());
- }
-
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- _connection.getMethodRegistry());
- }
-
- //set this as the default queue on the channel:
- channel.setDefaultQueue(queue);
- }
-
- if (!body.getNowait())
- {
- channel.sync();
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- QueueDeclareOkBody responseBody =
- methodRegistry.createQueueDeclareOkBody(queueName,
- queue.getQueueDepthMessages(),
- queue.getConsumerCount());
- _connection.writeFrame(responseBody.generateFrame(channelId));
-
- _logger.info("Queue " + queueName + " declared successfully");
- }
- return true;
- }
-
- protected AMQQueue createQueue(final AMQChannel channel, final AMQShortString queueName,
- QueueDeclareBody body,
- final VirtualHostImpl virtualHost,
- final AMQProtocolSession session)
- throws AMQException, QueueExistsException
- {
-
- final boolean durable = body.getDurable();
- final boolean autoDelete = body.getAutoDelete();
- final boolean exclusive = body.getExclusive();
-
-
- Map<String, Object> attributes =
- QueueArgumentsConverter.convertWireArgsToModel(FieldTable.convertToMap(body.getArguments()));
- final String queueNameString = AMQShortString.toString(queueName);
- attributes.put(Queue.NAME, queueNameString);
- attributes.put(Queue.ID, UUID.randomUUID());
- attributes.put(Queue.DURABLE, durable);
-
- LifetimePolicy lifetimePolicy;
- ExclusivityPolicy exclusivityPolicy;
-
- if(exclusive)
- {
- lifetimePolicy = autoDelete
- ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS
- : durable ? LifetimePolicy.PERMANENT : LifetimePolicy.DELETE_ON_CONNECTION_CLOSE;
- exclusivityPolicy = durable ? ExclusivityPolicy.CONTAINER : ExclusivityPolicy.CONNECTION;
- }
- else
- {
- lifetimePolicy = autoDelete ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS : LifetimePolicy.PERMANENT;
- exclusivityPolicy = ExclusivityPolicy.NONE;
- }
-
- attributes.put(Queue.EXCLUSIVE, exclusivityPolicy);
- attributes.put(Queue.LIFETIME_POLICY, lifetimePolicy);
-
-
- final AMQQueue queue = virtualHost.createQueue(attributes);
-
- return queue;
- }
-
- public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
- {
- VirtualHostImpl virtualHost = _connection.getVirtualHost();
-
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
- channel.sync();
- AMQQueue queue;
- if (body.getQueue() == null)
- {
-
- //get the default queue on the channel:
- queue = channel.getDefaultQueue();
- }
- else
- {
- queue = virtualHost.getQueue(body.getQueue().toString());
- }
-
- if (queue == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
- _connection.getMethodRegistry());
-
- }
- else
- {
- if (body.getIfEmpty() && !queue.isEmpty())
- {
- throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is not empty.",
- _connection.getMethodRegistry());
- }
- else if (body.getIfUnused() && !queue.isUnused())
- {
- // TODO - Error code
- throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is still used.",
- _connection.getMethodRegistry());
- }
- else
- {
- if (!queue.verifySessionAccess(channel))
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Queue "
- + queue.getName()
- + " is exclusive, but not created on this Connection.",
- _connection.getMethodRegistry());
- }
-
- int purged = 0;
- try
- {
- purged = virtualHost.removeQueue(queue);
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- _connection.getMethodRegistry());
- }
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- QueueDeleteOkBody responseBody = methodRegistry.createQueueDeleteOkBody(purged);
- _connection.writeFrame(responseBody.generateFrame(channelId));
- }
- }
- return true;
- }
-
- public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
- {
- VirtualHostImpl virtualHost = _connection.getVirtualHost();
-
- AMQChannel channel = _connection.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
- AMQQueue queue;
- if(body.getQueue() == null)
- {
-
- //get the default queue on the channel:
- queue = channel.getDefaultQueue();
-
- if(queue == null)
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "No queue specified.",
- _connection.getMethodRegistry());
- }
- }
- else
- {
- queue = virtualHost.getQueue(body.getQueue().toString());
- }
-
- if(queue == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
- _connection.getMethodRegistry());
- }
- else
- {
- if (!queue.verifySessionAccess(channel))
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Queue is exclusive, but not created on this Connection.",
- _connection.getMethodRegistry());
- }
-
- long purged = 0;
- try
- {
- purged = queue.clearQueue();
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- _connection.getMethodRegistry());
- }
-
-
- if(!body.getNowait())
- {
- channel.sync();
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged);
- _connection.writeFrame(responseBody.generateFrame(channelId));
-
- }
- }
- return true;
- }
-
-
- public boolean dispatchTxCommit(TxCommitBody body, final int channelId) throws AMQException
- {
- try
- {
- if (_logger.isDebugEnabled())
- {
- _logger.debug("Commit received on channel " + channelId);
- }
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
- channel.commit(new Runnable()
- {
-
- @Override
- public void run()
- {
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody();
- _connection.writeFrame(responseBody.generateFrame(channelId));
- }
- }, true);
-
-
-
- }
- catch (AMQException e)
- {
- throw body.getChannelException(e.getErrorCode(), "Failed to commit: " + e.getMessage(),
- _connection.getMethodRegistry());
- }
- return true;
- }
-
- public boolean dispatchTxRollback(TxRollbackBody body, final int channelId) throws AMQException
- {
- try
- {
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
-
-
- final MethodRegistry methodRegistry = _connection.getMethodRegistry();
- final AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody();
-
- Runnable task = new Runnable()
- {
-
- public void run()
- {
- _connection.writeFrame(responseBody.generateFrame(channelId));
- }
- };
-
- channel.rollback(task);
-
- //Now resend all the unacknowledged messages back to the original subscribers.
- //(Must be done after the TxnRollback-ok response).
- // Why, are we not allowed to send messages back to client before the ok method?
- channel.resend();
-
- }
- catch (AMQException e)
- {
- throw body.getChannelException(e.getErrorCode(), "Failed to rollback: " + e.getMessage(),
- _connection.getMethodRegistry());
- }
- return true;
- }
-
- public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
- {
- AMQChannel channel = _connection.getChannel(channelId);
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
- }
-
- channel.setLocalTransactional();
-
- MethodRegistry methodRegistry = _connection.getMethodRegistry();
- TxSelectOkBody responseBody = methodRegistry.createTxSelectOkBody();
- _connection.writeFrame(responseBody.generateFrame(channelId));
- return true;
- }
-
- public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
- {
- final AMQProtocolSession<?> connection = getConnection();
-
- _logger.debug("Recover received on protocol session " + connection + " and channel " + channelId);
- AMQChannel channel = connection.getChannel(channelId);
-
-
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
- }
- channel.sync();
- channel.resend();
-
- MethodRegistry methodRegistry = connection.getMethodRegistry();
- AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
- connection.writeFrame(recoverOk.generateFrame(channelId));
-
- return true;
- }
-
- public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- @Override
- public boolean dispatchChannelAlert(final ChannelAlertBody body, final int channelId)
- throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
- {
- throw new UnexpectedMethodException(body);
- }
-
- public boolean dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
- {
- final AMQProtocolSession<?> connection = getConnection();
-
- if (ProtocolVersion.v8_0.equals(connection.getProtocolVersion()))
- {
- // 0-8 does not support QueueUnbind
- throw new AMQException(AMQConstant.COMMAND_INVALID, "QueueUnbind not present in AMQP version: " + connection.getProtocolVersion(), null);
- }
-
- VirtualHostImpl virtualHost = connection.getVirtualHost();
-
- final AMQQueue queue;
- final AMQShortString routingKey;
-
-
- AMQChannel channel = connection.getChannel(channelId);
- if (channel == null)
- {
- throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
- }
-
- if (body.getQueue() == null)
- {
-
- queue = channel.getDefaultQueue();
-
- if (queue == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND,
- "No default queue defined on channel and queue was null",
- connection.getMethodRegistry());
- }
-
- routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false);
-
- }
- else
- {
- queue = virtualHost.getQueue(body.getQueue().toString());
- routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false);
- }
-
- if (queue == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
- connection.getMethodRegistry());
- }
-
- if(isDefaultExchange(body.getExchange()))
- {
- throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
- "Cannot unbind the queue "
- + queue.getName()
- + " from the default exchange", connection.getMethodRegistry());
- }
-
- final ExchangeImpl exch = virtualHost.getExchange(body.getExchange() == null ? null : body.getExchange().toString());
- if (exch == null)
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + body.getExchange() + " does not exist.",
- connection.getMethodRegistry());
- }
-
- if(!exch.hasBinding(String.valueOf(routingKey), queue))
- {
- throw body.getChannelException(AMQConstant.NOT_FOUND, "No such binding", connection.getMethodRegistry());
- }
- else
- {
- try
- {
- exch.deleteBinding(String.valueOf(routingKey), queue);
- }
- catch (AccessControlException e)
- {
- throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
- e.getMessage(),
- connection.getMethodRegistry());
- }
- }
-
-
- if (_logger.isInfoEnabled())
- {
- _logger.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey);
- }
-
-
- final AMQMethodBody responseBody = connection.getMethodRegistry().createQueueUnbindOkBody();
- channel.sync();
- connection.writeFrame(responseBody.generateFrame(channelId));
- return true;
- }
-
-}
+/*
+ *
+ * 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 java.security.AccessControlException;
+import java.security.PrivilegedAction;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.UUID;
+
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.AMQConnectionException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.framing.*;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.consumer.ConsumerImpl;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.filter.AMQInvalidArgumentException;
+import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.MessageOnlyCreditManager;
+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;
+import org.apache.qpid.server.model.ExclusivityPolicy;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.NoFactoryForTypeException;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.UnknownConfiguredObjectException;
+import org.apache.qpid.server.model.port.AmqpPort;
+import org.apache.qpid.server.protocol.AMQSessionModel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueArgumentsConverter;
+import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
+import org.apache.qpid.server.virtualhost.ExchangeExistsException;
+import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException;
+import org.apache.qpid.server.virtualhost.QueueExistsException;
+import org.apache.qpid.server.virtualhost.RequiredExchangeException;
+import org.apache.qpid.server.virtualhost.ReservedExchangeNameException;
+import org.apache.qpid.server.virtualhost.VirtualHostImpl;
+
+public class ServerMethodDispatcherImpl implements MethodDispatcher
+{
+ private static final Logger _logger = Logger.getLogger(ServerMethodDispatcherImpl.class);
+
+ private final AMQProtocolSession<?> _connection;
+
+
+ private static interface ChannelAction
+ {
+ void onChannel(ChannelMethodProcessor channel);
+ }
+
+ public static MethodDispatcher createMethodDispatcher(AMQProtocolSession<?> connection)
+ {
+ return new ServerMethodDispatcherImpl(connection);
+ }
+
+
+ public ServerMethodDispatcherImpl(AMQProtocolSession<?> connection)
+ {
+ _connection = connection;
+ }
+
+
+ protected final AMQProtocolSession<?> getConnection()
+ {
+ return _connection;
+ }
+
+ private void processChannelMethod(int channelId, final ChannelAction action)
+ {
+ final AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ // TODO throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ else
+ {
+ Subject.doAs(channel.getSubject(), new PrivilegedAction<Void>()
+ {
+ @Override
+ public Void run()
+ {
+ action.onChannel(channel.getMethodProcessor());
+ return null;
+ }
+ });
+ }
+
+ }
+
+ public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
+ {
+ final AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+ if(ProtocolVersion.v0_91.equals(_connection.getProtocolVersion()) )
+ {
+ throw new AMQException(AMQConstant.COMMAND_INVALID, "AccessRequest not present in AMQP versions other than 0-8, 0-9");
+ }
+
+ // We don't implement access control class, but to keep clients happy that expect it
+ // always use the "0" ticket.
+ AccessRequestOkBody response = methodRegistry.createAccessRequestOkBody(0);
+ channel.sync();
+ _connection.writeFrame(response.generateFrame(channelId));
+ return true;
+ }
+
+ public boolean dispatchBasicAck(BasicAckBody body, int channelId) throws AMQException
+ {
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Ack(Tag:" + body.getDeliveryTag() + ":Mult:" + body.getMultiple() + ") received on channel " + channelId);
+ }
+
+ final AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ // this method throws an AMQException if the delivery tag is not known
+ channel.acknowledgeMessage(body.getDeliveryTag(), body.getMultiple());
+ return true;
+ }
+
+ public boolean dispatchBasicCancel(BasicCancelBody body, int channelId) throws AMQException
+ {
+ final AMQChannel channel = _connection.getChannel(channelId);
+
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("BasicCancel: for:" + body.getConsumerTag() +
+ " nowait:" + body.getNowait());
+ }
+
+ channel.unsubscribeConsumer(body.getConsumerTag());
+ if (!body.getNowait())
+ {
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ BasicCancelOkBody cancelOkBody = methodRegistry.createBasicCancelOkBody(body.getConsumerTag());
+ channel.sync();
+ _connection.writeFrame(cancelOkBody.generateFrame(channelId));
+ }
+ return true;
+ }
+
+ public boolean dispatchBasicConsume(BasicConsumeBody body, int channelId) throws AMQException
+ {
+ AMQChannel channel = _connection.getChannel(channelId);
+ VirtualHostImpl<?,?,?> vHost = _connection.getVirtualHost();
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ else
+ {
+ channel.sync();
+ String queueName = body.getQueue() == null ? null : body.getQueue().asString();
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("BasicConsume: from '" + queueName +
+ "' for:" + body.getConsumerTag() +
+ " nowait:" + body.getNowait() +
+ " args:" + body.getArguments());
+ }
+
+ MessageSource queue = queueName == null ? channel.getDefaultQueue() : vHost.getQueue(queueName);
+ final Collection<MessageSource> sources = new HashSet<>();
+ if(queue != null)
+ {
+ sources.add(queue);
+ }
+ else if(vHost.getContextValue(Boolean.class, "qpid.enableMultiQueueConsumers")
+ && body.getArguments() != null
+ && body.getArguments().get("x-multiqueue") instanceof Collection)
+ {
+ for(Object object : (Collection<Object>) body.getArguments().get("x-multiqueue"))
+ {
+ String sourceName = String.valueOf(object);
+ sourceName = sourceName.trim();
+ if(sourceName.length() != 0)
+ {
+ MessageSource source = vHost.getMessageSource(sourceName);
+ if(source == null)
+ {
+ sources.clear();
+ break;
+ }
+ else
+ {
+ sources.add(source);
+ }
+ }
+ }
+ queueName = body.getArguments().get("x-multiqueue").toString();
+ }
+
+ if (sources.isEmpty())
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("No queue for '" + queueName + "'");
+ }
+ if (queueName != null)
+ {
+ String msg = "No such queue, '" + queueName + "'";
+ throw body.getChannelException(AMQConstant.NOT_FOUND, msg, _connection.getMethodRegistry());
+ }
+ else
+ {
+ String msg = "No queue name provided, no default queue defined.";
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED, msg, _connection.getMethodRegistry());
+ }
+ }
+ else
+ {
+ final AMQShortString consumerTagName;
+
+ if (body.getConsumerTag() != null)
+ {
+ consumerTagName = body.getConsumerTag().intern(false);
+ }
+ else
+ {
+ consumerTagName = null;
+ }
+
+ try
+ {
+ if(consumerTagName == null || channel.getSubscription(consumerTagName) == null)
+ {
+
+ AMQShortString consumerTag = channel.consumeFromSource(consumerTagName,
+ sources,
+ !body.getNoAck(),
+ body.getArguments(),
+ body.getExclusive(),
+ body.getNoLocal());
+ if (!body.getNowait())
+ {
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createBasicConsumeOkBody(consumerTag);
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+
+ }
+ }
+ else
+ {
+ AMQShortString msg = AMQShortString.validValueOf("Non-unique consumer tag, '" + body.getConsumerTag() + "'");
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode
+ msg, // replytext
+ body.getClazz(),
+ body.getMethod());
+ _connection.writeFrame(responseBody.generateFrame(0));
+ }
+
+ }
+ catch (AMQInvalidArgumentException ise)
+ {
+ _logger.debug("Closing connection due to invalid selector");
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.ARGUMENT_INVALID.getCode(),
+ AMQShortString.validValueOf(ise.getMessage()),
+ body.getClazz(),
+ body.getMethod());
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+
+
+ }
+ catch (AMQQueue.ExistingExclusiveConsumer e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ "Cannot subscribe to queue "
+ + queue.getName()
+ + " as it already has an existing exclusive consumer",
+ _connection.getMethodRegistry());
+ }
+ catch (AMQQueue.ExistingConsumerPreventsExclusive e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ "Cannot subscribe to queue "
+ + queue.getName()
+ + " exclusively as it already has a consumer",
+ _connection.getMethodRegistry());
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ "Cannot subscribe to queue "
+ + queue.getName()
+ + " permission denied", _connection.getMethodRegistry());
+ }
+ catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ "Cannot subscribe to queue "
+ + queue.getName()
+ + " as it already has an incompatible exclusivity policy",
+ _connection.getMethodRegistry());
+ }
+
+ }
+ }
+ return true;
+ }
+
+ public boolean dispatchBasicGet(BasicGetBody body, int channelId) throws AMQException
+ {
+
+ VirtualHostImpl vHost = _connection.getVirtualHost();
+
+ AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ else
+ {
+ channel.sync();
+ AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueue(body.getQueue().toString());
+ if (queue == null)
+ {
+ _logger.info("No queue for '" + body.getQueue() + "'");
+ if(body.getQueue()!=null)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_FOUND,
+ "No such queue, '" + body.getQueue() + "'",
+ _connection.getMethodRegistry());
+ }
+ else
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "No queue name provided, no default queue defined.",
+ _connection.getMethodRegistry());
+ }
+ }
+ else
+ {
+
+ try
+ {
+ if (!performGet(queue, _connection, channel, !body.getNoAck()))
+ {
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+ BasicGetEmptyBody responseBody = methodRegistry.createBasicGetEmptyBody(null);
+
+
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ }
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(), _connection.getMethodRegistry());
+ }
+ catch (MessageSource.ExistingExclusiveConsumer e)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Queue has an exclusive consumer",
+ _connection.getMethodRegistry());
+ }
+ catch (MessageSource.ExistingConsumerPreventsExclusive e)
+ {
+ throw body.getConnectionException(AMQConstant.INTERNAL_ERROR,
+ "The GET request has been evaluated as an exclusive consumer, " +
+ "this is likely due to a programming error in the Qpid broker",
+ _connection.getMethodRegistry());
+ }
+ catch (MessageSource.ConsumerAccessRefused consumerAccessRefused)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Queue has an incompatible exclusivit policy",
+ _connection.getMethodRegistry());
+ }
+ }
+ }
+ return true;
+ }
+
+ public static boolean performGet(final AMQQueue queue,
+ final AMQProtocolSession session,
+ final AMQChannel channel,
+ final boolean acks)
+ throws AMQException, MessageSource.ExistingConsumerPreventsExclusive,
+ MessageSource.ExistingExclusiveConsumer, MessageSource.ConsumerAccessRefused
+ {
+
+ final FlowCreditManager singleMessageCredit = new MessageOnlyCreditManager(1L);
+
+ final GetDeliveryMethod getDeliveryMethod =
+ new GetDeliveryMethod(singleMessageCredit, session, channel, queue);
+ final RecordDeliveryMethod getRecordMethod = new RecordDeliveryMethod()
+ {
+
+ public void recordMessageDelivery(final ConsumerImpl sub, final MessageInstance entry, final long deliveryTag)
+ {
+ channel.addUnacknowledgedMessage(entry, deliveryTag, null);
+ }
+ };
+
+ ConsumerTarget_0_8 target;
+ EnumSet<ConsumerImpl.Option> options = EnumSet.of(ConsumerImpl.Option.TRANSIENT, ConsumerImpl.Option.ACQUIRES,
+ ConsumerImpl.Option.SEES_REQUEUES);
+ if(acks)
+ {
+
+ target = ConsumerTarget_0_8.createAckTarget(channel,
+ AMQShortString.EMPTY_STRING, null,
+ singleMessageCredit, getDeliveryMethod, getRecordMethod);
+ }
+ else
+ {
+ target = ConsumerTarget_0_8.createGetNoAckTarget(channel,
+ AMQShortString.EMPTY_STRING, null,
+ singleMessageCredit, getDeliveryMethod, getRecordMethod);
+ }
+
+ ConsumerImpl sub = queue.addConsumer(target, null, AMQMessage.class, "", options);
+ sub.flush();
+ sub.close();
+ return(getDeliveryMethod.hasDeliveredMessage());
+
+
+ }
+
+
+ private static class GetDeliveryMethod implements ClientDeliveryMethod
+ {
+
+ private final FlowCreditManager _singleMessageCredit;
+ private final AMQProtocolSession _session;
+ private final AMQChannel _channel;
+ private final AMQQueue _queue;
+ private boolean _deliveredMessage;
+
+ public GetDeliveryMethod(final FlowCreditManager singleMessageCredit,
+ final AMQProtocolSession session,
+ final AMQChannel channel, final AMQQueue queue)
+ {
+ _singleMessageCredit = singleMessageCredit;
+ _session = session;
+ _channel = channel;
+ _queue = queue;
+ }
+
+ @Override
+ public long deliverToClient(final ConsumerImpl sub, final ServerMessage message,
+ final InstanceProperties props, final long deliveryTag)
+ {
+ _singleMessageCredit.useCreditForMessage(message.getSize());
+ long size =_session.getProtocolOutputConverter().writeGetOk(message,
+ props,
+ _channel.getChannelId(),
+ deliveryTag,
+ _queue.getQueueDepthMessages());
+
+ _deliveredMessage = true;
+ return size;
+ }
+
+ public boolean hasDeliveredMessage()
+ {
+ return _deliveredMessage;
+ }
+ }
+
+ public boolean dispatchBasicPublish(BasicPublishBody body, int channelId) throws AMQException
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Publish received on channel " + channelId);
+ }
+
+ AMQShortString exchangeName = body.getExchange();
+ VirtualHostImpl vHost = _connection.getVirtualHost();
+
+ // TODO: check the delivery tag field details - is it unique across the broker or per subscriber?
+
+ MessageDestination destination;
+
+ if (exchangeName == null || AMQShortString.EMPTY_STRING.equals(exchangeName))
+ {
+ destination = vHost.getDefaultDestination();
+ }
+ else
+ {
+ destination = vHost.getMessageDestination(exchangeName.toString());
+ }
+
+ // if the exchange does not exist we raise a channel exception
+ if (destination == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange name",
+ _connection.getMethodRegistry());
+ }
+ else
+ {
+ // The partially populated BasicDeliver frame plus the received route body
+ // is stored in the channel. Once the final body frame has been received
+ // it is routed to the exchange.
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ MessagePublishInfo info = new MessagePublishInfo(body.getExchange(),
+ body.getImmediate(),
+ body.getMandatory(),
+ body.getRoutingKey());
+ info.setExchange(exchangeName);
+ try
+ {
+ channel.setPublishFrame(info, destination);
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+ }
+ return true;
+ }
+
+ public boolean dispatchBasicQos(BasicQosBody body, int channelId) throws AMQException
+ {
+ AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ channel.sync();
+ channel.setCredit(body.getPrefetchSize(), body.getPrefetchCount());
+
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createBasicQosOkBody();
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+
+ return true;
+ }
+
+ public boolean dispatchBasicRecover(BasicRecoverBody body, int channelId) throws AMQException
+ {
+ _logger.debug("Recover received on protocol session " + _connection
+ + " and channel " + channelId);
+ AMQChannel channel = _connection.getChannel(channelId);
+
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ channel.resend();
+
+ // Qpid 0-8 hacks a synchronous -ok onto recover.
+ // In Qpid 0-9 we create a separate sync-recover, sync-recover-ok pair to be "more" compliant
+ if(_connection.getProtocolVersion().equals(ProtocolVersion.v8_0))
+ {
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
+ channel.sync();
+ _connection.writeFrame(recoverOk.generateFrame(channelId));
+
+ }
+
+ return true;
+ }
+
+ public boolean dispatchBasicReject(BasicRejectBody body, int channelId) throws AMQException
+ {
+
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Rejecting:" + body.getDeliveryTag() +
+ ": Requeue:" + body.getRequeue() +
+ " on channel:" + channel.debugIdentity());
+ }
+
+ long deliveryTag = body.getDeliveryTag();
+
+ MessageInstance message = channel.getUnacknowledgedMessageMap().get(deliveryTag);
+
+ if (message == null)
+ {
+ _logger.warn("Dropping reject request as message is null for tag:" + deliveryTag);
+ }
+ else
+ {
+
+ if (message.getMessage() == null)
+ {
+ _logger.warn("Message has already been purged, unable to Reject.");
+ }
+ else
+ {
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Rejecting: DT:" + deliveryTag + "-" + message.getMessage() +
+ ": Requeue:" + body.getRequeue() +
+ " on channel:" + channel.debugIdentity());
+ }
+
+ if (body.getRequeue())
+ {
+ //this requeue represents a message rejected from the pre-dispatch queue
+ //therefore we need to amend the delivery counter.
+ message.decrementDeliveryCount();
+
+ channel.requeue(deliveryTag);
+ }
+ else
+ {
+ // Since the Java client abuses the reject flag for requeing after rollback, we won't set reject here
+ // as it would prevent redelivery
+ // message.reject();
+
+ final boolean maxDeliveryCountEnabled = channel.isMaxDeliveryCountEnabled(deliveryTag);
+ _logger.debug("maxDeliveryCountEnabled: "
+ + maxDeliveryCountEnabled
+ + " deliveryTag "
+ + deliveryTag);
+ if (maxDeliveryCountEnabled)
+ {
+ final boolean deliveredTooManyTimes = channel.isDeliveredTooManyTimes(deliveryTag);
+ _logger.debug("deliveredTooManyTimes: "
+ + deliveredTooManyTimes
+ + " deliveryTag "
+ + deliveryTag);
+ if (deliveredTooManyTimes)
+ {
+ channel.deadLetter(body.getDeliveryTag());
+ }
+ else
+ {
+ //this requeue represents a message rejected because of a recover/rollback that we
+ //are not ready to DLQ. We rely on the reject command to resend from the unacked map
+ //and therefore need to increment the delivery counter so we cancel out the effect
+ //of the AMQChannel#resend() decrement.
+ message.incrementDeliveryCount();
+ }
+ }
+ else
+ {
+ channel.requeue(deliveryTag);
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ public boolean dispatchChannelOpen(ChannelOpenBody body, int channelId) throws AMQException
+ {
+ VirtualHostImpl virtualHost = _connection.getVirtualHost();
+
+ // Protect the broker against out of order frame request.
+ if (virtualHost == null)
+ {
+ throw new AMQException(AMQConstant.COMMAND_INVALID, "Virtualhost has not yet been set. ConnectionOpen has not been called.", null);
+ }
+ _logger.info("Connecting to: " + virtualHost.getName());
+
+ final AMQChannel channel = new AMQChannel(_connection, channelId, virtualHost.getMessageStore());
+
+ _connection.addChannel(channel);
+
+ ChannelOpenOkBody response;
+
+
+ response = _connection.getMethodRegistry().createChannelOpenOkBody();
+
+
+ _connection.writeFrame(response.generateFrame(channelId));
+ return true;
+ }
+
+
+ public boolean dispatchAccessRequestOk(AccessRequestOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+
+ public boolean dispatchBasicCancelOk(BasicCancelOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicConsumeOk(BasicConsumeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicDeliver(BasicDeliverBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicGetEmpty(BasicGetEmptyBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicGetOk(BasicGetOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicQosOk(BasicQosOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchBasicReturn(BasicReturnBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelClose(ChannelCloseBody body, int channelId) throws AMQException
+ {
+
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Received channel close for id " + channelId
+ + " citing class " + body.getClassId() +
+ " and method " + body.getMethodId());
+ }
+
+
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getConnectionException(AMQConstant.CHANNEL_ERROR,
+ "Trying to close unknown channel",
+ _connection.getMethodRegistry());
+ }
+ channel.sync();
+ _connection.closeChannel(channelId);
+ // Client requested closure so we don't wait for ok we send it
+ _connection.closeChannelOk(channelId);
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ ChannelCloseOkBody responseBody = methodRegistry.createChannelCloseOkBody();
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ return true;
+ }
+
+
+ public boolean dispatchChannelCloseOk(ChannelCloseOkBody body, int channelId) throws AMQException
+ {
+
+ _logger.info("Received channel-close-ok for channel-id " + channelId);
+
+ // Let the Protocol Session know the channel is now closed.
+ _connection.closeChannelOk(channelId);
+ return true;
+ }
+
+
+ public boolean dispatchChannelFlow(ChannelFlowBody body, int channelId) throws AMQException
+ {
+ final AMQProtocolSession<?> connection = getConnection();
+
+
+ AMQChannel channel = connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
+ }
+ channel.sync();
+ channel.setSuspended(!body.getActive());
+ _logger.debug("Channel.Flow for channel " + channelId + ", active=" + body.getActive());
+
+ MethodRegistry methodRegistry = connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createChannelFlowOkBody(body.getActive());
+ connection.writeFrame(responseBody.generateFrame(channelId));
+ return true;
+ }
+
+ public boolean dispatchChannelFlowOk(ChannelFlowOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchChannelOpenOk(ChannelOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+
+ public boolean dispatchConnectionOpen(ConnectionOpenBody body, int channelId) throws AMQException
+ {
+
+ //ignore leading '/'
+ String virtualHostName;
+ if ((body.getVirtualHost() != null) && body.getVirtualHost().charAt(0) == '/')
+ {
+ virtualHostName = new StringBuilder(body.getVirtualHost().subSequence(1, body.getVirtualHost().length())).toString();
+ }
+ else
+ {
+ virtualHostName = body.getVirtualHost() == null ? null : String.valueOf(body.getVirtualHost());
+ }
+
+ VirtualHostImpl virtualHost = ((AmqpPort) _connection.getPort()).getVirtualHost(virtualHostName);
+
+ if (virtualHost == null)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_FOUND, "Unknown virtual host: '" + virtualHostName + "'",
+ _connection.getMethodRegistry());
+ }
+ else
+ {
+ // Check virtualhost access
+ if (virtualHost.getState() != State.ACTIVE)
+ {
+ throw body.getConnectionException(AMQConstant.CONNECTION_FORCED,
+ "Virtual host '" + virtualHost.getName() + "' is not active",
+ _connection.getMethodRegistry());
+ }
+
+ _connection.setVirtualHost(virtualHost);
+ try
+ {
+ virtualHost.getSecurityManager().authoriseCreateConnection(_connection);
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+
+ // See Spec (0.8.2). Section 3.1.2 Virtual Hosts
+ if (_connection.getContextKey() == null)
+ {
+ _connection.setContextKey(new AMQShortString(Long.toString(System.currentTimeMillis())));
+ }
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createConnectionOpenOkBody(body.getVirtualHost());
+
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ }
+ return true;
+ }
+
+
+ public boolean dispatchConnectionClose(ConnectionCloseBody body, int channelId) throws AMQException
+ {
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("ConnectionClose received with reply code/reply text " + body.getReplyCode() + "/" +
+ body.getReplyText() + " for " + _connection);
+ }
+ try
+ {
+ _connection.closeSession();
+ }
+ catch (Exception e)
+ {
+ _logger.error("Error closing protocol session: " + e, e);
+ }
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ ConnectionCloseOkBody responseBody = methodRegistry.createConnectionCloseOkBody();
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+
+ _connection.closeProtocolSession();
+
+ return true;
+ }
+
+
+ public boolean dispatchConnectionCloseOk(ConnectionCloseOkBody body, int channelId) throws AMQException
+ {
+ _logger.info("Received Connection-close-ok");
+
+ try
+ {
+ _connection.closeSession();
+ }
+ catch (Exception e)
+ {
+ _logger.error("Error closing protocol session: " + e, e);
+ }
+ return true;
+ }
+
+ public boolean dispatchConnectionOpenOk(ConnectionOpenOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionRedirect(ConnectionRedirectBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionSecure(ConnectionSecureBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionStart(ConnectionStartBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchConnectionTune(ConnectionTuneBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+
+ public boolean dispatchExchangeBoundOk(ExchangeBoundOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchExchangeDeclareOk(ExchangeDeclareOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchExchangeDeleteOk(ExchangeDeleteOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueBindOk(QueueBindOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueDeclareOk(QueueDeclareOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueDeleteOk(QueueDeleteOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueuePurgeOk(QueuePurgeOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxCommitOk(TxCommitOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxRollbackOk(TxRollbackOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchTxSelectOk(TxSelectOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+
+ public boolean dispatchConnectionSecureOk(ConnectionSecureOkBody body, int channelId) throws AMQException
+ {
+ Broker<?> broker = _connection.getBroker();
+
+ SubjectCreator subjectCreator = _connection.getSubjectCreator();
+
+ SaslServer ss = _connection.getSaslServer();
+ if (ss == null)
+ {
+ throw new AMQException("No SASL context set up in session");
+ }
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse());
+ switch (authResult.getStatus())
+ {
+ case ERROR:
+ Exception cause = authResult.getCause();
+
+ _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
+
+ ConnectionCloseBody connectionCloseBody =
+ methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(),
+ AMQConstant.NOT_ALLOWED.getName(),
+ body.getClazz(),
+ body.getMethod());
+
+ _connection.writeFrame(connectionCloseBody.generateFrame(0));
+ disposeSaslServer(_connection);
+ break;
+ case SUCCESS:
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Connected as: " + authResult.getSubject());
+ }
+
+ int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
+
+ if(frameMax <= 0)
+ {
+ frameMax = Integer.MAX_VALUE;
+ }
+
+ ConnectionTuneBody tuneBody =
+ methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),
+ frameMax,
+ broker.getConnection_heartBeatDelay());
+ _connection.writeFrame(tuneBody.generateFrame(0));
+ _connection.setAuthorizedSubject(authResult.getSubject());
+ disposeSaslServer(_connection);
+ break;
+ case CONTINUE:
+
+ ConnectionSecureBody
+ secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
+ _connection.writeFrame(secureBody.generateFrame(0));
+ }
+ return true;
+ }
+
+ private void disposeSaslServer(AMQProtocolSession ps)
+ {
+ SaslServer ss = ps.getSaslServer();
+ if (ss != null)
+ {
+ ps.setSaslServer(null);
+ try
+ {
+ ss.dispose();
+ }
+ catch (SaslException e)
+ {
+ _logger.error("Error disposing of Sasl server: " + e);
+ }
+ }
+ }
+
+ public boolean dispatchConnectionStartOk(ConnectionStartOkBody body, int channelId) throws AMQException
+ {
+ Broker<?> broker = _connection.getBroker();
+
+ _logger.info("SASL Mechanism selected: " + body.getMechanism());
+ _logger.info("Locale selected: " + body.getLocale());
+
+ SubjectCreator subjectCreator = _connection.getSubjectCreator();
+ SaslServer ss = null;
+ try
+ {
+ ss = subjectCreator.createSaslServer(String.valueOf(body.getMechanism()),
+ _connection.getLocalFQDN(),
+ _connection.getPeerPrincipal());
+
+ if (ss == null)
+ {
+ throw body.getConnectionException(AMQConstant.RESOURCE_ERROR,
+ "Unable to create SASL Server:" + body.getMechanism(),
+ _connection.getMethodRegistry());
+ }
+
+ _connection.setSaslServer(ss);
+
+ final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, body.getResponse());
+ //save clientProperties
+ _connection.setClientProperties(body.getClientProperties());
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+ switch (authResult.getStatus())
+ {
+ case ERROR:
+ Exception cause = authResult.getCause();
+
+ _logger.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
+
+ ConnectionCloseBody closeBody =
+ methodRegistry.createConnectionCloseBody(AMQConstant.NOT_ALLOWED.getCode(), // replyCode
+ AMQConstant.NOT_ALLOWED.getName(),
+ body.getClazz(),
+ body.getMethod());
+
+ _connection.writeFrame(closeBody.generateFrame(0));
+ disposeSaslServer(_connection);
+ break;
+
+ case SUCCESS:
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Connected as: " + authResult.getSubject());
+ }
+ _connection.setAuthorizedSubject(authResult.getSubject());
+
+ int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
+
+ if(frameMax <= 0)
+ {
+ frameMax = Integer.MAX_VALUE;
+ }
+
+ ConnectionTuneBody
+ tuneBody = methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),
+ frameMax,
+ broker.getConnection_heartBeatDelay());
+ _connection.writeFrame(tuneBody.generateFrame(0));
+ break;
+ case CONTINUE:
+ ConnectionSecureBody
+ secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
+ _connection.writeFrame(secureBody.generateFrame(0));
+ }
+ }
+ catch (SaslException e)
+ {
+ disposeSaslServer(_connection);
+ throw new AMQException("SASL error: " + e, e);
+ }
+ return true;
+ }
+
+ public boolean dispatchConnectionTuneOk(ConnectionTuneOkBody body, int channelId) throws AMQException
+ {
+ final AMQProtocolSession<?> connection = getConnection();
+
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug(body);
+ }
+
+ connection.initHeartbeats(body.getHeartbeat());
+
+ int brokerFrameMax = connection.getBroker().getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
+ if(brokerFrameMax <= 0)
+ {
+ brokerFrameMax = Integer.MAX_VALUE;
+ }
+
+ if(body.getFrameMax() > (long) brokerFrameMax)
+ {
+ throw new AMQConnectionException(AMQConstant.SYNTAX_ERROR,
+ "Attempt to set max frame size to " + body.getFrameMax()
+ + " greater than the broker will allow: "
+ + brokerFrameMax,
+ body.getClazz(), body.getMethod(),
+ connection.getMethodRegistry(),null);
+ }
+ else if(body.getFrameMax() > 0 && body.getFrameMax() < AMQConstant.FRAME_MIN_SIZE.getCode())
+ {
+ throw new AMQConnectionException(AMQConstant.SYNTAX_ERROR,
+ "Attempt to set max frame size to " + body.getFrameMax()
+ + " which is smaller than the specification definined minimum: "
+ + AMQConstant.FRAME_MIN_SIZE.getCode(),
+ body.getClazz(), body.getMethod(),
+ connection.getMethodRegistry(),null);
+ }
+ int frameMax = body.getFrameMax() == 0 ? brokerFrameMax : (int) body.getFrameMax();
+ connection.setMaxFrameSize(frameMax);
+
+ long maxChannelNumber = body.getChannelMax();
+ //0 means no implied limit, except that forced by protocol limitations (0xFFFF)
+ connection.setMaximumNumberOfChannels(maxChannelNumber == 0 ? 0xFFFFL : maxChannelNumber);
+ return true;
+ }
+
+ public static final int OK = 0;
+ public static final int EXCHANGE_NOT_FOUND = 1;
+ public static final int QUEUE_NOT_FOUND = 2;
+ public static final int NO_BINDINGS = 3;
+ public static final int QUEUE_NOT_BOUND = 4;
+ public static final int NO_QUEUE_BOUND_WITH_RK = 5;
+ public static final int SPECIFIC_QUEUE_NOT_BOUND_WITH_RK = 6;
+
+ public boolean dispatchExchangeBound(ExchangeBoundBody body, int channelId) throws AMQException
+ {
+ VirtualHostImpl virtualHost = _connection.getVirtualHost();
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+ final AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ channel.sync();
+
+
+ AMQShortString exchangeName = body.getExchange();
+ AMQShortString queueName = body.getQueue();
+ AMQShortString routingKey = body.getRoutingKey();
+ ExchangeBoundOkBody response;
+
+ if(isDefaultExchange(exchangeName))
+ {
+ if(routingKey == null)
+ {
+ if(queueName == null)
+ {
+ response = methodRegistry.createExchangeBoundOkBody(virtualHost.getQueues().isEmpty() ? NO_BINDINGS : OK, null);
+ }
+ else
+ {
+ AMQQueue queue = virtualHost.getQueue(queueName.toString());
+ if (queue == null)
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode
+ AMQShortString.validValueOf("Queue '" + queueName + "' not found")); // replyText
+ }
+ else
+ {
+ response = methodRegistry.createExchangeBoundOkBody(OK, null);
+ }
+ }
+ }
+ else
+ {
+ if(queueName == null)
+ {
+ response = methodRegistry.createExchangeBoundOkBody(virtualHost.getQueue(routingKey.toString()) == null ? NO_QUEUE_BOUND_WITH_RK : OK, null);
+ }
+ else
+ {
+ AMQQueue queue = virtualHost.getQueue(queueName.toString());
+ if (queue == null)
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode
+ AMQShortString.validValueOf("Queue '" + queueName + "' not found")); // replyText
+ }
+ else
+ {
+ response = methodRegistry.createExchangeBoundOkBody(queueName.equals(routingKey) ? OK : SPECIFIC_QUEUE_NOT_BOUND_WITH_RK, null);
+ }
+ }
+ }
+ }
+ else
+ {
+ ExchangeImpl exchange = virtualHost.getExchange(exchangeName.toString());
+ if (exchange == null)
+ {
+
+
+ response = methodRegistry.createExchangeBoundOkBody(EXCHANGE_NOT_FOUND,
+ AMQShortString.validValueOf("Exchange '" + exchangeName + "' not found"));
+ }
+ else if (routingKey == null)
+ {
+ if (queueName == null)
+ {
+ if (exchange.hasBindings())
+ {
+ response = methodRegistry.createExchangeBoundOkBody(OK, null);
+ }
+ else
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(NO_BINDINGS, // replyCode
+ null); // replyText
+ }
+ }
+ else
+ {
+
+ AMQQueue queue = virtualHost.getQueue(queueName.toString());
+ if (queue == null)
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode
+ AMQShortString.validValueOf("Queue '" + queueName + "' not found")); // replyText
+ }
+ else
+ {
+ if (exchange.isBound(queue))
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode
+ null); // replyText
+ }
+ else
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_BOUND, // replyCode
+ AMQShortString.validValueOf("Queue '" + queueName + "' not bound to exchange '" + exchangeName + "'")); // replyText
+ }
+ }
+ }
+ }
+ else if (queueName != null)
+ {
+ AMQQueue queue = virtualHost.getQueue(queueName.toString());
+ if (queue == null)
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode
+ AMQShortString.validValueOf("Queue '" + queueName + "' not found")); // replyText
+ }
+ else
+ {
+ String bindingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().asString();
+ if (exchange.isBound(bindingKey, queue))
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode
+ null); // replyText
+ }
+ else
+ {
+
+ String message = "Queue '" + queueName + "' not bound with routing key '" +
+ body.getRoutingKey() + "' to exchange '" + exchangeName + "'";
+
+ response = methodRegistry.createExchangeBoundOkBody(SPECIFIC_QUEUE_NOT_BOUND_WITH_RK, // replyCode
+ AMQShortString.validValueOf(message)); // replyText
+ }
+ }
+ }
+ else
+ {
+ if (exchange.isBound(body.getRoutingKey() == null ? "" : body.getRoutingKey().asString()))
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode
+ null); // replyText
+ }
+ else
+ {
+
+ response = methodRegistry.createExchangeBoundOkBody(NO_QUEUE_BOUND_WITH_RK, // replyCode
+ AMQShortString.validValueOf("No queue bound with routing key '" + body.getRoutingKey() +
+ "' to exchange '" + exchangeName + "'")); // replyText
+ }
+ }
+ }
+ _connection.writeFrame(response.generateFrame(channelId));
+ return true;
+ }
+
+ public boolean dispatchExchangeDeclare(ExchangeDeclareBody body, int channelId) throws AMQException
+ {
+ VirtualHostImpl virtualHost = _connection.getVirtualHost();
+ final AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ final AMQShortString exchangeName = body.getExchange();
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Request to declare exchange of type " + body.getType() + " with name " + exchangeName);
+ }
+
+ ExchangeImpl exchange;
+
+ if(isDefaultExchange(exchangeName))
+ {
+ if(!new AMQShortString(ExchangeDefaults.DIRECT_EXCHANGE_CLASS).equals(body.getType()))
+ {
+ throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare default exchange: "
+ + " of type "
+ + ExchangeDefaults.DIRECT_EXCHANGE_CLASS
+ + " to " + body.getType() +".",
+ body.getClazz(), body.getMethod(),
+ _connection.getMethodRegistry(),null);
+ }
+ }
+ else
+ {
+ if (body.getPassive())
+ {
+ exchange = virtualHost.getExchange(exchangeName.toString());
+ if(exchange == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName,
+ _connection.getMethodRegistry());
+ }
+ else if (!(body.getType() == null || body.getType().length() ==0) && !exchange.getType().equals(body.getType().asString()))
+ {
+
+ throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " +
+ exchangeName + " of type " + exchange.getType()
+ + " to " + body.getType() +".",
+ body.getClazz(), body.getMethod(),
+ _connection.getMethodRegistry(),null);
+ }
+
+ }
+ else
+ {
+ try
+ {
+ String name = exchangeName == null ? null : exchangeName.intern().toString();
+ String type = body.getType() == null ? null : body.getType().intern().toString();
+
+ Map<String,Object> attributes = new HashMap<String, Object>();
+ if(body.getArguments() != null)
+ {
+ attributes.putAll(FieldTable.convertToMap(body.getArguments()));
+ }
+ attributes.put(org.apache.qpid.server.model.Exchange.ID, null);
+ attributes.put(org.apache.qpid.server.model.Exchange.NAME,name);
+ attributes.put(org.apache.qpid.server.model.Exchange.TYPE,type);
+ attributes.put(org.apache.qpid.server.model.Exchange.DURABLE, body.getDurable());
+ attributes.put(org.apache.qpid.server.model.Exchange.LIFETIME_POLICY,
+ body.getAutoDelete() ? LifetimePolicy.DELETE_ON_NO_LINKS : LifetimePolicy.PERMANENT);
+ if(!attributes.containsKey(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE))
+ {
+ attributes.put(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE, null);
+ }
+ exchange = virtualHost.createExchange(attributes);
+
+ }
+ catch(ReservedExchangeNameException e)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Attempt to declare exchange: " + exchangeName +
+ " which begins with reserved prefix.",
+ _connection.getMethodRegistry());
+
+ }
+ catch(ExchangeExistsException e)
+ {
+ exchange = e.getExistingExchange();
+ if(!new AMQShortString(exchange.getType()).equals(body.getType()))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: "
+ + exchangeName + " of type "
+ + exchange.getType()
+ + " to " + body.getType() + ".",
+ _connection.getMethodRegistry());
+ }
+ }
+ catch(NoFactoryForTypeException e)
+ {
+ throw body.getConnectionException(AMQConstant.COMMAND_INVALID,
+ "Unknown exchange type '"
+ + e.getType()
+ + "' for exchange '"
+ + exchangeName
+ + "'",
+ _connection.getMethodRegistry());
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+ catch (UnknownConfiguredObjectException e)
+ {
+ // note - since 0-8/9/9-1 can't set the alt. exchange this exception should never occur
+ throw body.getConnectionException(AMQConstant.NOT_FOUND,
+ "Unknown alternate exchange "
+ + (e.getName() != null
+ ? "name: \"" + e.getName() + "\""
+ : "id: " + e.getId()),
+ _connection.getMethodRegistry());
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw body.getConnectionException(AMQConstant.COMMAND_INVALID,
+ "Error creating exchange '"
+ + exchangeName
+ + "': "
+ + e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+ }
+ }
+
+ if(!body.getNowait())
+ {
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createExchangeDeclareOkBody();
+ channel.sync();
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ }
+ return true;
+ }
+
+ public boolean dispatchExchangeDelete(ExchangeDeleteBody body, int channelId) throws AMQException
+ {
+ VirtualHostImpl virtualHost = _connection.getVirtualHost();
+ final AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ channel.sync();
+ try
+ {
+
+ if(isDefaultExchange(body.getExchange()))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Default Exchange cannot be deleted",
+ _connection.getMethodRegistry());
+ }
+
+ final String exchangeName = body.getExchange().toString();
+
+ final ExchangeImpl exchange = virtualHost.getExchange(exchangeName);
+ if(exchange == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "No such exchange: " + body.getExchange(),
+ _connection.getMethodRegistry());
+ }
+
+ virtualHost.removeExchange(exchange, !body.getIfUnused());
+
+ ExchangeDeleteOkBody responseBody = _connection.getMethodRegistry().createExchangeDeleteOkBody();
+
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ }
+
+ catch (ExchangeIsAlternateException e)
+ {
+ throw body.getChannelException(AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange",
+ _connection.getMethodRegistry());
+
+ }
+ catch (RequiredExchangeException e)
+ {
+ throw body.getChannelException(AMQConstant.NOT_ALLOWED,
+ "Exchange '" + body.getExchange() + "' cannot be deleted",
+ _connection.getMethodRegistry());
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+ return true;
+ }
+
+ private boolean isDefaultExchange(final AMQShortString exchangeName)
+ {
+ return exchangeName == null || exchangeName.equals(AMQShortString.EMPTY_STRING);
+ }
+
+ public boolean dispatchQueueBind(QueueBindBody body, int channelId) throws AMQException
+ {
+ VirtualHostImpl virtualHost = _connection.getVirtualHost();
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ final AMQQueue queue;
+ final AMQShortString routingKey;
+
+ final AMQShortString queueName = body.getQueue();
+
+ if (queueName == null)
+ {
+
+ queue = channel.getDefaultQueue();
+
+ if (queue == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND,
+ "No default queue defined on channel and queue was null",
+ _connection.getMethodRegistry());
+ }
+
+ if (body.getRoutingKey() == null)
+ {
+ routingKey = AMQShortString.valueOf(queue.getName());
+ }
+ else
+ {
+ routingKey = body.getRoutingKey().intern();
+ }
+ }
+ else
+ {
+ queue = virtualHost.getQueue(queueName.toString());
+ routingKey = body.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : body.getRoutingKey().intern();
+ }
+
+ if (queue == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist.",
+ _connection.getMethodRegistry());
+ }
+
+ if(isDefaultExchange(body.getExchange()))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Cannot bind the queue " + queueName + " to the default exchange",
+ _connection.getMethodRegistry());
+ }
+
+ final String exchangeName = body.getExchange().toString();
+
+ final ExchangeImpl exch = virtualHost.getExchange(exchangeName);
+ if (exch == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + exchangeName + " does not exist.",
+ _connection.getMethodRegistry());
+ }
+
+
+ try
+ {
+
+ Map<String,Object> arguments = FieldTable.convertToMap(body.getArguments());
+ String bindingKey = String.valueOf(routingKey);
+
+ if (!exch.isBound(bindingKey, arguments, queue))
+ {
+
+ if(!exch.addBinding(bindingKey, queue, arguments) && ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(exch.getType()))
+ {
+ exch.replaceBinding(bindingKey, queue, arguments);
+ }
+ }
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey);
+ }
+ if (!body.getNowait())
+ {
+ channel.sync();
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createQueueBindOkBody();
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+
+ }
+ return true;
+ }
+
+ public boolean dispatchQueueDeclare(QueueDeclareBody body, int channelId) throws AMQException
+ {
+ final AMQSessionModel session = _connection.getChannel(channelId);
+ VirtualHostImpl virtualHost = _connection.getVirtualHost();
+
+ final AMQShortString queueName;
+
+ // if we aren't given a queue name, we create one which we return to the client
+ if ((body.getQueue() == null) || (body.getQueue().length() == 0))
+ {
+ queueName = new AMQShortString("tmp_" + UUID.randomUUID());
+ }
+ else
+ {
+ queueName = body.getQueue().intern();
+ }
+
+ AMQQueue queue;
+
+ //TODO: do we need to check that the queue already exists with exactly the same "configuration"?
+
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ if(body.getPassive())
+ {
+ queue = virtualHost.getQueue(queueName.toString());
+ if (queue == null)
+ {
+ String msg = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ").";
+ throw body.getChannelException(AMQConstant.NOT_FOUND, msg, _connection.getMethodRegistry());
+ }
+ else
+ {
+ if (!queue.verifySessionAccess(channel))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Queue "
+ + queue.getName()
+ + " is exclusive, but not created on this Connection.",
+ _connection.getMethodRegistry());
+ }
+
+ //set this as the default queue on the channel:
+ channel.setDefaultQueue(queue);
+ }
+ }
+ else
+ {
+
+ try
+ {
+
+ queue = createQueue(channel, queueName, body, virtualHost, _connection);
+
+ }
+ catch(QueueExistsException qe)
+ {
+
+ queue = qe.getExistingQueue();
+
+ if (!queue.verifySessionAccess(channel))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Queue "
+ + queue.getName()
+ + " is exclusive, but not created on this Connection.",
+ _connection.getMethodRegistry());
+ }
+ else if(queue.isExclusive() != body.getExclusive())
+ {
+
+ throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
+ "Cannot re-declare queue '"
+ + queue.getName()
+ + "' with different exclusivity (was: "
+ + queue.isExclusive()
+ + " requested "
+ + body.getExclusive()
+ + ")",
+ _connection.getMethodRegistry());
+ }
+ else if((body.getAutoDelete() && queue.getLifetimePolicy() != LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS)
+ || (!body.getAutoDelete() && queue.getLifetimePolicy() != ((body.getExclusive() && !body.getDurable()) ? LifetimePolicy.DELETE_ON_CONNECTION_CLOSE : LifetimePolicy.PERMANENT)))
+ {
+ throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
+ "Cannot re-declare queue '"
+ + queue.getName()
+ + "' with different lifetime policy (was: "
+ + queue.getLifetimePolicy()
+ + " requested autodelete: "
+ + body.getAutoDelete()
+ + ")",
+ _connection.getMethodRegistry());
+ }
+ else if(queue.isDurable() != body.getDurable())
+ {
+ throw body.getChannelException(AMQConstant.ALREADY_EXISTS,
+ "Cannot re-declare queue '"
+ + queue.getName()
+ + "' with different durability (was: "
+ + queue.isDurable()
+ + " requested "
+ + body.getDurable()
+ + ")",
+ _connection.getMethodRegistry());
+ }
+
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+
+ //set this as the default queue on the channel:
+ channel.setDefaultQueue(queue);
+ }
+
+ if (!body.getNowait())
+ {
+ channel.sync();
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ QueueDeclareOkBody responseBody =
+ methodRegistry.createQueueDeclareOkBody(queueName,
+ queue.getQueueDepthMessages(),
+ queue.getConsumerCount());
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+
+ _logger.info("Queue " + queueName + " declared successfully");
+ }
+ return true;
+ }
+
+ protected AMQQueue createQueue(final AMQChannel channel, final AMQShortString queueName,
+ QueueDeclareBody body,
+ final VirtualHostImpl virtualHost,
+ final AMQProtocolSession session)
+ throws AMQException, QueueExistsException
+ {
+
+ final boolean durable = body.getDurable();
+ final boolean autoDelete = body.getAutoDelete();
+ final boolean exclusive = body.getExclusive();
+
+
+ Map<String, Object> attributes =
+ QueueArgumentsConverter.convertWireArgsToModel(FieldTable.convertToMap(body.getArguments()));
+ final String queueNameString = AMQShortString.toString(queueName);
+ attributes.put(Queue.NAME, queueNameString);
+ attributes.put(Queue.ID, UUID.randomUUID());
+ attributes.put(Queue.DURABLE, durable);
+
+ LifetimePolicy lifetimePolicy;
+ ExclusivityPolicy exclusivityPolicy;
+
+ if(exclusive)
+ {
+ lifetimePolicy = autoDelete
+ ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS
+ : durable ? LifetimePolicy.PERMANENT : LifetimePolicy.DELETE_ON_CONNECTION_CLOSE;
+ exclusivityPolicy = durable ? ExclusivityPolicy.CONTAINER : ExclusivityPolicy.CONNECTION;
+ }
+ else
+ {
+ lifetimePolicy = autoDelete ? LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS : LifetimePolicy.PERMANENT;
+ exclusivityPolicy = ExclusivityPolicy.NONE;
+ }
+
+ attributes.put(Queue.EXCLUSIVE, exclusivityPolicy);
+ attributes.put(Queue.LIFETIME_POLICY, lifetimePolicy);
+
+
+ final AMQQueue queue = virtualHost.createQueue(attributes);
+
+ return queue;
+ }
+
+ public boolean dispatchQueueDelete(QueueDeleteBody body, int channelId) throws AMQException
+ {
+ VirtualHostImpl virtualHost = _connection.getVirtualHost();
+
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ channel.sync();
+ AMQQueue queue;
+ if (body.getQueue() == null)
+ {
+
+ //get the default queue on the channel:
+ queue = channel.getDefaultQueue();
+ }
+ else
+ {
+ queue = virtualHost.getQueue(body.getQueue().toString());
+ }
+
+ if (queue == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
+ _connection.getMethodRegistry());
+
+ }
+ else
+ {
+ if (body.getIfEmpty() && !queue.isEmpty())
+ {
+ throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is not empty.",
+ _connection.getMethodRegistry());
+ }
+ else if (body.getIfUnused() && !queue.isUnused())
+ {
+ // TODO - Error code
+ throw body.getChannelException(AMQConstant.IN_USE, "Queue: " + body.getQueue() + " is still used.",
+ _connection.getMethodRegistry());
+ }
+ else
+ {
+ if (!queue.verifySessionAccess(channel))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Queue "
+ + queue.getName()
+ + " is exclusive, but not created on this Connection.",
+ _connection.getMethodRegistry());
+ }
+
+ int purged = 0;
+ try
+ {
+ purged = virtualHost.removeQueue(queue);
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ QueueDeleteOkBody responseBody = methodRegistry.createQueueDeleteOkBody(purged);
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ }
+ }
+ return true;
+ }
+
+ public boolean dispatchQueuePurge(QueuePurgeBody body, int channelId) throws AMQException
+ {
+ VirtualHostImpl virtualHost = _connection.getVirtualHost();
+
+ AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ AMQQueue queue;
+ if(body.getQueue() == null)
+ {
+
+ //get the default queue on the channel:
+ queue = channel.getDefaultQueue();
+
+ if(queue == null)
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "No queue specified.",
+ _connection.getMethodRegistry());
+ }
+ }
+ else
+ {
+ queue = virtualHost.getQueue(body.getQueue().toString());
+ }
+
+ if(queue == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
+ _connection.getMethodRegistry());
+ }
+ else
+ {
+ if (!queue.verifySessionAccess(channel))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Queue is exclusive, but not created on this Connection.",
+ _connection.getMethodRegistry());
+ }
+
+ long purged = 0;
+ try
+ {
+ purged = queue.clearQueue();
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+
+
+ if(!body.getNowait())
+ {
+ channel.sync();
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createQueuePurgeOkBody(purged);
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+
+ }
+ }
+ return true;
+ }
+
+
+ public boolean dispatchTxCommit(TxCommitBody body, final int channelId) throws AMQException
+ {
+ try
+ {
+ if (_logger.isDebugEnabled())
+ {
+ _logger.debug("Commit received on channel " + channelId);
+ }
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ channel.commit(new Runnable()
+ {
+
+ @Override
+ public void run()
+ {
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody();
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ }
+ }, true);
+
+
+
+ }
+ catch (AMQException e)
+ {
+ throw body.getChannelException(e.getErrorCode(), "Failed to commit: " + e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+ return true;
+ }
+
+ public boolean dispatchTxRollback(TxRollbackBody body, final int channelId) throws AMQException
+ {
+ try
+ {
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+
+
+ final MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ final AMQMethodBody responseBody = methodRegistry.createTxRollbackOkBody();
+
+ Runnable task = new Runnable()
+ {
+
+ public void run()
+ {
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ }
+ };
+
+ channel.rollback(task);
+
+ //Now resend all the unacknowledged messages back to the original subscribers.
+ //(Must be done after the TxnRollback-ok response).
+ // Why, are we not allowed to send messages back to client before the ok method?
+ channel.resend();
+
+ }
+ catch (AMQException e)
+ {
+ throw body.getChannelException(e.getErrorCode(), "Failed to rollback: " + e.getMessage(),
+ _connection.getMethodRegistry());
+ }
+ return true;
+ }
+
+ public boolean dispatchTxSelect(TxSelectBody body, int channelId) throws AMQException
+ {
+ AMQChannel channel = _connection.getChannel(channelId);
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+
+ channel.setLocalTransactional();
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+ TxSelectOkBody responseBody = methodRegistry.createTxSelectOkBody();
+ _connection.writeFrame(responseBody.generateFrame(channelId));
+ return true;
+ }
+
+ public boolean dispatchBasicRecoverSync(BasicRecoverSyncBody body, int channelId) throws AMQException
+ {
+ final AMQProtocolSession<?> connection = getConnection();
+
+ _logger.debug("Recover received on protocol session " + connection + " and channel " + channelId);
+ AMQChannel channel = connection.getChannel(channelId);
+
+
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
+ }
+ channel.sync();
+ channel.resend();
+
+ MethodRegistry methodRegistry = connection.getMethodRegistry();
+ AMQMethodBody recoverOk = methodRegistry.createBasicRecoverSyncOkBody();
+ connection.writeFrame(recoverOk.generateFrame(channelId));
+
+ return true;
+ }
+
+ public boolean dispatchBasicRecoverSyncOk(BasicRecoverSyncOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ @Override
+ public boolean dispatchChannelAlert(final ChannelAlertBody body, final int channelId)
+ throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueUnbindOk(QueueUnbindOkBody body, int channelId) throws AMQException
+ {
+ throw new UnexpectedMethodException(body);
+ }
+
+ public boolean dispatchQueueUnbind(QueueUnbindBody body, int channelId) throws AMQException
+ {
+ final AMQProtocolSession<?> connection = getConnection();
+
+ if (ProtocolVersion.v8_0.equals(connection.getProtocolVersion()))
+ {
+ // 0-8 does not support QueueUnbind
+ throw new AMQException(AMQConstant.COMMAND_INVALID, "QueueUnbind not present in AMQP version: " + connection.getProtocolVersion(), null);
+ }
+
+ VirtualHostImpl virtualHost = connection.getVirtualHost();
+
+ final AMQQueue queue;
+ final AMQShortString routingKey;
+
+
+ AMQChannel channel = connection.getChannel(channelId);
+ if (channel == null)
+ {
+ throw body.getChannelNotFoundException(channelId, connection.getMethodRegistry());
+ }
+
+ if (body.getQueue() == null)
+ {
+
+ queue = channel.getDefaultQueue();
+
+ if (queue == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND,
+ "No default queue defined on channel and queue was null",
+ connection.getMethodRegistry());
+ }
+
+ routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false);
+
+ }
+ else
+ {
+ queue = virtualHost.getQueue(body.getQueue().toString());
+ routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false);
+ }
+
+ if (queue == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist.",
+ connection.getMethodRegistry());
+ }
+
+ if(isDefaultExchange(body.getExchange()))
+ {
+ throw body.getConnectionException(AMQConstant.NOT_ALLOWED,
+ "Cannot unbind the queue "
+ + queue.getName()
+ + " from the default exchange", connection.getMethodRegistry());
+ }
+
+ final ExchangeImpl exch = virtualHost.getExchange(body.getExchange() == null ? null : body.getExchange().toString());
+ if (exch == null)
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "Exchange " + body.getExchange() + " does not exist.",
+ connection.getMethodRegistry());
+ }
+
+ if(!exch.hasBinding(String.valueOf(routingKey), queue))
+ {
+ throw body.getChannelException(AMQConstant.NOT_FOUND, "No such binding", connection.getMethodRegistry());
+ }
+ else
+ {
+ try
+ {
+ exch.deleteBinding(String.valueOf(routingKey), queue);
+ }
+ catch (AccessControlException e)
+ {
+ throw body.getConnectionException(AMQConstant.ACCESS_REFUSED,
+ e.getMessage(),
+ connection.getMethodRegistry());
+ }
+ }
+
+
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Binding queue " + queue + " to exchange " + exch + " with routing key " + routingKey);
+ }
+
+
+ final AMQMethodBody responseBody = connection.getMethodRegistry().createQueueUnbindOkBody();
+ channel.sync();
+ connection.writeFrame(responseBody.generateFrame(channelId));
+ return true;
+ }
+
+}
diff --git a/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodProcessor.java b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodProcessor.java
new file mode 100644
index 0000000000..40e1af10c6
--- /dev/null
+++ b/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ServerMethodProcessor.java
@@ -0,0 +1,957 @@
+/*
+ *
+ * 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 java.security.PrivilegedAction;
+
+import javax.security.auth.Subject;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+
+import org.apache.log4j.Logger;
+
+import org.apache.qpid.framing.*;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.security.SubjectCreator;
+import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
+
+public class ServerMethodProcessor implements MethodProcessor
+{
+ private static final Logger LOGGER = Logger.getLogger(ServerMethodProcessor.class);
+
+
+ private static interface ChannelAction
+ {
+ void onChannel(ChannelMethodProcessor channel);
+ }
+
+ private ProtocolVersion _protocolVersion;
+ private ServerMethodDispatcherImpl _dispatcher;
+ private AMQProtocolEngine _connection;
+
+ public ServerMethodProcessor(final ProtocolVersion protocolVersion)
+ {
+ _protocolVersion = protocolVersion;
+ }
+
+
+ private void processChannelMethod(int channelId, final ChannelAction action)
+ {
+ final AMQChannel channel = _connection.getChannel(channelId);
+ if (channel == null)
+ {
+ // TODO throw body.getChannelNotFoundException(channelId, _connection.getMethodRegistry());
+ }
+ else
+ {
+ Subject.doAs(channel.getSubject(), new PrivilegedAction<Void>()
+ {
+ @Override
+ public Void run()
+ {
+ action.onChannel(channel.getMethodProcessor());
+ return null;
+ }
+ });
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionStart(final short versionMajor,
+ final short versionMinor,
+ final FieldTable serverProperties,
+ final byte[] mechanisms,
+ final byte[] locales)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0,
+ new ConnectionStartBody(versionMajor,
+ versionMinor,
+ serverProperties,
+ mechanisms,
+ locales));
+ }
+ _connection.closeConnection(AMQConstant.COMMAND_INVALID, "Unexpected method received: ConnectionStart", 0,
+ ConnectionStartBody.CLASS_ID, ConnectionStartBody.METHOD_ID);
+
+ }
+
+ @Override
+ public void receiveConnectionStartOk(final FieldTable clientProperties,
+ final AMQShortString mechanism,
+ final byte[] response,
+ final AMQShortString locale)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new ConnectionStartOkBody(clientProperties, mechanism, response, locale));
+ }
+
+ Broker<?> broker = _connection.getBroker();
+
+ SubjectCreator subjectCreator = _connection.getSubjectCreator();
+ SaslServer ss = null;
+ try
+ {
+ ss = subjectCreator.createSaslServer(String.valueOf(mechanism),
+ _connection.getLocalFQDN(),
+ _connection.getPeerPrincipal());
+
+ if (ss == null)
+ {
+ _connection.closeConnection(AMQConstant.RESOURCE_ERROR,
+ "Unable to create SASL Server:" + mechanism, 0,
+ ConnectionStartOkBody.CLASS_ID,
+ ConnectionStartOkBody.METHOD_ID);
+ }
+ else
+ {
+ _connection.setSaslServer(ss);
+
+ final SubjectAuthenticationResult authResult = subjectCreator.authenticate(ss, response);
+ //save clientProperties
+ _connection.setClientProperties(clientProperties);
+
+ MethodRegistry methodRegistry = _connection.getMethodRegistry();
+
+ switch (authResult.getStatus())
+ {
+ case ERROR:
+ Exception cause = authResult.getCause();
+
+ LOGGER.info("Authentication failed:" + (cause == null ? "" : cause.getMessage()));
+
+ _connection.closeConnection(AMQConstant.NOT_ALLOWED,
+ AMQConstant.NOT_ALLOWED.getName().toString(), 0,
+ ConnectionStartOkBody.CLASS_ID,
+ ConnectionStartOkBody.METHOD_ID);
+
+ disposeSaslServer();
+ break;
+
+ case SUCCESS:
+ if (LOGGER.isInfoEnabled())
+ {
+ LOGGER.info("Connected as: " + authResult.getSubject());
+ }
+ _connection.setAuthorizedSubject(authResult.getSubject());
+
+ int frameMax = broker.getContextValue(Integer.class, Broker.BROKER_FRAME_SIZE);
+
+ if (frameMax <= 0)
+ {
+ frameMax = Integer.MAX_VALUE;
+ }
+
+ ConnectionTuneBody
+ tuneBody =
+ methodRegistry.createConnectionTuneBody(broker.getConnection_sessionCountLimit(),
+ frameMax,
+ broker.getConnection_heartBeatDelay());
+ _connection.writeFrame(tuneBody.generateFrame(0));
+ break;
+ case CONTINUE:
+ ConnectionSecureBody
+ secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
+ _connection.writeFrame(secureBody.generateFrame(0));
+ }
+ }
+ }
+ catch (SaslException e)
+ {
+ disposeSaslServer();
+
+ _connection.closeConnection(AMQConstant.RESOURCE_ERROR, "SASL error: " + e.getMessage(), 0,
+ ConnectionStartOkBody.CLASS_ID, ConnectionStartOkBody.METHOD_ID);
+ }
+
+ }
+
+ @Override
+ public void receiveTxSelect(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, TxSelectBody.INSTANCE);
+ }
+
+ }
+
+ @Override
+ public void receiveTxSelectOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, TxSelectOkBody.INSTANCE);
+ }
+
+ }
+
+ @Override
+ public void receiveTxCommit(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, TxCommitBody.INSTANCE);
+ }
+
+ }
+
+ @Override
+ public void receiveTxCommitOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, TxCommitOkBody.INSTANCE);
+ }
+
+ }
+
+ @Override
+ public void receiveTxRollback(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, TxRollbackBody.INSTANCE);
+ }
+
+ }
+
+ @Override
+ public void receiveTxRollbackOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, TxRollbackOkBody.INSTANCE);
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionSecure(final byte[] challenge)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new ConnectionSecureBody(challenge));
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionSecureOk(final byte[] response)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new ConnectionSecureOkBody(response));
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionTune(final int channelMax, final long frameMax, final int heartbeat)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new ConnectionTuneBody(channelMax, frameMax, heartbeat));
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionTuneOk(final int channelMax, final long frameMax, final int heartbeat)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new ConnectionTuneOkBody(channelMax, frameMax, heartbeat));
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionOpen(final AMQShortString virtualHost,
+ final AMQShortString capabilities,
+ final boolean insist)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new ConnectionOpenBody(virtualHost, capabilities, insist));
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionOpenOk(final AMQShortString knownHosts)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new ConnectionOpenOkBody(knownHosts));
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionRedirect(final AMQShortString host, final AMQShortString knownHosts)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new ConnectionRedirectBody(getProtocolVersion(), host, knownHosts));
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionClose(final int replyCode,
+ final AMQShortString replyText,
+ final int classId,
+ final int methodId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0,
+ new ConnectionCloseBody(getProtocolVersion(),
+ replyCode,
+ replyText,
+ classId,
+ methodId));
+ }
+
+ }
+
+ @Override
+ public void receiveConnectionCloseOk()
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, ProtocolVersion.v8_0.equals(getProtocolVersion())
+ ? ConnectionCloseOkBody.CONNECTION_CLOSE_OK_0_8
+ : ConnectionCloseOkBody.CONNECTION_CLOSE_OK_0_9);
+ }
+ }
+
+ @Override
+ public void receiveChannelOpen(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ChannelOpenBody());
+ }
+
+ }
+
+ @Override
+ public void receiveChannelOpenOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, ProtocolVersion.v8_0.equals(getProtocolVersion())
+ ? ChannelOpenOkBody.INSTANCE_0_8
+ : ChannelOpenOkBody.INSTANCE_0_9);
+ }
+ }
+
+ @Override
+ public void receiveChannelFlow(final int channelId, final boolean active)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ChannelFlowBody(active));
+ }
+
+ }
+
+ @Override
+ public void receiveChannelFlowOk(final int channelId, final boolean active)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ChannelFlowOkBody(active));
+ }
+
+ }
+
+ @Override
+ public void receiveChannelAlert(final int channelId,
+ final int replyCode,
+ final AMQShortString replyText,
+ final FieldTable details)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ChannelAlertBody(replyCode, replyText, details));
+ }
+
+ }
+
+ @Override
+ public void receiveChannelClose(final int channelId,
+ final int replyCode,
+ final AMQShortString replyText,
+ final int classId,
+ final int methodId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ChannelCloseBody(replyCode, replyText, classId, methodId));
+ }
+
+ }
+
+ @Override
+ public void receiveChannelCloseOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, ChannelCloseOkBody.INSTANCE);
+ }
+
+ }
+
+ @Override
+ public void receiveAccessRequest(final int channelId,
+ final AMQShortString realm,
+ final boolean exclusive,
+ final boolean passive,
+ final boolean active,
+ final boolean write,
+ final boolean read)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame =
+ new AMQFrame(channelId, new AccessRequestBody(realm, exclusive, passive, active, write, read));
+ }
+
+ }
+
+ @Override
+ public void receiveAccessRequestOk(final int channelId, final int ticket)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new AccessRequestOkBody(ticket));
+ }
+
+ }
+
+ @Override
+ public void receiveExchangeDeclare(final int channelId,
+ final AMQShortString exchange,
+ final AMQShortString type,
+ final boolean passive,
+ final boolean durable,
+ final boolean autoDelete,
+ final boolean internal,
+ final boolean nowait, final FieldTable arguments)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId,
+ new ExchangeDeclareBody(0,
+ exchange,
+ type,
+ passive,
+ durable,
+ autoDelete,
+ internal,
+ nowait,
+ arguments));
+ }
+
+ }
+
+ @Override
+ public void receiveExchangeDeclareOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ExchangeDeclareOkBody());
+ }
+
+ }
+
+ @Override
+ public void receiveExchangeDelete(final int channelId,
+ final AMQShortString exchange,
+ final boolean ifUnused,
+ final boolean nowait)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ExchangeDeleteBody(0, exchange, ifUnused, nowait));
+ }
+
+ }
+
+ @Override
+ public void receiveExchangeDeleteOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ExchangeDeleteOkBody());
+ }
+
+ }
+
+ @Override
+ public void receiveExchangeBound(final int channelId,
+ final AMQShortString exchange,
+ final AMQShortString routingKey,
+ final AMQShortString queue)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ExchangeBoundBody(exchange, routingKey, queue));
+ }
+
+ }
+
+ @Override
+ public void receiveExchangeBoundOk(final int channelId, final int replyCode, final AMQShortString replyText)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ExchangeBoundOkBody(replyCode, replyText));
+ }
+
+ }
+
+ @Override
+ public void receiveQueueBindOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new QueueBindOkBody());
+ }
+
+ }
+
+ @Override
+ public void receiveQueueUnbindOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new QueueUnbindOkBody());
+ }
+
+ }
+
+ @Override
+ public void receiveQueueDeclare(final int channelId,
+ final AMQShortString queue,
+ final boolean passive,
+ final boolean durable,
+ final boolean exclusive,
+ final boolean autoDelete,
+ final boolean nowait,
+ final FieldTable arguments)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId,
+ new QueueDeclareBody(0,
+ queue,
+ passive,
+ durable,
+ exclusive,
+ autoDelete,
+ nowait,
+ arguments));
+ }
+
+ }
+
+ @Override
+ public void receiveQueueDeclareOk(final int channelId,
+ final AMQShortString queue,
+ final long messageCount,
+ final long consumerCount)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new QueueDeclareOkBody(queue, messageCount, consumerCount));
+ }
+
+ }
+
+ @Override
+ public void receiveQueueBind(final int channelId,
+ final AMQShortString queue,
+ final AMQShortString exchange,
+ final AMQShortString bindingKey,
+ final boolean nowait,
+ final FieldTable arguments)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame =
+ new AMQFrame(channelId, new QueueBindBody(0, queue, exchange, bindingKey, nowait, arguments));
+ }
+
+ }
+
+ @Override
+ public void receiveQueuePurge(final int channelId, final AMQShortString queue, final boolean nowait)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new QueuePurgeBody(0, queue, nowait));
+ }
+
+ }
+
+ @Override
+ public void receiveQueuePurgeOk(final int channelId, final long messageCount)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new QueuePurgeOkBody(messageCount));
+ }
+
+ }
+
+ @Override
+ public void receiveQueueDelete(final int channelId,
+ final AMQShortString queue,
+ final boolean ifUnused,
+ final boolean ifEmpty,
+ final boolean nowait)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new QueueDeleteBody(0, queue, ifUnused, ifEmpty, nowait));
+ }
+
+ }
+
+ @Override
+ public void receiveQueueDeleteOk(final int channelId, final long messageCount)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new QueueDeleteOkBody(messageCount));
+ }
+
+ }
+
+ @Override
+ public void receiveQueueUnbind(final int channelId,
+ final AMQShortString queue,
+ final AMQShortString exchange,
+ final AMQShortString bindingKey,
+ final FieldTable arguments)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new QueueUnbindBody(0, queue, exchange, bindingKey, arguments));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicRecoverSyncOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicRecoverSyncOkBody(getProtocolVersion()));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicRecover(final int channelId, final boolean requeue, final boolean sync)
+ {
+ if (ProtocolVersion.v8_0.equals(getProtocolVersion()) || !sync)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicRecoverBody(requeue));
+ }
+
+ }
+ else
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicRecoverSyncBody(getProtocolVersion(), requeue));
+ }
+
+ }
+ }
+
+ @Override
+ public void receiveBasicQos(final int channelId,
+ final long prefetchSize,
+ final int prefetchCount,
+ final boolean global)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicQosBody(prefetchSize, prefetchCount, global));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicQosOk(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicQosOkBody());
+ }
+
+ }
+
+ @Override
+ public void receiveBasicConsume(final int channelId,
+ final AMQShortString queue,
+ final AMQShortString consumerTag,
+ final boolean noLocal,
+ final boolean noAck,
+ final boolean exclusive,
+ final boolean nowait,
+ final FieldTable arguments)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId,
+ new BasicConsumeBody(0,
+ queue,
+ consumerTag,
+ noLocal,
+ noAck,
+ exclusive,
+ nowait,
+ arguments));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicConsumeOk(final int channelId, final AMQShortString consumerTag)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicConsumeOkBody(consumerTag));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicCancel(final int channelId, final AMQShortString consumerTag, final boolean noWait)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicCancelBody(consumerTag, noWait));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicCancelOk(final int channelId, final AMQShortString consumerTag)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicCancelOkBody(consumerTag));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicPublish(final int channelId,
+ final AMQShortString exchange,
+ final AMQShortString routingKey,
+ final boolean mandatory,
+ final boolean immediate)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame =
+ new AMQFrame(channelId, new BasicPublishBody(0, exchange, routingKey, mandatory, immediate));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicReturn(final int channelId, final int replyCode,
+ final AMQShortString replyText,
+ final AMQShortString exchange,
+ final AMQShortString routingKey)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicReturnBody(replyCode, replyText, exchange, routingKey));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicDeliver(final int channelId,
+ final AMQShortString consumerTag,
+ final long deliveryTag,
+ final boolean redelivered,
+ final AMQShortString exchange,
+ final AMQShortString routingKey)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId,
+ new BasicDeliverBody(consumerTag,
+ deliveryTag,
+ redelivered,
+ exchange,
+ routingKey));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicGet(final int channelId, final AMQShortString queue, final boolean noAck)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicGetBody(0, queue, noAck));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicGetOk(final int channelId,
+ final long deliveryTag,
+ final boolean redelivered,
+ final AMQShortString exchange,
+ final AMQShortString routingKey,
+ final long messageCount)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId,
+ new BasicGetOkBody(deliveryTag,
+ redelivered,
+ exchange,
+ routingKey,
+ messageCount));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicGetEmpty(final int channelId)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicGetEmptyBody((AMQShortString) null));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicAck(final int channelId, final long deliveryTag, final boolean multiple)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicAckBody(deliveryTag, multiple));
+ }
+
+ }
+
+ @Override
+ public void receiveBasicReject(final int channelId, final long deliveryTag, final boolean requeue)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new BasicRejectBody(deliveryTag, requeue));
+ }
+
+ }
+
+ @Override
+ public void receiveHeartbeat()
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(0, new HeartbeatBody());
+ }
+
+ }
+
+ @Override
+ public ProtocolVersion getProtocolVersion()
+ {
+ return _protocolVersion;
+ }
+
+ public void setProtocolVersion(final ProtocolVersion protocolVersion)
+ {
+ _protocolVersion = protocolVersion;
+ }
+
+ @Override
+ public void receiveMessageContent(final int channelId, final byte[] data)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ContentBody(data));
+ }
+
+ }
+
+ @Override
+ public void receiveMessageHeader(final int channelId,
+ final BasicContentHeaderProperties properties,
+ final long bodySize)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQFrame frame = new AMQFrame(channelId, new ContentHeaderBody(properties, bodySize));
+ }
+
+ }
+
+ @Override
+ public void receiveProtocolHeader(final ProtocolInitiation protocolInitiation)
+ {
+ if (LOGGER.isDebugEnabled())
+ {
+ AMQDataBlock frame = protocolInitiation;
+ }
+
+ }
+
+ private void disposeSaslServer()
+ {
+ SaslServer ss = _connection.getSaslServer();
+ if (ss != null)
+ {
+ _connection.setSaslServer(null);
+ try
+ {
+ ss.dispose();
+ }
+ catch (SaslException e)
+ {
+ LOGGER.error("Error disposing of Sasl server: " + e);
+ }
+ }
+ }
+}
diff --git a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
index 32c5bcd541..a8b9edaa12 100644
--- a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
+++ b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbySystemConfigImpl.java
@@ -26,6 +26,7 @@ import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.model.AbstractSystemConfig;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.SystemConfigFactoryConstructor;
@@ -47,9 +48,10 @@ public class DerbySystemConfigImpl extends AbstractSystemConfig<DerbySystemConfi
public DerbySystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions)
+ final BrokerOptions brokerOptions,
+ final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+ super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
}
@Override
diff --git a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
index fd1cad7de4..a552b170a0 100644
--- a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
+++ b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCSystemConfigImpl.java
@@ -26,6 +26,7 @@ import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.model.AbstractSystemConfig;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.SystemConfigFactoryConstructor;
@@ -49,9 +50,10 @@ public class JDBCSystemConfigImpl extends AbstractSystemConfig<JDBCSystemConfigI
public JDBCSystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions)
+ final BrokerOptions brokerOptions,
+ final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+ super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
}
@Override
diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
index e07705656a..936cc4789a 100644
--- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
+++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java
@@ -122,7 +122,7 @@ public class HttpManagement extends AbstractPluginAdapter<HttpManagement> implem
super(attributes, broker);
}
- @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+ @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
private void doStart()
{
getBroker().getEventLogger().message(ManagementConsoleMessages.STARTUP(OPERATIONAL_LOGGING_NAME));
diff --git a/java/broker-plugins/management-http/src/main/java/resources/addQueue.html b/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
index 352e69893b..042d6d7ad7 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
+++ b/java/broker-plugins/management-http/src/main/java/resources/addQueue.html
@@ -39,19 +39,75 @@
<div class="clear">
<div class="formLabel-labelCell">Queue Type:</div>
<div class="formLabel-controlCell">
- <input type="radio" id="formAddQueueTypeStandard" name="type" value="standard" checked="checked" dojoType="dijit.form.RadioButton" />
- <label for="formAddQueueTypeStandard">Standard</label>
- &nbsp;
- <input type="radio" id="formAddQueueTypePriority" name="type" value="priority" dojoType="dijit.form.RadioButton" />
- <label for="formAddQueueTypePriority">Priority</label>
- &nbsp;
- <input type="radio" id="formAddQueueTypeLVQ" name="type" value="lvq" dojoType="dijit.form.RadioButton" />
- <label for="formAddQueueTypeLVQ">LVQ</label>
- &nbsp;
- <input type="radio" id="formAddQueueTypeSorted" name="type" value="sorted" dojoType="dijit.form.RadioButton" />
- <label for="formAddQueueTypeSorted">Sorted</label>
+ <select id="formAddQueue.type"
+ dojoType="dijit.form.FilteringSelect"
+ data-dojo-props="
+ name: 'type',
+ value: 'standard',
+ searchAttr: 'name',
+ required: true,
+ promptMessage: 'Type of Queue',
+ title: 'Enter the queue type'">
+ <option value="standard">Standard</option>
+ <option value="priority">Priority</option>
+ <option value="lvq">LVQ</option>
+ <option value="sorted">Sorted</option>
+ </select>
+ </div>
+ </div>
+ <div class="clear"></div>
+
+ <div id="formAddQueueType:priority" class="hidden typeSpecificDiv">
+ <div class="clear">
+ <div class="formLabel-labelCell">Priorities:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formAddQueue.priorities"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'priorities',
+ placeHolder: 'number of priorities',
+ promptMessage: 'Number of priorities supported by the queue',
+ title: 'Enter the number of priorities supported by the queue',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear"></div>
+ </div>
+
+ <div id="formAddQueueType:lvq" class="hidden typeSpecificDiv">
+ <div class="clear">
+ <div class="formLabel-labelCell">LVQ Message Property:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formAddQueue.lvqKey"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'lvqKey',
+ placeHolder: 'lvq key',
+ promptMessage: 'Name of the message property used to perform the conflation',
+ title: 'Enter the name of the message property used to perform the conflation',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear"></div>
+ </div>
+
+ <div id="formAddQueueType:sorted" class="hidden typeSpecificDiv">
+ <div class="clear">
+ <div class="formLabel-labelCell">Sort Message Property*:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formAddQueue.sortKey"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'sortKey',
+ placeHolder: 'sort key',
+ promptMessage: 'Name of the message property used for sorting the messages on the queue',
+ title: 'Enter the name of the message property used for sorting the messages on the queue',
+ trim: true"/>
+ </div>
</div>
+ <div class="clear"></div>
</div>
+
<div class="clear">
<div class="formLabel-labelCell">Durable?</div>
<div class="formLabel-controlCell">
@@ -73,8 +129,8 @@
value: '',
searchAttr: 'name',
required: false,
- promptMessage: 'Message durability override. If not default, messages arriving will have durability setting overridden',
- title: 'Enter message durability override'">
+ promptMessage: 'Message persistence override. If not default, messages arriving will have persistence setting overridden',
+ title: 'Enter message persistence override'">
<option value="ALWAYS">Always</option>
<option value="DEFAULT">Default</option>
<option value="NEVER">Never</option>
@@ -108,66 +164,9 @@
</div>
</div>
- <br/>
- <div class="clear"></div>
-
-
- <div id="formAddQueueTypePriority:fields" class="hidden"
- data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Priority Queue Settings'">
- <div class="clear">
- <div class="formLabel-labelCell">Priorities:</div>
- <div class="formLabel-controlCell">
- <input type="text" id="formAddQueue.priorities"
- data-dojo-type="dijit/form/ValidationTextBox"
- data-dojo-props="
- name: 'priorities',
- placeHolder: 'number of priorities',
- promptMessage: 'Number of priorities supported by the queue',
- title: 'Enter the number of priorities supported by the queue',
- trim: true"/>
- </div>
- </div>
- <div class="clear"></div>
- </div>
-
- <div id="formAddQueueTypeLVQ:fields" class="hidden"
- data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Last Value Queue Settings'">
- <div class="clear">
- <div class="formLabel-labelCell">LVQ Message Property:</div>
- <div class="formLabel-controlCell">
- <input type="text" id="formAddQueue.lvqkey"
- data-dojo-type="dijit/form/ValidationTextBox"
- data-dojo-props="
- name: 'lvqKey',
- placeHolder: 'lvq key',
- promptMessage: 'Name of the message property used to perform the conflation',
- title: 'Enter the name of the message property used to perform the conflation',
- trim: true"/>
- </div>
- </div>
- <div class="clear"></div>
- </div>
-
- <div id="formAddQueueTypeSorted:fields" class="hidden"
- data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Sorted Queue Settings'">
- <div class="clear">
- <div class="formLabel-labelCell">Sort Message Property*:</div>
- <div class="formLabel-controlCell">
- <input type="text" id="formAddQueue.sortkey"
- data-dojo-type="dijit/form/ValidationTextBox"
- data-dojo-props="
- name: 'sortKey',
- placeHolder: 'sort key',
- promptMessage: 'Name of the message property used for sorting the messages on the queue',
- title: 'Enter the name of the message property used for sorting the messages on the queue',
- trim: true"/>
- </div>
- </div>
- <div class="clear"></div>
- </div>
-
- <br/>
- <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Flow Control Settings', open: false">
+ <div class="clear formBox">
+ <fieldset>
+ <legend>Flow Control Settings</legend>
<div class="clear">
<div class="formLabel-labelCell">Capacity:</div>
<div class="formLabel-controlCell">
@@ -194,11 +193,13 @@
trim: true"/>
</div>
</div>
+ </fieldset>
<div class="clear"></div>
</div>
- <br/>
- <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Alerting Settings', open: false">
+ <div class="clear formBox">
+ <fieldset>
+ <legend>Alerting Settings</legend>
<div class="clear">
<div class="formLabel-labelCell">Queue Depth:</div>
<div class="formLabel-controlCell">
@@ -264,11 +265,13 @@
trim: true"/>
</div>
</div>
+ </fieldset>
<div class="clear"></div>
</div>
- <br/>
- <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Other Settings', open: false">
+ <div class="clear formBox">
+ <fieldset>
+ <legend>Other Settings</legend>
<div class="clear">
<div class="formLabel-labelCell">Maximum Delivery Retries:</div>
<div class="formLabel-controlCell">
@@ -323,9 +326,14 @@
title: 'Controls where a shared groups feature is enabled'"/>
</div>
</div>
+ </fieldset>
<div class="clear"></div>
</div>
+ <div class="clear" data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'Context variables', open: false">
+ <div id="formAddQueue.context" ></div>
+ </div>
+
<div class="dijitDialogPaneActionBar">
<!-- submit buttons -->
<input type="submit" value="Create Queue" label="Create Queue" dojoType="dijit.form.Button" />
diff --git a/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/java/broker-plugins/management-http/src/main/java/resources/css/common.css
index 7c8ca2e644..d04117b266 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/css/common.css
+++ b/java/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -262,7 +262,6 @@ div .messages {
/* Required to keep queue type radio buttons on one line when dialog adds scrollbar */
#addQueue {
- max-height: 350px;
overflow: auto;
width: 630px;
}
@@ -305,4 +304,4 @@ div .messages {
width:100%;
max-height: 140px;
overflow: auto;
-} \ No newline at end of file
+}
diff --git a/java/broker-plugins/management-http/src/main/java/resources/editQueue.html b/java/broker-plugins/management-http/src/main/java/resources/editQueue.html
new file mode 100644
index 0000000000..aff2b5dfa5
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/editQueue.html
@@ -0,0 +1,300 @@
+<!--
+ ~ 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.
+ -->
+<div class="dijitHidden">
+ <div data-dojo-type="dijit.Dialog" data-dojo-props="title:'Edit Queue'" id="editQueue">
+ <form id="formEditQueue" method="post" dojoType="dijit.form.Form">
+ <div id="formEditQueue.allFields">
+ <div id="formEditQueue.contentPane">
+ <div class="editNoteBanner">NOTE: All changes will only take effect after Virtual Host restart.</div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Queue Name:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.name"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'name',
+ placeHolder: 'queue name',
+ required: true,
+ promptMessage: 'Name of queue',
+ disabled: 'true'"/>
+ </div>
+ </div>
+
+ <div class="clear">
+ <div class="formLabel-labelCell">Queue Type:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.type"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'type',
+ placeHolder: 'queue type',
+ required: true,
+ promptMessage: 'Type of queue',
+ disabled: 'true'"/>
+ </div>
+ </div>
+ <div class="clear"></div>
+
+ <div id="formEditQueueType:priority" class="hidden typeSpecificDiv">
+ <div class="clear">
+ <div class="formLabel-labelCell">Priorities:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.priorities"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'priorities',
+ disabled: 'true',
+ promptMessage: 'Number of priorities supported by the queue',
+ title: 'Enter the number of priorities supported by the queue',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear"></div>
+ </div>
+
+ <div id="formEditQueueType:lvq" class="hidden typeSpecificDiv">
+ <div class="clear">
+ <div class="formLabel-labelCell">LVQ Message Property:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.lvqKey"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'lvqKey',
+ disabled: 'true',
+ promptMessage: 'Name of the message property used to perform the conflation',
+ title: 'Enter the name of the message property used to perform the conflation',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear"></div>
+ </div>
+
+ <div id="formEditQueueType:sorted" class="hidden typeSpecificDiv">
+ <div class="clear">
+ <div class="formLabel-labelCell">Sort Message Property*:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.sortKey"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'sortKey',
+ disabled: 'true',
+ promptMessage: 'Name of the message property used for sorting the messages on the queue',
+ title: 'Enter the name of the message property used for sorting the messages on the queue',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear"></div>
+ </div>
+
+ <div class="clear">
+ <div class="formLabel-labelCell">Durable?</div>
+ <div class="formLabel-controlCell">
+ <input type="checkbox" id="formEditQueue.durable"
+ dojoType="dijit.form.CheckBox"
+ data-dojo-props="
+ name: 'durable',
+ value: 'durable',
+ disabled: 'true'"/>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Persist Messages?</div>
+ <div class="formLabel-controlCell">
+ <select id="formEditQueue.messageDurability"
+ dojoType="dijit.form.FilteringSelect"
+ data-dojo-props="
+ name: 'messageDurability',
+ value: '',
+ searchAttr: 'name',
+ required: false,
+ promptMessage: 'Message persistence override. If not default, messages arriving will have persistence setting overridden',
+ title: 'Enter message persistence override'">
+ <option value="ALWAYS">Always</option>
+ <option value="DEFAULT">Default</option>
+ <option value="NEVER">Never</option>
+ </select>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Maximum Ttl:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.maximumMessageTtl"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'maximumMessageTtl',
+ placeHolder: 'ttl in ms',
+ promptMessage: 'Maximum message time to live (ttl) in ms. Messages arriving with larger ttl values will be overridden by this value',
+ title: 'Enter the maximum message time to live in milliseconds',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Minimum Ttl:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.minimumMessageTtl"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'minimumMessageTtl',
+ placeHolder: 'ttl in ms',
+ promptMessage: 'Minimum message time to live (ttl) in ms. Messages arriving with smaller ttl values will be overridden by this value',
+ title: 'Enter the minimum message time to live in milliseconds',
+ trim: true"/>
+ </div>
+ </div>
+
+ <div class="clear"></div>
+
+ <div class="clear formBox">
+ <fieldset>
+ <legend>Flow Control Settings</legend>
+ <div class="clear">
+ <div class="formLabel-labelCell">Capacity:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.queueFlowControlSizeBytes"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'queueFlowControlSizeBytes',
+ placeHolder: 'size in bytes',
+ promptMessage: 'Ceiling (in bytes) at which queue will begin to throttle sessions producing messages',
+ title: 'Enter the ceiling (in bytes) at which queue will begin to throttle sessions producing messages',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Resume Capacity:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.queueFlowResumeSizeBytes"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'queueFlowResumeSizeBytes',
+ placeHolder: 'size in bytes',
+ promptMessage: 'Floor (in bytes) at which queue will cease to throttle sessions producing messages',
+ title: 'Enter the floor (in bytes) at which queue will cease to throttle sessions producing messages',
+ trim: true"/>
+ </div>
+ </div>
+ </fieldset>
+ <div class="clear"></div>
+ </div>
+
+ <div class="clear formBox">
+ <fieldset>
+ <legend>Alerting Settings</legend>
+ <div class="clear">
+ <div class="formLabel-labelCell">Queue Depth:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.alertThresholdQueueDepthMessages"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'alertThresholdQueueDepthMessages',
+ placeHolder: 'number of messages',
+ promptMessage: 'Ceiling value for number of messages on queue before alerts will be generated',
+ title: 'Enter the ceiling value for number of messages on queue before alerts will be generated',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Queue Depth:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.alertThresholdQueueDepthBytes"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'alertThresholdQueueDepthBytes',
+ placeHolder: 'total message size in bytes',
+ promptMessage: 'Ceiling value (in bytes) for total size of all messages on the queue before alerts will be generated',
+ title: 'Enter the ceiling value (in bytes) for total size of all messages on the queue before alerts will be generated',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Message Age:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.alertThresholdMessageAge"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'alertThresholdMessageAge',
+ placeHolder: 'time in ms',
+ promptMessage: 'Message age (in milliseconds) above which alerts will be generated',
+ title: 'Enter the message age (in milliseconds) above which alerts will be generated',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Message Size:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.alertThresholdMessageSize"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'alertThresholdMessageSize',
+ placeHolder: 'message size in bytes',
+ promptMessage: 'Message size (in bytes) above which alerts will be generated',
+ title: 'Enter the message size (in bytes) above which alerts will be generated',
+ trim: true"/>
+ </div>
+ </div>
+ <div class="clear">
+ <div class="formLabel-labelCell">Gap between alerts:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.alertRepeatGap"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'alertRepeatGap',
+ placeHolder: 'time in ms',
+ promptMessage: 'Minimum time (in milliseconds) between each alert',
+ title: 'Enter the minimum time (in milliseconds) between each alert.',
+ trim: true"/>
+ </div>
+ </div>
+ </fieldset>
+ <div class="clear"></div>
+ </div>
+
+ <div class="clear formBox">
+ <fieldset>
+ <legend>Other Settings</legend>
+ <div class="clear">
+ <div class="formLabel-labelCell">Maximum Delivery Retries:</div>
+ <div class="formLabel-controlCell">
+ <input type="text" id="formEditQueue.maximumDeliveryAttempts"
+ data-dojo-type="dijit/form/ValidationTextBox"
+ data-dojo-props="
+ name: 'maximumDeliveryAttempts',
+ placeHolder: 'number of retries',
+ promptMessage: 'Maximum number of delivery attempts before the message will be sent to the alternate exchange',
+ title: 'Enter the maximum number of delivery attempts before the message will be sent to the alternate exchange',
+ trim: true"/>
+ </div>
+ </div>
+ </fieldset>
+ <div class="clear"></div>
+ </div>
+
+ <div data-dojo-type="dijit/TitlePane" data-dojo-props="title: 'Context variables', open: false">
+ <div id="formEditQueue.context" ></div>
+ </div>
+ </div>
+ <div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit/form/Button" id="formEditQueue.saveButton" data-dojo-props="label: 'Save'">Save</button>
+ <button data-dojo-type="dijit/form/Button" id="formEditQueue.cancelButton" data-dojo-props="label: 'Cancel'" ></button>
+ </div>
+ </div>
+
+ </form>
+ </div>
+</div>
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js
index e5d341de91..a3e4023273 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ContextVariablesEditor.js
@@ -77,8 +77,8 @@ function (util, xhr, declare, array, connect, lang, domConstruct, parser, query,
var addButton = registry.byNode(addButtonNode);
var deleteButton = registry.byNode(deleteButtonNode);
var layout = [[
- { name: "Name", field: "name", width: "40%", editable: true, selectOnClick: false, type: dojox.grid.cells._Widget, widgetClass: dijit.form.TextBox },
- { name: 'Actual Value', field: 'actualValue', width: '30%', editable: true, selectOnClick: false, type: dojox.grid.cells._Widget, widgetClass: dijit.form.TextBox},
+ { name: "Name", field: "name", width: "40%", editable: true},
+ { name: 'Actual Value', field: 'actualValue', width: '30%', editable: true},
{ name: 'Effective Value', field: 'effectiveValue', width: '30%', editable: false}
]];
var data = [];
@@ -177,6 +177,38 @@ function (util, xhr, declare, array, connect, lang, domConstruct, parser, query,
}
this.setData(actualValues, allEffectiveValues, inheritedActualValues);
},
+ loadInheritedData: function(restUrl)
+ {
+ var allEffectiveValues = null;
+ xhr.get(
+ {
+ url: restUrl,
+ sync: true,
+ content: { actuals: false },
+ handleAs: "json",
+ load: function(data)
+ {
+ allEffectiveValues = data[0].context;
+ }
+ }
+ );
+
+ var inheritedActualValues = null;
+ xhr.get(
+ {
+ url: restUrl,
+ sync: true,
+ content: { actuals: true, inheritedActuals: true},
+ handleAs: "json",
+ load: function(data)
+ {
+ inheritedActualValues = data[0].context;
+ }
+ }
+ );
+
+ this.setData({}, allEffectiveValues, inheritedActualValues);
+ },
setData: function(actualValues, allEffectiveValues, inheritedActualValues)
{
this.value = actualValues;
@@ -523,4 +555,4 @@ function (util, xhr, declare, array, connect, lang, domConstruct, parser, query,
}
});
-}); \ No newline at end of file
+});
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
index b4ef7b4403..5b441a7b2f 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Queue.js
@@ -34,6 +34,7 @@ define(["dojo/_base/xhr",
"qpid/management/moveCopyMessages",
"qpid/management/showMessage",
"qpid/management/UserPreferences",
+ "qpid/management/editQueue",
"dojo/store/JsonRest",
"dojox/grid/EnhancedGrid",
"dojo/data/ObjectStore",
@@ -42,7 +43,7 @@ define(["dojo/_base/xhr",
"dojox/grid/enhanced/plugins/IndirectSelection",
"dojo/domReady!"],
function (xhr, parser, query, registry, connect, event, json, properties, updater, util, formatter,
- UpdatableStore, addBinding, moveMessages, showMessage, UserPreferences, JsonRest, EnhancedGrid, ObjectStore, entities) {
+ UpdatableStore, addBinding, moveMessages, showMessage, UserPreferences, editQueue, JsonRest, EnhancedGrid, ObjectStore, entities) {
function Queue(name, parent, controller) {
this.name = name;
@@ -172,6 +173,12 @@ define(["dojo/_base/xhr",
event.stop(evt);
that.deleteQueue();
});
+ var editQueueButton = query(".editQueueButton", contentPane.containerNode)[0];
+ connect.connect(registry.byNode(editQueueButton), "onClick",
+ function(evt){
+ event.stop(evt);
+ editQueue.show({nodeName:that.modelObj.parent.parent.name, hostName:that.modelObj.parent.name,queueName:that.name});
+ });
UserPreferences.addListener(that);
}});
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
index 444ed67d63..236efb2efa 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addQueue.js
@@ -27,7 +27,9 @@ define(["dojo/_base/xhr",
"dojo/_base/array",
"dojo/_base/event",
'dojo/_base/json',
+ "dojo/query",
'qpid/common/util',
+ "qpid/common/ContextVariablesEditor",
"dijit/form/NumberSpinner", // required by the form
/* dojox/ validate resources */
"dojox/validate/us", "dojox/validate/web",
@@ -42,22 +44,14 @@ define(["dojo/_base/xhr",
/* basic dojox classes */
"dojox/form/BusyButton", "dojox/form/CheckedMultiSelect",
"dojo/domReady!"],
- function (xhr, dom, construct, win, registry, parser, array, event, json, util) {
+ function (xhr, dom, construct, win, registry, parser, array, event, json, query, util) {
var addQueue = {};
var node = construct.create("div", null, win.body(), "last");
- var typeSpecificFields = {
- priorities: "priority",
- lvqKey: "lvq",
- sortKey: "sorted"
- };
-
- var requiredFields = {
- priority: "priorities",
- sorted: "sortkey"
- };
+ var typeSpecificFields = { priorities: "priority", lvqKey: "lvq", sortKey: "sorted" };
+ var requiredFields = { sorted: "sortKey"};
var fieldConverters = {
queueFlowControlSizeBytes: parseInt,
@@ -96,8 +90,8 @@ define(["dojo/_base/xhr",
newQueue["messageGroupSharedGroups"] = true;
}
}
- else if (!typeSpecificFields.hasOwnProperty(propName) ||
- formValues[ "type" ] === typeSpecificFields[ propName ]) {
+ else if (!typeSpecificFields.hasOwnProperty(propName) || formValues[ "type" ] === typeSpecificFields[ propName ])
+ {
if(formValues[ propName ] !== "") {
if (fieldConverters.hasOwnProperty(propName))
{
@@ -125,36 +119,29 @@ define(["dojo/_base/xhr",
addQueue.dialogNode = dom.byId("addQueue");
parser.instantiate([addQueue.dialogNode]);
- // for children which have name type, add a function to make all the associated rows
- // visible / invisible as the radio button is checked / unchecked
-
+ // for children which have name type, add a function to make all the associated atrributes
+ // visible / invisible as the select is changed
theForm = registry.byId("formAddQueue");
- array.forEach(theForm.getDescendants(), function(widget)
+ var typeSelector = registry.byId("formAddQueue.type");
+ typeSelector.on("change", function(value)
+ {
+ query(".typeSpecificDiv").forEach(function(node, index, arr)
{
- if(widget.name === "type") {
- widget.on("change", function(isChecked) {
-
- var objId = widget.id + ":fields";
- var obj = registry.byId(objId);
- if(obj) {
- if(isChecked) {
- obj.domNode.style.display = "block";
- } else {
- obj.domNode.style.display = "none";
- }
- obj.resize();
- var widgetValue = widget.value;
- if (requiredFields.hasOwnProperty(widgetValue))
- {
- dijit.byId('formAddQueue.' + requiredFields[widgetValue]).required = isChecked;
- }
-
- util.applyMetadataToWidgets(obj.domNode, "Queue", widgetValue);
- }
- })
+ if (node.id === "formAddQueueType:" + value)
+ {
+ node.style.display = "block";
+ util.applyMetadataToWidgets(node, "Queue", value);
+ }
+ else
+ {
+ node.style.display = "none";
}
-
});
+ for(var requiredField in requiredFields)
+ {
+ dijit.byId('formAddQueue.' + requiredFields[requiredField]).required = (requiredField == value);
+ }
+ });
theForm.on("submit", function(e) {
@@ -200,6 +187,14 @@ define(["dojo/_base/xhr",
registry.byId("addQueue").show();
util.applyMetadataToWidgets(form.domNode, "Queue", "standard");
+ if (!this.context)
+ {
+ this.context = new qpid.common.ContextVariablesEditor({name: 'context', title: 'Context variables'});
+ this.context.placeAt(dom.byId("formAddQueue.context"));
+ }
+
+ var escapedUrl = "api/latest/virtualhost/" + encodeURIComponent(addQueue.vhostnode) + "/" + encodeURIComponent(addQueue.vhost);
+ this.context.loadInheritedData(escapedUrl);
};
return addQueue;
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
index 226674bf5a..0a18a8909b 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addVirtualHostNodeAndVirtualHost.js
@@ -134,35 +134,10 @@ define(["dojo/_base/xhr",
this.virtualHostContext.placeAt(dom.byId("addVirtualHost.context"));
}
- var inheritedActualValues = null;
- xhr.get(
- {
- url: "api/latest/broker",
- sync: true,
- content: { actuals: true, inheritedActuals: true},
- handleAs: "json",
- load: function(data)
- {
- inheritedActualValues = data[0].context;
- }
- }
- );
- var effectiveValues = null;
- xhr.get(
- {
- url: "api/latest/broker",
- sync: true,
- handleAs: "json",
- load: function(data)
- {
- effectiveValues = data[0].context;
- }
- }
- );
+ this.virtualHostNodeContext.loadInheritedData("api/latest/broker");
+ this.virtualHostContext.setData({}, this.virtualHostNodeContext.effectiveValues,this.virtualHostNodeContext.inheritedActualValues);
- this.virtualHostNodeContext.setData({},effectiveValues,inheritedActualValues);
- this.virtualHostContext.setData({},effectiveValues,inheritedActualValues);
this.dialog.show();
if (!this.resizeEventRegistered)
{
diff --git a/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editQueue.js b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editQueue.js
new file mode 100644
index 0000000000..06c9672efe
--- /dev/null
+++ b/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/editQueue.js
@@ -0,0 +1,232 @@
+/*
+ *
+ * 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.
+ *
+ */
+define(["dojo/_base/xhr",
+ "dojox/html/entities",
+ "dojo/_base/array",
+ "dojo/_base/event",
+ "dojo/_base/lang",
+ "dojo/_base/window",
+ "dojo/dom",
+ "dojo/dom-construct",
+ "dijit/registry",
+ "dojo/parser",
+ 'dojo/json',
+ "dojo/query",
+ "qpid/common/util",
+ "dojo/text!editQueue.html",
+ "qpid/common/ContextVariablesEditor",
+ "dijit/Dialog",
+ "dijit/form/CheckBox",
+ "dijit/form/FilteringSelect",
+ "dijit/form/ValidationTextBox",
+ "dijit/form/Button",
+ "dijit/form/Form",
+ "dojox/validate/us",
+ "dojox/validate/web",
+ "dojo/domReady!"],
+ function (xhr, entities, array, event, lang, win, dom, domConstruct, registry, parser, json, query, util, template)
+ {
+ var fields = ["name",
+ "type",
+ "durable",
+ "messageDurability",
+ "maximumMessageTtl",
+ "minimumMessageTtl",
+ "queueFlowControlSizeBytes",
+ "queueFlowResumeSizeBytes",
+ "alertThresholdQueueDepthMessages",
+ "alertThresholdQueueDepthBytes",
+ "alertThresholdMessageAge",
+ "alertThresholdMessageSize",
+ "alertRepeatGap",
+ "maximumDeliveryAttempts",
+ "priorities",
+ "lvqKey",
+ "sortKey"];
+
+ var numericFieldNames = ["maximumMessageTtl",
+ "minimumMessageTtl",
+ "queueFlowControlSizeBytes",
+ "queueFlowResumeSizeBytes",
+ "alertThresholdQueueDepthMessages",
+ "alertThresholdQueueDepthBytes",
+ "alertThresholdMessageAge",
+ "alertThresholdMessageSize",
+ "alertRepeatGap",
+ "maximumDeliveryAttempts"];
+
+ var queueEditor =
+ {
+ init: function()
+ {
+ var that=this;
+ this.containerNode = domConstruct.create("div", {innerHTML: template});
+ parser.parse(this.containerNode);
+ this.allFieldsContainer = dom.byId("formEditQueue.allFields");
+ this.dialog = registry.byId("editQueue");
+ this.saveButton = registry.byId("formEditQueue.saveButton");
+ this.cancelButton = registry.byId("formEditQueue.cancelButton");
+ this.cancelButton.on("click", function(e){that._cancel(e);});
+ this.saveButton.on("click", function(e){that._save(e);});
+ for(var i = 0; i < fields.length; i++)
+ {
+ var fieldName = fields[i];
+ this[fieldName] = registry.byId("formEditQueue." + fieldName);
+ }
+ this.form = registry.byId("formEditQueue");
+ this.form.on("submit", function(){return false;});
+ this.typeSelector = registry.byId("formEditQueue.type");
+ },
+ show: function(hostData)
+ {
+ var that=this;
+ if (!this.context)
+ {
+ this.context = new qpid.common.ContextVariablesEditor({name: 'context', title: 'Context variables'});
+ this.context.placeAt(dom.byId("formEditQueue.context"));
+ }
+ this.query = "api/latest/queue/" + encodeURIComponent(hostData.nodeName) + "/" + encodeURIComponent(hostData.hostName) + "/" + encodeURIComponent(hostData.queueName);
+ this.dialog.set("title", "Edit Queue - " + entities.encode(String(hostData.queueName)));
+ xhr.get(
+ {
+ url: this.query,
+ sync: true,
+ content: { actuals: true },
+ handleAs: "json",
+ load: function(data)
+ {
+ that._show(data[0], hostData);
+ }
+ }
+ );
+ var queueType = this.typeSelector.get("value");
+ query(".typeSpecificDiv").forEach(function(node, index, arr){
+ if (node.id === "formEditQueueType:" + queueType)
+ {
+ node.style.display = "block";
+ util.applyMetadataToWidgets(node, "Queue", queueType);
+ }
+ else
+ {
+ node.style.display = "none";
+ }
+ });
+ },
+ destroy: function()
+ {
+ if (this.dialog)
+ {
+ this.dialog.destroyRecursive();
+ this.dialog = null;
+ }
+
+ if (this.containerNode)
+ {
+ domConstruct.destroy(this.containerNode);
+ this.containerNode = null;
+ }
+ },
+ _cancel: function(e)
+ {
+ this.dialog.hide();
+ },
+ _save: function(e)
+ {
+ event.stop(e);
+ if(this.form.validate())
+ {
+ var data = util.getFormWidgetValues(this.form, this.initialData);
+ var context = this.context.get("value");
+ if (context && !util.equals(context, this.initialData.context))
+ {
+ data["context"] = context;
+ }
+ var success = false,failureReason=null;
+ xhr.put({
+ url: this.query,
+ sync: true,
+ handleAs: "json",
+ headers: { "Content-Type": "application/json"},
+ putData: json.stringify(data),
+ load: function(x) {success = true; },
+ error: function(error) {success = false; failureReason = error;}
+ });
+
+ if(success === true)
+ {
+ this.dialog.hide();
+ }
+ else
+ {
+ util.xhrErrorHandler(failureReason);
+ }
+ }
+ else
+ {
+ alert('Form contains invalid data. Please correct first');
+ }
+ },
+ _show:function(actualData, effectiveData)
+ {
+
+ this.initialData = actualData;
+ for(var i = 0; i < fields.length; i++)
+ {
+ var fieldName = fields[i];
+ var widget = this[fieldName];
+ widget.reset();
+
+ if (widget instanceof dijit.form.CheckBox)
+ {
+ widget.set("checked", actualData[fieldName]);
+ }
+ else
+ {
+ widget.set("value", actualData[fieldName]);
+ }
+ }
+
+ var that = this;
+ util.applyMetadataToWidgets(that.allFieldsContainer, "Queue", actualData.type);
+
+ this.context.load(this.query, {actualValues:actualData.context, effectiveValues:effectiveData.context});
+
+ // Add regexp to the numeric fields
+ for(var i = 0; i < numericFieldNames.length; i++)
+ {
+ this[numericFieldNames[i]].set("regExpGen", util.numericOrContextVarRegexp);
+ }
+
+ this.dialog.startup();
+ this.dialog.show();
+ if (!this.resizeEventRegistered)
+ {
+ this.resizeEventRegistered = true;
+ util.resizeContentAreaAndRepositionDialog(dom.byId("formEditQueue.contentPane"), this.dialog);
+ }
+ }
+ };
+
+ queueEditor.init();
+
+ return queueEditor;
+ }
+);
diff --git a/java/broker-plugins/management-http/src/main/java/resources/showQueue.html b/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
index e5b9699c64..a068868e7f 100644
--- a/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
+++ b/java/broker-plugins/management-http/src/main/java/resources/showQueue.html
@@ -198,7 +198,7 @@
</div>
</div>
<div class="clear">
- <div class="formLabel-labelCell">Alert frequency:</div>
+ <div class="formLabel-labelCell">Gap between alerts:</div>
<div>
<span class="alertRepeatGap"></span>
<span class="alertRepeatGapUnits"></span>
@@ -208,6 +208,7 @@
</div>
<div class="dijitDialogPaneActionBar">
+ <button data-dojo-type="dijit.form.Button" class="editQueueButton" type="button">Edit Queue</button>
<button data-dojo-type="dijit.form.Button" class="deleteQueueButton" type="button">Delete Queue</button>
</div>
</div>
diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
index a38aa9e349..6c962c2901 100644
--- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
+++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java
@@ -29,6 +29,7 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import javax.management.InstanceAlreadyExistsException;
import javax.management.JMException;
import org.apache.log4j.Logger;
@@ -103,7 +104,7 @@ public class JMXManagementPluginImpl
return _usePlatformMBeanServer;
}
- @StateTransition(currentState = State.UNINITIALIZED, desiredState = State.ACTIVE)
+ @StateTransition(currentState = {State.UNINITIALIZED,State.ERRORED}, desiredState = State.ACTIVE)
private void doStart() throws JMException, IOException
{
_allowPortActivation = true;
@@ -340,8 +341,8 @@ public class JMXManagementPluginImpl
mbean = new UserManagementMBean((PasswordCredentialManagingAuthenticationProvider<?>) object, _objectRegistry);
registerMBean(object, _pluginMBeanProvider, mbean);
}
- createAdditionalMBeansFromProvidersIfNecessary(object, _objectRegistry);
}
+ createAdditionalMBeansFromProvidersIfNecessary(object, _objectRegistry);
}
}
return mbean;
@@ -351,10 +352,27 @@ public class JMXManagementPluginImpl
{
if (!providerMBeanExists(host, _pluginMBeanProvider))
{
- VirtualHostMBean mbean = new VirtualHostMBean(host, _objectRegistry);
- registerMBean(host, _pluginMBeanProvider, mbean);
host.addChangeListener(_changeListener);
- return mbean;
+ try
+ {
+ VirtualHostMBean mbean = new VirtualHostMBean(host, _objectRegistry);
+ registerMBean(host, _pluginMBeanProvider, mbean);
+ return mbean;
+ }
+ catch (InstanceAlreadyExistsException e)
+ {
+ VirtualHostNode parent = host.getParent(VirtualHostNode.class);
+ Set<ConfiguredObject<?>> registered = _children.keySet();
+ for (ConfiguredObject<?> object: registered)
+ {
+ if (object instanceof VirtualHost && object.getParent(VirtualHostNode.class) == parent)
+ {
+ LOGGER.warn("Unexpected MBean is found for VirtualHost " + object + " belonging to node " + parent);
+ }
+ }
+
+ throw e;
+ }
}
return null;
}
@@ -392,24 +410,21 @@ public class JMXManagementPluginImpl
}
unregisterObjectMBeans(object);
_children.remove(object);
- destroyChildrenMBeansIfVirtualHostNode(object);
+ destroyChildrenMBeans(object);
}
}
}
- private void destroyChildrenMBeansIfVirtualHostNode(ConfiguredObject<?> child)
+ private void destroyChildrenMBeans(ConfiguredObject<?> object)
{
- if (child instanceof VirtualHostNode)
+ for (Iterator<ConfiguredObject<?>> iterator = _children.keySet().iterator(); iterator.hasNext();)
{
- for (Iterator<ConfiguredObject<?>> iterator = _children.keySet().iterator(); iterator.hasNext();)
+ ConfiguredObject<?> registeredObject = iterator.next();
+ ConfiguredObject<?> parent = registeredObject.getParent(object.getCategoryClass());
+ if (parent == object)
{
- ConfiguredObject<?> registeredObject = iterator.next();
- ConfiguredObject<?> parent = registeredObject.getParent(VirtualHostNode.class);
- if (parent == child)
- {
- registeredObject.removeChangeListener(_changeListener);
- unregisterObjectMBeans(registeredObject);
- }
+ registeredObject.removeChangeListener(_changeListener);
+ unregisterObjectMBeans(registeredObject);
iterator.remove();
}
}
diff --git a/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
index f644b8f46b..3f5215219b 100644
--- a/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
+++ b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemorySystemConfigImpl.java
@@ -26,6 +26,7 @@ import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.LogRecorder;
import org.apache.qpid.server.model.AbstractSystemConfig;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.ManagedObject;
import org.apache.qpid.server.model.SystemConfigFactoryConstructor;
@@ -39,9 +40,10 @@ public class MemorySystemConfigImpl extends AbstractSystemConfig<MemorySystemCon
public MemorySystemConfigImpl(final TaskExecutor taskExecutor,
final EventLogger eventLogger,
final LogRecorder logRecorder,
- final BrokerOptions brokerOptions)
+ final BrokerOptions brokerOptions,
+ final BrokerShutdownProvider brokerShutdownProvider)
{
- super(taskExecutor, eventLogger, logRecorder, brokerOptions);
+ super(taskExecutor, eventLogger, logRecorder, brokerOptions, brokerShutdownProvider);
}
@Override
diff --git a/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef b/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef
index 73d1a93b11..2327fb610f 100644
--- a/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef
+++ b/java/perftests/etc/chartdefs/1001-MessageSize-Transient-ByteSec.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Impact of Message Size Bytes/S
chartSubtitle=Transient messages
-chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes ${baselineName}.
+chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes ${baselineName}, single queue.
xAxisTitle=Message Size (B)
yAxisTitle=Throughput (KB/s)
diff --git a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef
index 2cd5e8d9d5..cd7029963b 100644
--- a/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef
+++ b/java/perftests/etc/chartdefs/1002-MessageSize-Persistent-ByteSec.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Impact of Message Size Bytes/S
chartSubtitle=Persistent messages
-chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue.
xAxisTitle=Message Size (B)
yAxisTitle=Throughput (KB/s)
diff --git a/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef b/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef
index ae59f61741..979136e2ed 100644
--- a/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef
+++ b/java/perftests/etc/chartdefs/1003-MessageSize-Transient-MsgSec.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Impact of Message Size
chartSubtitle=Transient messages
-chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes, single queue.
xAxisTitle=Message Size (B)
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef b/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef
index f5ce7662f3..fef5509107 100644
--- a/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef
+++ b/java/perftests/etc/chartdefs/1004-MessageSize-Persistent-MsgSec.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Impact of Message Size
chartSubtitle=Persistent messages
-chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue.
xAxisTitle=Message Size (B)
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef
index d67c8881de..8ad987ea74 100644
--- a/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef
+++ b/java/perftests/etc/chartdefs/1011-VaryingNumberOfProducers-AutoAck.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Varying number of producers - auto ack
chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue.
xAxisTitle=Producers
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef
index b78c7c53d2..599c37cf60 100644
--- a/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef
+++ b/java/perftests/etc/chartdefs/1012-VaryingNumberOfConsumers-AutoAck.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Varying number of consumers - auto ack
chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue.
xAxisTitle=Consumers
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef b/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
index d00d1e9d00..d22594ca89 100644
--- a/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
+++ b/java/perftests/etc/chartdefs/1015-VaryingNumberOfProducers-SessionTrans.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Varying number of producers - transacted
chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB, single queue.
xAxisTitle=Producers
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef b/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
index a808334560..0e781177fe 100644
--- a/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
+++ b/java/perftests/etc/chartdefs/1016-VaryingNumberOfConsumers-SessionTrans.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Varying number of consumers - transacted
chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, transacted, with message payload 1KB, single queue.
xAxisTitle=Consumers
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef
index a8abd6f02c..7d1abe6418 100644
--- a/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef
+++ b/java/perftests/etc/chartdefs/1021-AcknowledgementModes-Persistent.chartdef
@@ -20,7 +20,7 @@
chartType=BAR
chartTitle=Performance of acknowledgement modes
chartSubtitle=Persistent messages (1KB)
-chartDescription=1P 1C, persistent, with message payload 1KB.
+chartDescription=1P 1C, persistent, with message payload 1KB, single queue.
xAxisTitle=Acknowledge mode (0=session transacted; 1=auto-acknowledge)
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef
index ebc040cd25..662cb8529d 100644
--- a/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef
+++ b/java/perftests/etc/chartdefs/1022-AcknowledgementModes-Transient.chartdef
@@ -20,7 +20,7 @@
chartType=BAR
chartTitle=Performance of acknowledgement modes
chartSubtitle=Transient messages (1024b)
-chartDescription=1P 1C, transient, with message payload 1KB.
+chartDescription=1P 1C, transient, with message payload 1KB, single queue.
xAxisTitle=Acknowledge mode (0=session transacted; 1=auto-acknowledge)
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef b/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef
index bf55750c4a..1b37d50c33 100644
--- a/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef
+++ b/java/perftests/etc/chartdefs/1030-BatchSize-Equal.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Transaction Batch Sizes Equal
chartSubtitle=Persistent 1KB messages
-chartDescription=1P 1C, persistent, transacted with message payload 1KB with producer/consumer batch size varying between 1-400 messages for both P and C
+chartDescription=1P 1C, persistent, transacted with message payload 1KB with producer/consumer batch size varying between 1-400 messages for both P and C, single queue.
xAxisTitle=Batch Size
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef b/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef
index 5f846c6ca0..cd72663552 100644
--- a/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef
+++ b/java/perftests/etc/chartdefs/1031-BatchSize-Unequal.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Transaction Batch Size Unequal
chartSubtitle=Persistent 1KB messages
-chartDescription=1P 1C, persistent, transacted with message payload 1KB with fixed batch size 1 for one party whilst other varies between 1-400 messages
+chartDescription=1P 1C, persistent, transacted with message payload 1KB with fixed batch size 1 for one party whilst other varies between 1-400 messages, single queue.
xAxisTitle=Batch Size
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef
index 248db4905f..3ba42e2c00 100644
--- a/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef
+++ b/java/perftests/etc/chartdefs/1040-QueueTypes.chartdef
@@ -20,7 +20,7 @@
chartType=BAR
chartTitle=Queue Types
chartSubtitle=Persistent 1KB messages
-chartDescription=1P 1C, persistent, auto-ack with message payload 1KB. Sorted queue - 160,000 random keys, Priority - iteriates priority 0..9.
+chartDescription=1P 1C, persistent, auto-ack with message payload 1KB. Sorted queue - 160,000 random keys, Priority - iteriates priority 0..9, single queue.
xAxisTitle=Queue Types
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef b/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef
index 50816a8cd3..c92974ddc0 100644
--- a/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef
+++ b/java/perftests/etc/chartdefs/1050-VaryingNumberOfProducerSessionsSingleConnection.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Varying number of producer sessions on single connection
chartSubtitle=Persistent messages (1024b)
-chartDescription=1-80P transacted on single connection, 20C transacted on separate connections, persistent, message payload 1KB.
+chartDescription=1-80P transacted on single connection, 20C transacted on separate connections, persistent, message payload 1KB, single queue.
xAxisTitle=Number of producer sessions
yAxisTitle=Throughput (KB/s)
diff --git a/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef
index 67821b8581..95f717ad95 100644
--- a/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef
+++ b/java/perftests/etc/chartdefs/1300-QueueConsumersWithNonOverlappingSelectors-Transient.chartdef
@@ -22,7 +22,7 @@ chartTitle=Impact of non-overlapping selectors on queue consumers with transient
chartSubtitle=Transient 1KB messages
xAxisTitle=Consumers
yAxisTitle=Throughput (messages/s)
-chartDescription=Impact of non-overlapping selectors on queue consumers with transient messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32.
+chartDescription=Impact of non-overlapping selectors on queue consumers with transient messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32, single queue.
series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - NON_PERSISTENT%'
series.1.legend=Current
diff --git a/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef
index 7fbf55a2ab..302b508413 100644
--- a/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef
+++ b/java/perftests/etc/chartdefs/1301-QueueConsumersWithNonOverlappingSelectors-Persistent.chartdef
@@ -22,7 +22,7 @@ chartTitle=Impact of non-overlapping selectors on queue consumers with persisten
chartSubtitle=Persistent 1KB messages
xAxisTitle=Consumers
yAxisTitle=Throughput (messages/s)
-chartDescription=Impact of non-overlapping selectors on queue consumers with persistent messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32..
+chartDescription=Impact of non-overlapping selectors on queue consumers with persistent messages, auto-ack, message payload of 1024 bytes, 1 producer, varying number of consumers from 1 to 32, single queue.
series.1.statement=SELECT totalNumberOfConsumers, throughputMessagesPerS FROM QueueConsumersWithNonOverlappingSelectors WHERE participantName = 'All' and testName like '%non overlapping - PERSISTENT'
diff --git a/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef b/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef
index 1734265adf..c0796ca8a3 100644
--- a/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef
+++ b/java/perftests/etc/chartdefs/1302-QueueConsumersWithOverlappingSelectors-Transient.chartdef
@@ -22,7 +22,7 @@ chartTitle=Impact of 50%-overlapping selectors in queue consumers with transient
chartSubtitle=Transient 1KB messages
xAxisTitle=Consumers
yAxisTitle=Throughput (messages/s)
-chartDescription=Impact of 50%-overlapping selectors in queue consumers with transient messages, auto-ack, message payload 1KB, 1 producer, varying number of consumers from 2 to 32.
+chartDescription=Impact of 50%-overlapping selectors in queue consumers with transient messages, auto-ack, message payload 1KB, 1 producer, varying number of consumers from 2 to 32, single queue.
series.1.statement=SELECT totalNumberOfConsumers,throughputMessagesPerS FROM QueueConsumersWithOverlappingSelectors WHERE participantName = 'All' and testName like '%50_ overlapping - NON_PERSISTENT%'
series.1.legend=Current
diff --git a/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef b/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef
index ef7beb252d..a2c75c1037 100644
--- a/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef
+++ b/java/perftests/etc/chartdefs/1303-QueueConsumersWithOverlappingSelectors-Persistent.chartdef
@@ -19,7 +19,7 @@
chartType=XYLINE
chartTitle=Impact of 50%-overlapping selectors in queue consumers with persistent messages
-chartDescription=Impact of 50%-overlapping selectors in queue consumers with persistent messages, auto-ack, message payload of 1KB, 1 producer, varying number of consumers from 2 to 32.
+chartDescription=Impact of 50%-overlapping selectors in queue consumers with persistent messages, auto-ack, message payload of 1KB, 1 producer, varying number of consumers from 2 to 32, single queue.
chartSubtitle=Persistent 1KB messages
xAxisTitle=Consumers
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef
index ef82fdf45f..96f0ce3284 100644
--- a/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef
+++ b/java/perftests/etc/chartdefs/1500-Topic-NumberOfConsumers.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Number of topic consumers
chartSubtitle=Transient 1KB messages
-chartDescription=1P 1-100C transient, transacted, with message payload 1KB.
+chartDescription=1P 1-100C transient, transacted, with message payload 1KB, single queue.
xAxisTitle=Numer of consumers
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef
index 394b23227c..5eac3d90c9 100644
--- a/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef
+++ b/java/perftests/etc/chartdefs/1501-Topic-NumberOfTopics.chartdef
@@ -20,7 +20,7 @@
chartType=XYLINE
chartTitle=Number of topics
chartSubtitle=Transient 1KB messages
-chartDescription=1,10,50,100 PC, transient, transacted, with each PC pair having own topic, message payload 1KB.
+chartDescription=1,10,50,100 PC, transient, transacted, with each PC pair having own topic, message payload 1KB, single topic.
xAxisTitle=Numer of topics
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef
index c418709a82..25e64ea1c9 100644
--- a/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef
+++ b/java/perftests/etc/chartdefs/1502-Topic-Persistence.chartdef
@@ -20,7 +20,7 @@
chartType=BAR
chartTitle=Topic transient/durable subscriptions
chartSubtitle=1KB messages
-chartDescription=1P 10C, transacted, message payload 1KB, transient messages on non-durable sub, persistent messages on durable sub
+chartDescription=1P 10C, transacted, message payload 1KB, transient messages on non-durable sub, persistent messages on durable sub, single topic,
xAxisTitle=Subscription type (true durable, false non durable)
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef
index f25dd89a2b..8d549abcc9 100644
--- a/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef
+++ b/java/perftests/etc/chartdefs/1503-Topic-AckModes.chartdef
@@ -20,7 +20,7 @@
chartType=BAR
chartTitle=Topic acknowledge modes
chartSubtitle=Transient 1KB messages
-chartDescription=1P 10C, transient, non-durable subscription, message payload 1KB
+chartDescription=1P 10C, transient, non-durable subscription, message payload 1KB, single topic.
xAxisTitle=Ack Mode (0=transaction 1=auto-ack)
yAxisTitle=Throughput (messages/s)
diff --git a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef
index 6b7939157a..bd252d1b6e 100644
--- a/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef
+++ b/java/perftests/etc/chartdefs/2001-Latency-MessageSize-Transient.chartdef
@@ -20,7 +20,7 @@
chartType=STATISTICAL_BAR
chartTitle=Impact of message size on latency
chartSubtitle=Transient messages
-chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, transient, auto-ack, with message payload between 256-262144 bytes, single queue.
xAxisTitle=Message Size (B)
yAxisTitle=Latency (millis)
diff --git a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef
index c04e393046..36acdb6cd7 100644
--- a/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef
+++ b/java/perftests/etc/chartdefs/2002-Latency-MessageSize-Persistent.chartdef
@@ -20,7 +20,7 @@
chartType=STATISTICAL_BAR
chartTitle=Impact of message size on latency
chartSubtitle=Persistent messages
-chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes.
+chartDescription=1P 1C, persistent, auto-ack, with message payload between 256-262144 bytes, single queue.
xAxisTitle=Message Size (B)
yAxisTitle=Latency (millis)
diff --git a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef
index fa688feb1f..bb19eb2aca 100644
--- a/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef
+++ b/java/perftests/etc/chartdefs/2031-Latency-VaryingNumberOfParticipants.chartdef
@@ -20,7 +20,7 @@
chartType=STATISTICAL_BAR
chartTitle=Latency, varying number of participants
chartSubtitle=Persistent 1KB messages
-chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB.
+chartDescription=1,2,5,10 P/Cs, persistent, auto-ack, with message payload 1KB, single queue.
xAxisTitle=Consumers
yAxisTitle=Latency (millis)
diff --git a/java/perftests/etc/testdefs/Latency-MessageSize.json b/java/perftests/etc/testdefs/Latency-MessageSize.json
index 4486d7a4b5..f93d1ecaab 100644
--- a/java/perftests/etc/testdefs/Latency-MessageSize.json
+++ b/java/perftests/etc/testdefs/Latency-MessageSize.json
@@ -136,7 +136,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer1",
@@ -160,7 +160,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer1",
diff --git a/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json b/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json
index aefd51dde0..50f00a8c45 100644
--- a/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json
+++ b/java/perftests/etc/testdefs/Latency-VaryingNumberOfParticipants.json
@@ -18,7 +18,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer1",
@@ -43,7 +43,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer1",
@@ -79,7 +79,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer1",
@@ -99,7 +99,7 @@
"_sessions": [
{
"_sessionName": "session2",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer2",
@@ -119,7 +119,7 @@
"_sessions": [
{
"_sessionName": "session3",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer3",
@@ -139,7 +139,7 @@
"_sessions": [
{
"_sessionName": "session4",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer4",
@@ -159,7 +159,7 @@
"_sessions": [
{
"_sessionName": "session5",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer5",
@@ -179,7 +179,7 @@
"_sessions": [
{
"_sessionName": "session6",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer6",
@@ -199,7 +199,7 @@
"_sessions": [
{
"_sessionName": "session7",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer7",
@@ -219,7 +219,7 @@
"_sessions": [
{
"_sessionName": "session8",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer8",
@@ -239,7 +239,7 @@
"_sessions": [
{
"_sessionName": "session9",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer9",
@@ -259,7 +259,7 @@
"_sessions": [
{
"_sessionName": "session10",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer10",
@@ -284,7 +284,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer1",
@@ -319,7 +319,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer1",
@@ -339,7 +339,7 @@
"_sessions": [
{
"_sessionName": "session2",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer2",
@@ -359,7 +359,7 @@
"_sessions": [
{
"_sessionName": "session3",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer3",
@@ -379,7 +379,7 @@
"_sessions": [
{
"_sessionName": "session4",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer4",
@@ -399,7 +399,7 @@
"_sessions": [
{
"_sessionName": "session5",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer5",
@@ -419,7 +419,7 @@
"_sessions": [
{
"_sessionName": "session6",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer6",
@@ -439,7 +439,7 @@
"_sessions": [
{
"_sessionName": "session7",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer7",
@@ -459,7 +459,7 @@
"_sessions": [
{
"_sessionName": "session8",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer8",
@@ -479,7 +479,7 @@
"_sessions": [
{
"_sessionName": "session9",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer9",
@@ -499,7 +499,7 @@
"_sessions": [
{
"_sessionName": "session10",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer10",
@@ -524,7 +524,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer1",
@@ -542,7 +542,7 @@
"_sessions": [
{
"_sessionName": "session2",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer2",
@@ -560,7 +560,7 @@
"_sessions": [
{
"_sessionName": "session3",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer3",
@@ -578,7 +578,7 @@
"_sessions": [
{
"_sessionName": "session4",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer4",
@@ -596,7 +596,7 @@
"_sessions": [
{
"_sessionName": "session5",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer5",
@@ -614,7 +614,7 @@
"_sessions": [
{
"_sessionName": "session6",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer6",
@@ -632,7 +632,7 @@
"_sessions": [
{
"_sessionName": "session7",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer7",
@@ -650,7 +650,7 @@
"_sessions": [
{
"_sessionName": "session8",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer8",
@@ -668,7 +668,7 @@
"_sessions": [
{
"_sessionName": "session9",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer9",
@@ -686,7 +686,7 @@
"_sessions": [
{
"_sessionName": "session10",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer10",
diff --git a/java/perftests/etc/testdefs/MessageSize.json b/java/perftests/etc/testdefs/MessageSize.json
index 6d796bd824..c97815507b 100644
--- a/java/perftests/etc/testdefs/MessageSize.json
+++ b/java/perftests/etc/testdefs/MessageSize.json
@@ -153,7 +153,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_producers": [
{
"_name": "Producer1",
@@ -177,7 +177,7 @@
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": 0,
"_consumers": [
{
"_name": "Consumer1",
diff --git a/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js b/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js
index 0dd45b0392..72b77e0e93 100644
--- a/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js
+++ b/java/perftests/etc/testdefs/QueueConsumersWithNonOverlappingSelectors.js
@@ -25,11 +25,11 @@ var jsonObject = {
for (var i=0; i<2; i++)
{
var deliveryMode = i+1;
+ var acknowledgeMode = ((i==0) ? 1 : 0);
var durable = (deliveryMode == 2);
var suffix = durable ? "PERSISTENT" : "NON-PERSISTENT";
var queueName = "direct://amq.direct//queue-selectors-" + suffix + "?durable='" + durable + "'";
var consumerNumbers = [1, 2, 4, 8, 16, 32];
- var consumerAcknowledgeMode = 1;
for (var j=0; j<consumerNumbers.length; j++)
{
var consumerNumber = consumerNumbers[j];
@@ -70,7 +70,7 @@ for (var i=0; i<2; i++)
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": acknowledgeMode,
"_producers": [
{
"_name": "Producer1",
@@ -100,7 +100,7 @@ for (var i=0; i<2; i++)
"_sessions": [
{
"_sessionName": "session" + n,
- "_acknowledgeMode": consumerAcknowledgeMode,
+ "_acknowledgeMode": acknowledgeMode,
"_consumers": [
{
"_name": "Consumer" + n,
diff --git a/java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js b/java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js
index 20cfb4ad45..e4c076b9f4 100644
--- a/java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js
+++ b/java/perftests/etc/testdefs/QueueConsumersWithOverlappingSelectors.js
@@ -26,6 +26,7 @@ for (var i=0; i<2; i++)
{
var deliveryMode = i+1;
var durable = (deliveryMode == 2);
+ var acknowledgeMode = ((i==0) ? 1 : 0);
var suffix = durable ? "PERSISTENT" : "NON-PERSISTENT";
var queueName = "direct://amq.direct//queue-selectors-overlapping-" + suffix + "?durable='" + durable + "'";
var consumerNumbers = [2, 4, 8, 16, 32];
@@ -70,7 +71,7 @@ for (var i=0; i<2; i++)
"_sessions": [
{
"_sessionName": "session1",
- "_acknowledgeMode": 1,
+ "_acknowledgeMode": acknowledgeMode,
"_producers": [
{
"_name": "Producer1",
@@ -111,7 +112,7 @@ for (var i=0; i<2; i++)
"_sessions": [
{
"_sessionName": "session" + n,
- "_acknowledgeMode": consumerAcknowledgeMode,
+ "_acknowledgeMode": acknowledgeMode,
"_consumers": [
{
"_name": "Consumer" + n,
diff --git a/java/perftests/pom.xml b/java/perftests/pom.xml
index c395069e84..7787c82b74 100644
--- a/java/perftests/pom.xml
+++ b/java/perftests/pom.xml
@@ -156,6 +156,48 @@
<skip>true</skip>
</configuration>
</plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.3.2</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>java</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <mainClass>org.apache.qpid.disttest.ControllerRunner</mainClass>
+ <includePluginDependencies>true</includePluginDependencies>
+ <arguments>
+ <argument>jndi-config=${basedir}/etc/perftests-jndi.properties</argument>
+ <argument>test-config=${basedir}/etc/testdefs</argument>
+ <argument>distributed=false</argument>
+ <argument>writeToDb=false</argument>
+ </arguments>
+ <systemProperties>
+ <systemProperty>
+ <key>qpid.amqp</key><value>0-91</value>
+ </systemProperty>
+ <systemProperty>
+ <key>qpid.dest_syntax</key><value>BURL</value>
+ </systemProperty>
+ <systemProperty>
+ <key>qpid.disttest.duration</key><value>5000</value>
+ </systemProperty>
+ </systemProperties>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ <version>${geronimo-jms-1-1-version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+
</plugins>
</build>
diff --git a/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java b/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java
index 26bbe151d2..00231039c3 100644
--- a/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java
+++ b/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/TestFileUtils.java
@@ -121,33 +121,38 @@ public class TestFileUtils
File file = createTempFile(testcase, suffix);
if (content != null)
{
- FileOutputStream fos = null;
- try
- {
- fos = new FileOutputStream(file);
- fos.write(content.getBytes("UTF-8"));
- fos.flush();
- }
- catch (Exception e)
- {
- throw new RuntimeException("Cannot add the content into temp file " + file.getAbsolutePath(), e);
- }
- finally
+ saveTextContentInFile(content, file);
+ }
+ return file;
+ }
+
+ public static void saveTextContentInFile(String content, File file)
+ {
+ FileOutputStream fos = null;
+ try
+ {
+ fos = new FileOutputStream(file);
+ fos.write(content.getBytes("UTF-8"));
+ fos.flush();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Cannot add the content into temp file " + file.getAbsolutePath(), e);
+ }
+ finally
+ {
+ if (fos != null)
{
- if (fos != null)
+ try
{
- try
- {
- fos.close();
- }
- catch (IOException e)
- {
- throw new RuntimeException("Cannot close output stream into temp file " + file.getAbsolutePath(), e);
- }
+ fos.close();
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Cannot close output stream into temp file " + file.getAbsolutePath(), e);
}
}
}
- return file;
}
/**
diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
index 70e1b27fba..c7bcdd2edb 100644
--- a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
+++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java
@@ -49,6 +49,7 @@ import org.apache.qpid.server.model.AccessControlProvider;
import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.BrokerShutdownProvider;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.GroupProvider;
import org.apache.qpid.server.model.JsonSystemConfigImpl;
@@ -105,7 +106,8 @@ public class TestBrokerConfiguration
final AbstractSystemConfig parentObject = new JsonSystemConfigImpl(taskExecutor,
mock(EventLogger.class),
mock(LogRecorder.class),
- brokerOptions);
+ brokerOptions,
+ mock(BrokerShutdownProvider.class));
ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(BrokerModel.getInstance());
@@ -215,7 +217,8 @@ public class TestBrokerConfiguration
final SystemConfig parentObject = configFactory.newInstance(_taskExecutor,
mock(EventLogger.class),
mock(LogRecorder.class),
- brokerOptions);
+ brokerOptions,
+ mock(BrokerShutdownProvider.class));
parentObject.open();
DurableConfigurationStore configurationStore = parentObject.getConfigurationStore();
diff --git a/java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java b/java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java
index 8b86163aa6..538bd3b32a 100644
--- a/java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java
+++ b/java/systests/src/test/java/org/apache/qpid/systest/rest/PortRestTest.java
@@ -358,9 +358,9 @@ public class PortRestTest extends QpidRestTestCase
attributes.put(Port.AUTHENTICATION_PROVIDER, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER);
int responseCode = getRestTestHelper().submitRequest("port/" + newPortName, "PUT", attributes);
- assertEquals("Unexpected response code for port creation", 201, responseCode);
+ assertEquals("Unexpected response code for port creation", 409, responseCode);
- portData = getRestTestHelper().getJsonAsSingletonList("port/" + URLDecoder.decode(newPortName, "UTF-8"));
- Asserts.assertPortAttributes(portData, State.ERRORED);
+ List<Map<String,Object>> ports = getRestTestHelper().getJsonAsList("port/" + URLDecoder.decode(newPortName, "UTF-8"));
+ assertTrue("Port should not be created", ports.isEmpty());
}
}