summaryrefslogtreecommitdiff
path: root/qpid/java
diff options
context:
space:
mode:
authorKeith Wall <kwall@apache.org>2014-03-25 17:54:10 +0000
committerKeith Wall <kwall@apache.org>2014-03-25 17:54:10 +0000
commitcd6130384dc5f27ad494eabf8a2b15ca79280aa1 (patch)
tree77d7b1f0ced2cea6b031327fcb5c8143d763cf9d /qpid/java
parentfcc3f654b60b7dd2180afe73e8809545725b41af (diff)
parent809061e0024b74f89afdeff8ba83d6514589f417 (diff)
downloadqpid-python-cd6130384dc5f27ad494eabf8a2b15ca79280aa1.tar.gz
NO-JIRA: Merge changes from trunk.
Command was: svn merge https://svn.apache.org/repos/asf/qpid/trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-broker-bdb-ha2@1581428 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java')
-rw-r--r--qpid/java/bdbstore/pom.xml14
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfiguredObjectRecord.java107
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java4
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java318
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/HierarchyKey.java79
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java5
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/HierarchyKeyBinding.java59
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java4
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java3
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java5
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java4
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java160
-rw-r--r--qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java10
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java3
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java11
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java4
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java22
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java2
-rw-r--r--qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java4
-rw-r--r--qpid/java/bdbstore/systests/pom.xml61
-rw-r--r--qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java3
-rwxr-xr-xqpid/java/broker-core/src/main/java/broker.bnd2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java19
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java22
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java94
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java7
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java11
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java64
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java13
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java366
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java64
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java36
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java8
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java696
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerFactory.java74
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSHA1SaslServer.java273
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java15
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java614
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java5
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java63
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java104
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java34
-rwxr-xr-xqpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java34
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java38
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreUpgrader.java3
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java3
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java170
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java6
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NonNullUpgrader.java12
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java28
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java10
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java21
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java93
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java7
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java8
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java4
-rw-r--r--qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory2
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java5
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java571
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerTest.java203
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java122
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java128
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java6
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java5
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java93
-rw-r--r--qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java16
-rw-r--r--qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java105
-rw-r--r--qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java2
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java5
-rw-r--r--qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java3
-rw-r--r--qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html2
-rw-r--r--qpid/java/broker-plugins/management-http/pom.xml6
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java4
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java6
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java12
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js221
-rw-r--r--qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js2
-rw-r--r--qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java25
-rw-r--r--qpid/java/build.deps4
-rwxr-xr-xqpid/java/client/src/main/java/client.bnd2
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties2
-rw-r--r--qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties1
-rw-r--r--qpid/java/common.xml4
-rwxr-xr-xqpid/java/common/src/main/java/common.bnd2
-rw-r--r--qpid/java/ivy.retrieve.xml1
-rw-r--r--qpid/java/management/common/src/main/java/management-common.bnd2
-rw-r--r--qpid/java/maven/qpid-enforcer-plugin-rules/pom.xml93
-rw-r--r--qpid/java/maven/qpid-enforcer-plugin-rules/src/main/java/org/apache/qpid/maven/enforcer/rule/RequireFileContentsAreEquivalent.java104
-rw-r--r--qpid/java/maven/qpid-enforcer-plugin-rules/src/test/java/org/apache/qpid/maven/enforcer/rule/TestRequireFileContentsAreEquivalent.java149
-rw-r--r--qpid/java/pom.xml111
-rw-r--r--qpid/java/qpid-perftests-systests/pom.xml14
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java38
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java53
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java78
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java214
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java6
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java34
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java12
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java3
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java2
-rw-r--r--qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java9
110 files changed, 4916 insertions, 1492 deletions
diff --git a/qpid/java/bdbstore/pom.xml b/qpid/java/bdbstore/pom.xml
index d7d12f0b33..5d34559a46 100644
--- a/qpid/java/bdbstore/pom.xml
+++ b/qpid/java/bdbstore/pom.xml
@@ -102,6 +102,20 @@
</includes>
</resource>
</resources>
+
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>test-jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
</build>
</project>
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfiguredObjectRecord.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfiguredObjectRecord.java
new file mode 100644
index 0000000000..f13e4dd08b
--- /dev/null
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBConfiguredObjectRecord.java
@@ -0,0 +1,107 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb;
+
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class BDBConfiguredObjectRecord implements ConfiguredObjectRecord
+{
+ private final UUID _id;
+ private final String _type;
+ private final Map<String,Object> _attributes;
+ private Map<String, ConfiguredObjectRecord> _parents = new HashMap<String, ConfiguredObjectRecord>();
+
+ public BDBConfiguredObjectRecord(final UUID id, final String type, final Map<String, Object> attributes)
+ {
+ _id = id;
+ _type = type;
+ _attributes = Collections.unmodifiableMap(attributes);
+ }
+
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ public String getType()
+ {
+ return _type;
+ }
+
+ public Map<String, Object> getAttributes()
+ {
+ return _attributes;
+ }
+
+ void addParent(String parentType, ConfiguredObjectRecord parent)
+ {
+ _parents.put(parentType, parent);
+ }
+
+ @Override
+ public Map<String, ConfiguredObjectRecord> getParents()
+ {
+ return Collections.unmodifiableMap(_parents);
+ }
+
+ @Override
+ public boolean equals(final Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ final BDBConfiguredObjectRecord that = (BDBConfiguredObjectRecord) o;
+
+ if (_attributes != null ? !_attributes.equals(that._attributes) : that._attributes != null)
+ {
+ return false;
+ }
+ if (_id != null ? !_id.equals(that._id) : that._id != null)
+ {
+ return false;
+ }
+ if (_type != null ? !_type.equals(that._type) : that._type != null)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = _id != null ? _id.hashCode() : 0;
+ result = 31 * result + (_type != null ? _type.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java
index 7e42d09ba6..492ec9d7bf 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java
@@ -242,10 +242,10 @@ public class BDBHAVirtualHost extends AbstractVirtualHost
DurableConfigurationRecoverer configRecoverer =
new DurableConfigurationRecoverer(getName(), getDurableConfigurationRecoverers(),
new DefaultUpgraderProvider(BDBHAVirtualHost.this, getExchangeRegistry()), getEventLogger());
- _messageStore.recoverConfigurationStore(configRecoverer);
+ _messageStore.recoverConfigurationStore(getModel(), configRecoverer);
VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(BDBHAVirtualHost.this);
- _messageStore.recoverMessageStore(recoveryHandler, recoveryHandler);
+ _messageStore.recoverMessageStore(getModel(), recoveryHandler, recoveryHandler);
}
catch (Exception e)
{
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
index 2022f36bd9..ec6ae23367 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java
@@ -25,6 +25,8 @@ import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -34,6 +36,7 @@ import java.util.concurrent.atomic.AtomicLong;
import org.apache.log4j.Logger;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
@@ -54,11 +57,13 @@ import org.apache.qpid.server.store.StoredMessage;
import org.apache.qpid.server.store.TransactionLogRecoveryHandler;
import org.apache.qpid.server.store.TransactionLogRecoveryHandler.QueueEntryRecoveryHandler;
import org.apache.qpid.server.store.TransactionLogResource;
+import org.apache.qpid.server.store.berkeleydb.entry.HierarchyKey;
import org.apache.qpid.server.store.berkeleydb.entry.PreparedTransaction;
import org.apache.qpid.server.store.berkeleydb.entry.QueueEntryKey;
import org.apache.qpid.server.store.berkeleydb.entry.Xid;
import org.apache.qpid.server.store.berkeleydb.tuple.ConfiguredObjectBinding;
import org.apache.qpid.server.store.berkeleydb.tuple.ContentBinding;
+import org.apache.qpid.server.store.berkeleydb.tuple.HierarchyKeyBinding;
import org.apache.qpid.server.store.berkeleydb.tuple.MessageMetaDataBinding;
import org.apache.qpid.server.store.berkeleydb.tuple.PreparedTransactionBinding;
import org.apache.qpid.server.store.berkeleydb.tuple.QueueEntryBinding;
@@ -94,9 +99,11 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
{
private static final Logger LOGGER = Logger.getLogger(BDBMessageStore.class);
- public static final int VERSION = 7;
+ public static final int VERSION = 8;
private static final int LOCK_RETRY_ATTEMPTS = 5;
private static String CONFIGURED_OBJECTS_DB_NAME = "CONFIGURED_OBJECTS";
+ private static String CONFIGURED_OBJECT_HIERARCHY_DB_NAME = "CONFIGURED_OBJECT_HIERARCHY";
+
private static String MESSAGE_META_DATA_DB_NAME = "MESSAGE_METADATA";
private static String MESSAGE_CONTENT_DB_NAME = "MESSAGE_CONTENT";
private static String DELIVERY_DB_NAME = "QUEUE_ENTRIES";
@@ -106,7 +113,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
private static String LINKDB_NAME = "LINKS";
private static String XID_DB_NAME = "XIDS";
private static String CONFIG_VERSION_DB_NAME = "CONFIG_VERSION";
- private static final String[] CONFIGURATION_STORE_DATABASE_NAMES = new String[] { CONFIGURED_OBJECTS_DB_NAME, CONFIG_VERSION_DB_NAME };
+ private static final String[] CONFIGURATION_STORE_DATABASE_NAMES = new String[] { CONFIGURED_OBJECTS_DB_NAME, CONFIG_VERSION_DB_NAME , CONFIGURED_OBJECT_HIERARCHY_DB_NAME};
private static final String[] MESSAGE_STORE_DATABASE_NAMES = new String[] { MESSAGE_META_DATA_DB_NAME, MESSAGE_CONTENT_DB_NAME, DELIVERY_DB_NAME, BRIDGEDB_NAME, LINKDB_NAME, XID_DB_NAME };
private EnvironmentFacade _environmentFacade;
@@ -163,7 +170,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
@Override
- public void recoverConfigurationStore(ConfigurationRecoveryHandler recoveryHandler)
+ public void recoverConfigurationStore(ConfiguredObject<?> parent, ConfigurationRecoveryHandler recoveryHandler)
{
_configurationStoreStateManager.attainState(State.ACTIVATING);
@@ -172,7 +179,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
dbConfig.setAllowCreate(true);
try
{
- new Upgrader(_environmentFacade.getEnvironment(), _virtualHostName).upgradeIfNecessary();
+ new Upgrader(_environmentFacade.getEnvironment(), parent).upgradeIfNecessary();
_environmentFacade.openDatabases(dbConfig, CONFIGURATION_STORE_DATABASE_NAMES);
}
catch(DatabaseException e)
@@ -216,7 +223,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
@Override
- public synchronized void recoverMessageStore(MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler) throws StoreException
+ public synchronized void recoverMessageStore(ConfiguredObject<?> parent, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler) throws StoreException
{
_messageStoreStateManager.attainState(State.ACTIVATING);
DatabaseConfig dbConfig = new DatabaseConfig();
@@ -224,13 +231,13 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
dbConfig.setAllowCreate(true);
try
{
- new Upgrader(_environmentFacade.getEnvironment(), _virtualHostName).upgradeIfNecessary();
+ new Upgrader(_environmentFacade.getEnvironment(), parent).upgradeIfNecessary();
_environmentFacade.openDatabases(dbConfig, MESSAGE_STORE_DATABASE_NAMES);
_totalStoreSize = getSizeOnDisk();
}
catch(DatabaseException e)
{
- throw _environmentFacade.handleDatabaseException("Cannot activate message store", e);
+ throw _environmentFacade.handleDatabaseException("Cannot upgrade message store or open datatbases", e);
}
if(messageRecoveryHandler != null)
@@ -352,10 +359,11 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
@SuppressWarnings("resource")
private void updateConfigVersion(int newConfigVersion) throws StoreException
{
+ Transaction txn = null;
Cursor cursor = null;
try
{
- Transaction txn = _environmentFacade.getEnvironment().beginTransaction(null, null);
+ txn = _environmentFacade.getEnvironment().beginTransaction(null, null);
cursor = getConfigVersionDb().openCursor(txn, null);
DatabaseEntry key = new DatabaseEntry();
ByteBinding.byteToEntry((byte) 0,key);
@@ -373,10 +381,12 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
cursor.close();
cursor = null;
txn.commit();
+ txn = null;
}
finally
{
closeCursorSafely(cursor);
+ abortTransactionIgnoringException("Error setting config version", txn);;
}
}
@@ -412,24 +422,57 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
private void loadConfiguredObjects(ConfigurationRecoveryHandler crh) throws DatabaseException, StoreException
{
- Cursor cursor = null;
+ Cursor objectsCursor = null;
+ Cursor hierarchyCursor = null;
try
{
- cursor = getConfiguredObjectsDb().openCursor(null, null);
+ objectsCursor = getConfiguredObjectsDb().openCursor(null, null);
DatabaseEntry key = new DatabaseEntry();
DatabaseEntry value = new DatabaseEntry();
- while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
+
+ Map<UUID, BDBConfiguredObjectRecord> configuredObjects =
+ new HashMap<UUID, BDBConfiguredObjectRecord>();
+
+ while (objectsCursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
{
UUID id = UUIDTupleBinding.getInstance().entryToObject(key);
- ConfiguredObjectRecord configuredObject = new ConfiguredObjectBinding(id).entryToObject(value);
- crh.configuredObject(configuredObject.getId(),configuredObject.getType(),configuredObject.getAttributes());
+ BDBConfiguredObjectRecord configuredObject =
+ (BDBConfiguredObjectRecord) new ConfiguredObjectBinding(id).entryToObject(value);
+ configuredObjects.put(configuredObject.getId(), configuredObject);
+ }
+
+ // set parents
+ hierarchyCursor = getConfiguredObjectHierarchyDb().openCursor(null, null);
+ while (hierarchyCursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
+ {
+ HierarchyKey hk = HierarchyKeyBinding.getInstance().entryToObject(key);
+ UUID parentId = UUIDTupleBinding.getInstance().entryToObject(value);
+ BDBConfiguredObjectRecord child = configuredObjects.get(hk.getChildId());
+ if(child != null)
+ {
+ ConfiguredObjectRecord parent = configuredObjects.get(parentId);
+ if(parent != null)
+ {
+ child.addParent(hk.getParentType(), parent);
+ }
+ else if(hk.getParentType().equals("Exchange"))
+ {
+ // TODO - remove this hack for the pre-defined exchanges
+ child.addParent(hk.getParentType(), new BDBConfiguredObjectRecord(parentId, "Exchange", Collections.<String,Object>emptyMap()));
+ }
+ }
}
+ for (ConfiguredObjectRecord record : configuredObjects.values())
+ {
+ crh.configuredObject(record);
+ }
}
finally
{
- closeCursorSafely(cursor);
+ closeCursorSafely(objectsCursor);
+ closeCursorSafely(hierarchyCursor);
}
}
@@ -448,7 +491,6 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
}
-
private void recoverMessages(MessageStoreRecoveryHandler msrh) throws StoreException
{
StoredMessageRecoveryHandler mrh = msrh.begin();
@@ -568,9 +610,8 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
dtxrh.completeDtxRecordRecovery();
}
- public void removeMessage(long messageId, boolean sync) throws StoreException
+ void removeMessage(long messageId, boolean sync) throws StoreException
{
-
boolean complete = false;
com.sleepycat.je.Transaction tx = null;
@@ -715,116 +756,130 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
@Override
- public void create(UUID id, String type, Map<String, Object> attributes) throws StoreException
+ public void create(ConfiguredObjectRecord configuredObject) throws StoreException
{
if (_configurationStoreStateManager.isInState(State.ACTIVE))
{
- ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(id, type, attributes);
- storeConfiguredObjectEntry(configuredObject);
+ com.sleepycat.je.Transaction txn = null;
+ try
+ {
+ txn = _environmentFacade.getEnvironment().beginTransaction(null, null);
+ storeConfiguredObjectEntry(txn, configuredObject);
+ txn.commit();
+ txn = null;
+ }
+ catch (DatabaseException e)
+ {
+ throw _environmentFacade.handleDatabaseException("Error creating configured object " + configuredObject
+ + " in database: " + e.getMessage(), e);
+ }
+ finally
+ {
+ if (txn != null)
+ {
+ abortTransactionIgnoringException("Error creating configured object", txn);
+ }
+ }
}
}
@Override
- public void remove(UUID id, String type) throws StoreException
+ public UUID[] remove(final ConfiguredObjectRecord... objects) throws StoreException
{
- if (LOGGER.isDebugEnabled())
+ com.sleepycat.je.Transaction txn = null;
+ try
{
- LOGGER.debug("public void remove(id = " + id + ", type="+type+"): called");
+ txn = _environmentFacade.getEnvironment().beginTransaction(null, null);
+
+ Collection<UUID> removed = new ArrayList<UUID>(objects.length);
+ for(ConfiguredObjectRecord record : objects)
+ {
+ if(removeConfiguredObject(txn, record) == OperationStatus.SUCCESS)
+ {
+ removed.add(record.getId());
+ }
+ }
+
+ txn.commit();
+ txn = null;
+ return removed.toArray(new UUID[removed.size()]);
}
- OperationStatus status = removeConfiguredObject(null, id);
- if (status == OperationStatus.NOTFOUND)
+ catch (DatabaseException e)
{
- throw new StoreException("Configured object of type " + type + " with id " + id + " not found");
+ throw _environmentFacade.handleDatabaseException("Error deleting configured objects from database", e);
}
- }
-
- @Override
- public UUID[] removeConfiguredObjects(final UUID... objects) throws StoreException
- {
- com.sleepycat.je.Transaction txn = _environmentFacade.getEnvironment().beginTransaction(null, null);
- Collection<UUID> removed = new ArrayList<UUID>(objects.length);
- for(UUID id : objects)
+ finally
{
- if(removeConfiguredObject(txn, id) == OperationStatus.SUCCESS)
+ if (txn != null)
{
- removed.add(id);
+ abortTransactionIgnoringException("Error deleting configured objects", txn);
}
}
- commitTransaction(txn);
- return removed.toArray(new UUID[removed.size()]);
+
}
- private void commitTransaction(com.sleepycat.je.Transaction txn) throws StoreException
+ @Override
+ public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException
{
+ com.sleepycat.je.Transaction txn = null;
try
{
+ txn = _environmentFacade.getEnvironment().beginTransaction(null, null);
+ for(ConfiguredObjectRecord record : records)
+ {
+ update(createIfNecessary, record, txn);
+ }
txn.commit();
+ txn = null;
}
- catch(DatabaseException e)
+ catch (DatabaseException e)
{
- throw _environmentFacade.handleDatabaseException("Cannot commit transaction on configured objects removal", e);
+ throw _environmentFacade.handleDatabaseException("Error updating configuration details within the store: " + e,e);
}
- }
-
- @Override
- public void update(UUID id, String type, Map<String, Object> attributes) throws StoreException
- {
- update(false, id, type, attributes, null);
- }
-
- @Override
- public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException
- {
- com.sleepycat.je.Transaction txn = _environmentFacade.getEnvironment().beginTransaction(null, null);
- for(ConfiguredObjectRecord record : records)
+ finally
{
- update(createIfNecessary, record.getId(), record.getType(), record.getAttributes(), txn);
+ if (txn != null)
+ {
+ abortTransactionIgnoringException("Error updating configuration details within the store", txn);
+ }
}
- commitTransaction(txn);
+
}
- private void update(boolean createIfNecessary, UUID id, String type, Map<String, Object> attributes, com.sleepycat.je.Transaction txn) throws StoreException
+ private void update(boolean createIfNecessary, ConfiguredObjectRecord record, com.sleepycat.je.Transaction txn) throws StoreException
{
if (LOGGER.isDebugEnabled())
{
- LOGGER.debug("Updating " + type + ", id: " + id);
+ LOGGER.debug("Updating " + record.getType() + ", id: " + record.getId());
}
- try
- {
- DatabaseEntry key = new DatabaseEntry();
- UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance();
- keyBinding.objectToEntry(id, key);
+ DatabaseEntry key = new DatabaseEntry();
+ UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance();
+ keyBinding.objectToEntry(record.getId(), key);
- DatabaseEntry value = new DatabaseEntry();
- DatabaseEntry newValue = new DatabaseEntry();
- ConfiguredObjectBinding configuredObjectBinding = ConfiguredObjectBinding.getInstance();
+ DatabaseEntry value = new DatabaseEntry();
+ DatabaseEntry newValue = new DatabaseEntry();
+ ConfiguredObjectBinding configuredObjectBinding = ConfiguredObjectBinding.getInstance();
- OperationStatus status = getConfiguredObjectsDb().get(txn, key, value, LockMode.DEFAULT);
- if (status == OperationStatus.SUCCESS || (createIfNecessary && status == OperationStatus.NOTFOUND))
+ OperationStatus status = getConfiguredObjectsDb().get(txn, key, value, LockMode.DEFAULT);
+ final boolean isNewRecord = status == OperationStatus.NOTFOUND;
+ if (status == OperationStatus.SUCCESS || (createIfNecessary && isNewRecord))
+ {
+ // write the updated entry to the store
+ configuredObjectBinding.objectToEntry(record, newValue);
+ status = getConfiguredObjectsDb().put(txn, key, newValue);
+ if (status != OperationStatus.SUCCESS)
{
- ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(id, type, attributes);
-
- // write the updated entry to the store
- configuredObjectBinding.objectToEntry(newQueueRecord, newValue);
- status = getConfiguredObjectsDb().put(txn, key, newValue);
- if (status != OperationStatus.SUCCESS)
- {
- throw new StoreException("Error updating configuration details within the store: " + status);
- }
+ throw new StoreException("Error updating configuration details within the store: " + status);
}
- else if (status != OperationStatus.NOTFOUND)
+ if(isNewRecord)
{
- throw new StoreException("Error finding configuration details within the store: " + status);
+ writeHierarchyRecords(txn, record);
}
}
- catch (DatabaseException e)
+ else if (status != OperationStatus.NOTFOUND)
{
- if (txn != null)
- {
- abortTransactionIgnoringException("Error updating configuration details within the store: " + e.getMessage(), txn);
- }
- throw _environmentFacade.handleDatabaseException("Error updating configuration details within the store: " + e,e);
+ throw new StoreException("Error finding configuration details within the store: " + status);
}
}
@@ -1018,7 +1073,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
*
* @throws StoreException If the operation fails for any reason.
*/
- public void abortTran(final com.sleepycat.je.Transaction tx) throws StoreException
+ private void abortTran(final com.sleepycat.je.Transaction tx) throws StoreException
{
if (LOGGER.isDebugEnabled())
{
@@ -1091,7 +1146,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
*
* @return A fresh message id.
*/
- public long getNewMessageId()
+ private long getNewMessageId()
{
return _messageId.incrementAndGet();
}
@@ -1106,7 +1161,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
*
* @throws StoreException If the operation fails for any reason, or if the specified message does not exist.
*/
- protected void addContent(final com.sleepycat.je.Transaction tx, long messageId, int offset,
+ private void addContent(final com.sleepycat.je.Transaction tx, long messageId, int offset,
ByteBuffer contentBody) throws StoreException
{
DatabaseEntry key = new DatabaseEntry();
@@ -1183,7 +1238,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
*
* @throws StoreException If the operation fails for any reason, or if the specified message does not exist.
*/
- public StorableMessageMetaData getMessageMetaData(long messageId) throws StoreException
+ StorableMessageMetaData getMessageMetaData(long messageId) throws StoreException
{
if (LOGGER.isDebugEnabled())
{
@@ -1226,7 +1281,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
*
* @throws StoreException If the operation fails for any reason, or if the specified message does not exist.
*/
- public int getContent(long messageId, int offset, ByteBuffer dst) throws StoreException
+ int getContent(long messageId, int offset, ByteBuffer dst) throws StoreException
{
DatabaseEntry contentKeyEntry = new DatabaseEntry();
LongBinding.longToEntry(messageId, contentKeyEntry);
@@ -1291,20 +1346,17 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
}
- /**
- * Makes the specified configured object persistent.
- *
- * @param configuredObject Details of the configured object to store.
- * @throws StoreException If the operation fails for any reason.
- */
- private void storeConfiguredObjectEntry(ConfiguredObjectRecord configuredObject) throws StoreException
+ private void storeConfiguredObjectEntry(final Transaction txn, ConfiguredObjectRecord configuredObject) throws StoreException
{
if (_configurationStoreStateManager.isInState(State.ACTIVE))
{
- LOGGER.debug("Storing configured object: " + configuredObject);
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Storing configured object: " + configuredObject);
+ }
DatabaseEntry key = new DatabaseEntry();
- UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance();
- keyBinding.objectToEntry(configuredObject.getId(), key);
+ UUIDTupleBinding uuidBinding = UUIDTupleBinding.getInstance();
+ uuidBinding.objectToEntry(configuredObject.getId(), key);
DatabaseEntry value = new DatabaseEntry();
ConfiguredObjectBinding queueBinding = ConfiguredObjectBinding.getInstance();
@@ -1312,12 +1364,13 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
queueBinding.objectToEntry(configuredObject, value);
try
{
- OperationStatus status = getConfiguredObjectsDb().put(null, key, value);
+ OperationStatus status = getConfiguredObjectsDb().put(txn, key, value);
if (status != OperationStatus.SUCCESS)
{
throw new StoreException("Error writing configured object " + configuredObject + " to database: "
+ status);
}
+ writeHierarchyRecords(txn, configuredObject);
}
catch (DatabaseException e)
{
@@ -1326,26 +1379,54 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
}
}
}
-
- private OperationStatus removeConfiguredObject(Transaction tx, UUID id) throws StoreException
+
+ private void writeHierarchyRecords(final Transaction txn, final ConfiguredObjectRecord configuredObject)
{
+ OperationStatus status;
+ HierarchyKeyBinding hierarchyBinding = HierarchyKeyBinding.getInstance();
+ DatabaseEntry hierarchyKey = new DatabaseEntry();
+ DatabaseEntry hierarchyValue = new DatabaseEntry();
- LOGGER.debug("Removing configured object: " + id);
+ for(Map.Entry<String, ConfiguredObjectRecord> parent : configuredObject.getParents().entrySet())
+ {
+
+ hierarchyBinding.objectToEntry(new HierarchyKey(configuredObject.getId(), parent.getKey()), hierarchyKey);
+ UUIDTupleBinding.getInstance().objectToEntry(parent.getValue().getId(), hierarchyValue);
+ status = getConfiguredObjectHierarchyDb().put(txn, hierarchyKey, hierarchyValue);
+ if (status != OperationStatus.SUCCESS)
+ {
+ throw new StoreException("Error writing configured object " + configuredObject + " parent record to database: "
+ + status);
+ }
+ }
+ }
+
+ private OperationStatus removeConfiguredObject(Transaction tx, ConfiguredObjectRecord record) throws StoreException
+ {
+ UUID id = record.getId();
+ Map<String, ConfiguredObjectRecord> parents = record.getParents();
+
+ if (LOGGER.isDebugEnabled())
+ {
+ LOGGER.debug("Removing configured object: " + id);
+ }
DatabaseEntry key = new DatabaseEntry();
UUIDTupleBinding uuidBinding = UUIDTupleBinding.getInstance();
uuidBinding.objectToEntry(id, key);
- try
- {
- return getConfiguredObjectsDb().delete(tx, key);
- }
- catch (DatabaseException e)
+ OperationStatus status = getConfiguredObjectsDb().delete(tx, key);
+ if(status == OperationStatus.SUCCESS)
{
- throw _environmentFacade.handleDatabaseException("Error deleting of configured object with id " + id + " from database", e);
+ for(String parentType : parents.keySet())
+ {
+ DatabaseEntry hierarchyKey = new DatabaseEntry();
+ HierarchyKeyBinding keyBinding = HierarchyKeyBinding.getInstance();
+ keyBinding.objectToEntry(new HierarchyKey(record.getId(), parentType), hierarchyKey);
+ getConfiguredObjectHierarchyDb().delete(tx, hierarchyKey);
+ }
}
+ return status;
}
-
-
private class StoredBDBMessage implements StoredMessage<StorableMessageMetaData>
{
@@ -1687,14 +1768,19 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore
return _type;
}
- private Database getMessageContentDb()
+ private Database getConfiguredObjectsDb()
{
- return _environmentFacade.getOpenDatabase(MESSAGE_CONTENT_DB_NAME);
+ return _environmentFacade.getOpenDatabase(CONFIGURED_OBJECTS_DB_NAME);
}
- private Database getConfiguredObjectsDb()
+ private Database getConfiguredObjectHierarchyDb()
{
- return _environmentFacade.getOpenDatabase(CONFIGURED_OBJECTS_DB_NAME);
+ return _environmentFacade.getOpenDatabase(CONFIGURED_OBJECT_HIERARCHY_DB_NAME);
+ }
+
+ private Database getMessageContentDb()
+ {
+ return _environmentFacade.getOpenDatabase(MESSAGE_CONTENT_DB_NAME);
}
private Database getConfigVersionDb()
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/HierarchyKey.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/HierarchyKey.java
new file mode 100644
index 0000000000..d1c341447e
--- /dev/null
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/entry/HierarchyKey.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb.entry;
+
+import java.util.UUID;
+
+public class HierarchyKey
+{
+ private final UUID _childId;
+ private final String _parentType;
+
+ public HierarchyKey(final UUID childId, final String parentType)
+ {
+ _childId = childId;
+ _parentType = parentType;
+ }
+
+ public UUID getChildId()
+ {
+ return _childId;
+ }
+
+ public String getParentType()
+ {
+ return _parentType;
+ }
+
+ @Override
+ public boolean equals(final Object o)
+ {
+ if (this == o)
+ {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ final HierarchyKey that = (HierarchyKey) o;
+
+ if (!_childId.equals(that._childId))
+ {
+ return false;
+ }
+ if (!_parentType.equals(that._parentType))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = _childId.hashCode();
+ result = 31 * result + _parentType.hashCode();
+ return result;
+ }
+}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java
index bc3beeb78b..38a2215fe7 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBinding.java
@@ -32,6 +32,7 @@ import com.sleepycat.bind.tuple.TupleBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;
import org.apache.qpid.server.store.StoreException;
+import org.apache.qpid.server.store.berkeleydb.BDBConfiguredObjectRecord;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
@@ -80,7 +81,7 @@ public class ConfiguredObjectBinding extends TupleBinding<ConfiguredObjectRecord
_uuid = uuid;
}
- public ConfiguredObjectRecord entryToObject(TupleInput tupleInput)
+ public BDBConfiguredObjectRecord entryToObject(TupleInput tupleInput)
{
String type = tupleInput.readString();
String json = tupleInput.readString();
@@ -88,7 +89,7 @@ public class ConfiguredObjectBinding extends TupleBinding<ConfiguredObjectRecord
try
{
Map<String,Object> value = mapper.readValue(json, Map.class);
- ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(_uuid, type, value);
+ BDBConfiguredObjectRecord configuredObject = new BDBConfiguredObjectRecord(_uuid, type, value);
return configuredObject;
}
catch (IOException e)
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/HierarchyKeyBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/HierarchyKeyBinding.java
new file mode 100644
index 0000000000..13adaabfc8
--- /dev/null
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/HierarchyKeyBinding.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb.tuple;
+
+import com.sleepycat.bind.tuple.TupleBinding;
+import com.sleepycat.bind.tuple.TupleInput;
+import com.sleepycat.bind.tuple.TupleOutput;
+import org.apache.qpid.server.store.berkeleydb.entry.HierarchyKey;
+import org.apache.qpid.server.store.berkeleydb.entry.QueueEntryKey;
+
+import java.util.UUID;
+
+public class HierarchyKeyBinding extends TupleBinding<HierarchyKey>
+{
+
+ private static final HierarchyKeyBinding INSTANCE = new HierarchyKeyBinding();
+
+ public static HierarchyKeyBinding getInstance()
+ {
+ return INSTANCE;
+ }
+
+ /** private constructor forces getInstance instead */
+ private HierarchyKeyBinding() { }
+
+ public HierarchyKey entryToObject(TupleInput tupleInput)
+ {
+ UUID childId = new UUID(tupleInput.readLong(), tupleInput.readLong());
+ String parentType = tupleInput.readString();
+
+ return new HierarchyKey(childId, parentType);
+ }
+
+ public void objectToEntry(HierarchyKey hk, TupleOutput tupleOutput)
+ {
+ UUID uuid = hk.getChildId();
+ tupleOutput.writeLong(uuid.getMostSignificantBits());
+ tupleOutput.writeLong(uuid.getLeastSignificantBits());
+ tupleOutput.writeString(hk.getParentType());
+ }
+} \ No newline at end of file
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java
index adcaef35ef..0ff90a6d77 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/StoreUpgrade.java
@@ -22,7 +22,9 @@ package org.apache.qpid.server.store.berkeleydb.upgrade;
import com.sleepycat.je.Environment;
+import org.apache.qpid.server.model.ConfiguredObject;
+
public interface StoreUpgrade
{
- void performUpgrade(Environment environment, UpgradeInteractionHandler handler, String virtualHostName);
+ void performUpgrade(Environment environment, UpgradeInteractionHandler handler, ConfiguredObject<?> parent);
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java
index 87f8afde4a..3588b96e88 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java
@@ -39,6 +39,7 @@ import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.protocol.v0_8.MessageMetaData;
import org.apache.qpid.server.store.StoreException;
import org.apache.qpid.server.store.StorableMessageMetaData;
@@ -74,7 +75,7 @@ public class UpgradeFrom4To5 extends AbstractStoreUpgrade
private static final Logger _logger = Logger.getLogger(UpgradeFrom4To5.class);
- public void performUpgrade(final Environment environment, final UpgradeInteractionHandler handler, String virtualHostName)
+ public void performUpgrade(final Environment environment, final UpgradeInteractionHandler handler, ConfiguredObject<?> parent)
{
Transaction transaction = null;
reportStarting(environment, 4);
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
index 46f2afd741..366b6a1c97 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java
@@ -40,6 +40,7 @@ import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Queue;
@@ -118,11 +119,11 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade
* Queue, Exchange, Bindings entries are stored now as configurable objects
* in "CONFIGURED_OBJECTS" table.
*/
- public void performUpgrade(final Environment environment, final UpgradeInteractionHandler handler, String virtualHostName)
+ public void performUpgrade(final Environment environment, final UpgradeInteractionHandler handler, ConfiguredObject<?> parent)
{
reportStarting(environment, 5);
upgradeMessages(environment, handler);
- upgradeConfiguredObjectsAndDependencies(environment, handler, virtualHostName);
+ upgradeConfiguredObjectsAndDependencies(environment, handler, parent.getName());
renameDatabases(environment, null);
reportFinished(environment, 6);
}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java
index ce00fd1a48..9dcd291b9d 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java
@@ -27,6 +27,8 @@ import com.sleepycat.je.DatabaseConfig;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.Environment;
import com.sleepycat.je.OperationStatus;
+
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.store.StoreException;
public class UpgradeFrom6To7 extends AbstractStoreUpgrade
@@ -35,7 +37,7 @@ public class UpgradeFrom6To7 extends AbstractStoreUpgrade
private static final int DEFAULT_CONFIG_VERSION = 0;
@Override
- public void performUpgrade(Environment environment, UpgradeInteractionHandler handler, String virtualHostName)
+ public void performUpgrade(Environment environment, UpgradeInteractionHandler handler, ConfiguredObject<?> parent)
{
reportStarting(environment, 6);
DatabaseConfig dbConfig = new DatabaseConfig();
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java
new file mode 100644
index 0000000000..413acc90c4
--- /dev/null
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java
@@ -0,0 +1,160 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store.berkeleydb.upgrade;
+
+import com.sleepycat.bind.tuple.ByteBinding;
+import com.sleepycat.bind.tuple.IntegerBinding;
+import com.sleepycat.bind.tuple.TupleBinding;
+import com.sleepycat.bind.tuple.TupleInput;
+import com.sleepycat.bind.tuple.TupleOutput;
+import com.sleepycat.je.*;
+
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.server.store.StoreException;
+import org.apache.qpid.server.store.berkeleydb.BDBConfiguredObjectRecord;
+import org.apache.qpid.server.store.berkeleydb.entry.HierarchyKey;
+import org.apache.qpid.server.store.berkeleydb.tuple.ConfiguredObjectBinding;
+import org.apache.qpid.server.store.berkeleydb.tuple.HierarchyKeyBinding;
+import org.apache.qpid.server.store.berkeleydb.tuple.UUIDTupleBinding;
+import org.codehaus.jackson.map.ObjectMapper;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class UpgradeFrom7To8 extends AbstractStoreUpgrade
+{
+
+ @Override
+ public void performUpgrade(Environment environment, UpgradeInteractionHandler handler, ConfiguredObject<?> parent)
+ {
+ reportStarting(environment, 7);
+
+ DatabaseConfig dbConfig = new DatabaseConfig();
+ dbConfig.setTransactional(true);
+ dbConfig.setAllowCreate(true);
+
+ Database hierarchyDb = environment.openDatabase(null, "CONFIGURED_OBJECT_HIERARCHY", dbConfig);
+ Database configuredObjectsDb = environment.openDatabase(null, "CONFIGURED_OBJECTS", dbConfig);
+
+ Cursor objectsCursor = null;
+
+ Transaction txn = environment.beginTransaction(null, null);
+
+ try
+ {
+ objectsCursor = configuredObjectsDb.openCursor(txn, null);
+ DatabaseEntry key = new DatabaseEntry();
+ DatabaseEntry value = new DatabaseEntry();
+
+ Map<UUID, BDBConfiguredObjectRecord> configuredObjects =
+ new HashMap<UUID, BDBConfiguredObjectRecord>();
+
+ while (objectsCursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS)
+ {
+ UUID id = UUIDTupleBinding.getInstance().entryToObject(key);
+ TupleInput input = TupleBinding.entryToInput(value);
+ String type = input.readString();
+
+ if(!type.endsWith("Binding"))
+ {
+ UUIDTupleBinding.getInstance().objectToEntry(parent.getId(),value);
+ TupleOutput tupleOutput = new TupleOutput();
+ tupleOutput.writeLong(id.getMostSignificantBits());
+ tupleOutput.writeLong(id.getLeastSignificantBits());
+ tupleOutput.writeString("VirtualHost");
+ TupleBinding.outputToEntry(tupleOutput, key);
+ hierarchyDb.put(txn, key, value);
+ }
+ else
+ {
+ String json = input.readString();
+ ObjectMapper mapper = new ObjectMapper();
+ try
+ {
+ DatabaseEntry hierarchyKey = new DatabaseEntry();
+ DatabaseEntry hierarchyValue = new DatabaseEntry();
+
+ Map<String,Object> attributes = mapper.readValue(json, Map.class);
+ Object queueIdString = attributes.remove("queue");
+ if(queueIdString instanceof String)
+ {
+ UUID queueId = UUID.fromString(queueIdString.toString());
+ UUIDTupleBinding.getInstance().objectToEntry(queueId,hierarchyValue);
+ TupleOutput tupleOutput = new TupleOutput();
+ tupleOutput.writeLong(id.getMostSignificantBits());
+ tupleOutput.writeLong(id.getLeastSignificantBits());
+ tupleOutput.writeString("Queue");
+ TupleBinding.outputToEntry(tupleOutput, hierarchyKey);
+ hierarchyDb.put(txn, hierarchyKey, hierarchyValue);
+ }
+ Object exchangeIdString = attributes.remove("exchange");
+ if(exchangeIdString instanceof String)
+ {
+ UUID exchangeId = UUID.fromString(exchangeIdString.toString());
+ UUIDTupleBinding.getInstance().objectToEntry(exchangeId,hierarchyValue);
+ TupleOutput tupleOutput = new TupleOutput();
+ tupleOutput.writeLong(id.getMostSignificantBits());
+ tupleOutput.writeLong(id.getLeastSignificantBits());
+ tupleOutput.writeString("Exchange");
+ TupleBinding.outputToEntry(tupleOutput, hierarchyKey);
+ hierarchyDb.put(txn, hierarchyKey, hierarchyValue);
+ }
+ TupleOutput tupleOutput = new TupleOutput();
+ tupleOutput.writeString(type);
+ StringWriter writer = new StringWriter();
+ mapper.writeValue(writer,attributes);
+ tupleOutput.writeString(writer.getBuffer().toString());
+ TupleBinding.outputToEntry(tupleOutput, value);
+ objectsCursor.putCurrent(value);
+ }
+ catch (IOException e)
+ {
+ throw new StoreException(e);
+ }
+
+ }
+
+
+ }
+
+
+ }
+ finally
+ {
+ if(objectsCursor != null)
+ {
+ objectsCursor.close();
+ }
+ }
+ txn.commit();
+
+ hierarchyDb.close();
+ configuredObjectsDb.close();
+
+
+
+ reportFinished(environment, 8);
+ }
+}
diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java
index 7852e2d703..e80d60609f 100644
--- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java
+++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java
@@ -26,6 +26,8 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.store.StoreException;
import org.apache.qpid.server.store.berkeleydb.BDBMessageStore;
@@ -45,12 +47,12 @@ public class Upgrader
static final String VERSION_DB_NAME = "DB_VERSION";
private Environment _environment;
- private String _virtualHostName;
+ private ConfiguredObject<?> _parent;
- public Upgrader(Environment environment, String virtualHostName)
+ public Upgrader(Environment environment, ConfiguredObject<?> parent)
{
_environment = environment;
- _virtualHostName = virtualHostName;
+ _parent = parent;
}
public void upgradeIfNecessary()
@@ -158,7 +160,7 @@ public class Upgrader
+ "UpgradeFrom"+fromVersion+"To"+toVersion);
Constructor<StoreUpgrade> ctr = upgradeClass.getConstructor();
StoreUpgrade upgrade = ctr.newInstance();
- upgrade.performUpgrade(_environment, UpgradeInteractionHandler.DEFAULT_HANDLER, _virtualHostName);
+ upgrade.performUpgrade(_environment, UpgradeInteractionHandler.DEFAULT_HANDLER, _parent);
}
catch (ClassNotFoundException e)
{
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java
index 5a5d39081c..965cad1cb5 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/tuple/ConfiguredObjectBindingTest.java
@@ -29,6 +29,7 @@ import org.apache.qpid.server.store.ConfiguredObjectRecord;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;
+import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
public class ConfiguredObjectBindingTest extends TestCase
{
@@ -46,7 +47,7 @@ public class ConfiguredObjectBindingTest extends TestCase
{
super.setUp();
_configuredObjectBinding = ConfiguredObjectBinding.getInstance();
- _object = new ConfiguredObjectRecord(UUIDGenerator.generateRandomUUID(), DUMMY_TYPE_STRING,
+ _object = new ConfiguredObjectRecordImpl(UUIDGenerator.generateRandomUUID(), DUMMY_TYPE_STRING,
DUMMY_ATTRIBUTES_MAP);
}
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
index b2b28b3c2d..ce143aba1b 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/AbstractUpgradeTestCase.java
@@ -25,12 +25,16 @@ import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPrepare
import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.PRIORITY_QUEUE_NAME;
import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_NAME;
import static org.apache.qpid.server.store.berkeleydb.BDBStoreUpgradeTestPreparer.QUEUE_WITH_DLQ_NAME;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import java.io.File;
import java.io.InputStream;
+import java.util.UUID;
import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.subjects.TestBlankSubject;
+import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.util.FileUtils;
@@ -167,8 +171,11 @@ public abstract class AbstractUpgradeTestCase extends QpidTestCase
return count.longValue();
}
- public String getVirtualHostName()
+ public VirtualHost getVirtualHost()
{
- return getName();
+ VirtualHost virtualHost = mock(VirtualHost.class);
+ when(virtualHost.getName()).thenReturn(getName());
+ when(virtualHost.getId()).thenReturn(UUID.randomUUID());
+ return virtualHost;
}
}
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
index 500fb0a919..d0f9455d9a 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4to5Test.java
@@ -73,7 +73,7 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
public void testPerformUpgradeWithHandlerAnsweringYes() throws Exception
{
UpgradeFrom4To5 upgrade = new UpgradeFrom4To5();
- upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.YES), getVirtualHostName());
+ upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.YES), getVirtualHost());
assertQueues(new HashSet<String>(Arrays.asList(QUEUE_NAMES)));
@@ -103,7 +103,7 @@ public class UpgradeFrom4to5Test extends AbstractUpgradeTestCase
public void testPerformUpgradeWithHandlerAnsweringNo() throws Exception
{
UpgradeFrom4To5 upgrade = new UpgradeFrom4To5();
- upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.NO), getVirtualHostName());
+ upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.NO), getVirtualHost());
HashSet<String> queues = new HashSet<String>(Arrays.asList(QUEUE_NAMES));
assertTrue(NON_DURABLE_QUEUE_NAME + " should be in the list of queues" , queues.remove(NON_DURABLE_QUEUE_NAME));
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
index 701fd94115..0460b1ce4c 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java
@@ -87,7 +87,7 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
public void testPerformUpgrade() throws Exception
{
UpgradeFrom5To6 upgrade = new UpgradeFrom5To6();
- upgrade.performUpgrade(_environment, UpgradeInteractionHandler.DEFAULT_HANDLER, getVirtualHostName());
+ upgrade.performUpgrade(_environment, UpgradeInteractionHandler.DEFAULT_HANDLER, getVirtualHost());
assertDatabaseRecordCounts();
assertContent();
@@ -101,7 +101,7 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
corruptDatabase();
UpgradeFrom5To6 upgrade = new UpgradeFrom5To6();
- upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.YES), getVirtualHostName());
+ upgrade.performUpgrade(_environment, new StaticAnswerHandler(UpgradeInteractionResponse.YES), getVirtualHost());
assertDatabaseRecordCounts();
@@ -117,7 +117,7 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
UpgradeInteractionHandler discardMessageInteractionHandler = new StaticAnswerHandler(UpgradeInteractionResponse.NO);
- upgrade.performUpgrade(_environment, discardMessageInteractionHandler, getVirtualHostName());
+ upgrade.performUpgrade(_environment, discardMessageInteractionHandler, getVirtualHost());
assertDatabaseRecordCount(NEW_METADATA_DB_NAME, 12);
assertDatabaseRecordCount(NEW_CONTENT_DB_NAME, 12);
@@ -135,7 +135,7 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
{
populateOldXidEntries(environment);
UpgradeFrom5To6 upgrade = new UpgradeFrom5To6();
- upgrade.performUpgrade(environment, UpgradeInteractionHandler.DEFAULT_HANDLER, getVirtualHostName());
+ upgrade.performUpgrade(environment, UpgradeInteractionHandler.DEFAULT_HANDLER, getVirtualHost());
assertXidEntries(environment);
}
finally
@@ -171,11 +171,11 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
NewRecordImpl[] newDequeues = newTransaction.getDequeues();
assertEquals("Unxpected new enqueus number", 1, newEnqueues.length);
NewRecordImpl enqueue = newEnqueues[0];
- assertEquals("Unxpected queue id", UUIDGenerator.generateQueueUUID("TEST1", getVirtualHostName()), enqueue.getId());
+ assertEquals("Unxpected queue id", UUIDGenerator.generateQueueUUID("TEST1", getVirtualHost().getName()), enqueue.getId());
assertEquals("Unxpected message id", 1, enqueue.getMessageNumber());
assertEquals("Unxpected new dequeues number", 1, newDequeues.length);
NewRecordImpl dequeue = newDequeues[0];
- assertEquals("Unxpected queue id", UUIDGenerator.generateQueueUUID("TEST2", getVirtualHostName()), dequeue.getId());
+ assertEquals("Unxpected queue id", UUIDGenerator.generateQueueUUID("TEST2", getVirtualHost().getName()), dequeue.getId());
assertEquals("Unxpected message id", 2, dequeue.getMessageNumber());
}
@@ -347,13 +347,13 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
{
String exchangeName = (String) deserialized.get(Exchange.NAME);
assertNotNull(exchangeName);
- assertEquals("Unexpected key", key, UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHostName()));
+ assertEquals("Unexpected key", key, UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHost().getName()));
}
else if (type.equals(Queue.class.getName()))
{
String queueName = (String) deserialized.get(Queue.NAME);
assertNotNull(queueName);
- assertEquals("Unexpected key", key, UUIDGenerator.generateQueueUUID(queueName, getVirtualHostName()));
+ assertEquals("Unexpected key", key, UUIDGenerator.generateQueueUUID(queueName, getVirtualHost().getName()));
}
else if (type.equals(Binding.class.getName()))
{
@@ -368,15 +368,15 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase
private Map<String, Object> createExpectedQueueBindingMapAndID(String queue, String bindingName, String exchangeName, Map<String, String> argumentMap, List<UUID> expectedBindingIDs)
{
Map<String, Object> expectedQueueBinding = new HashMap<String, Object>();
- expectedQueueBinding.put(Binding.QUEUE, UUIDGenerator.generateQueueUUID(queue, getVirtualHostName()).toString());
+ expectedQueueBinding.put(Binding.QUEUE, UUIDGenerator.generateQueueUUID(queue, getVirtualHost().getName()).toString());
expectedQueueBinding.put(Binding.NAME, bindingName);
- expectedQueueBinding.put(Binding.EXCHANGE, UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHostName()).toString());
+ expectedQueueBinding.put(Binding.EXCHANGE, UUIDGenerator.generateExchangeUUID(exchangeName, getVirtualHost().getName()).toString());
if (argumentMap != null)
{
expectedQueueBinding.put(Binding.ARGUMENTS, argumentMap);
}
- expectedBindingIDs.add(UUIDGenerator.generateBindingUUID(exchangeName, queue, bindingName, getVirtualHostName()));
+ expectedBindingIDs.add(UUIDGenerator.generateBindingUUID(exchangeName, queue, bindingName, getVirtualHost().getName()));
return expectedQueueBinding;
}
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java
index 810f4a1fca..c407be50c6 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java
@@ -43,7 +43,7 @@ public class UpgraderFailOnNewerVersionTest extends AbstractUpgradeTestCase
public void setUp() throws Exception
{
super.setUp();
- _upgrader = new Upgrader(_environment, getVirtualHostName());
+ _upgrader = new Upgrader(_environment, getVirtualHost());
}
private int getStoreVersion()
diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java
index 3465f3582f..4b9a8d19a8 100644
--- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java
+++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderTest.java
@@ -51,7 +51,7 @@ public class UpgraderTest extends AbstractUpgradeTestCase
public void setUp() throws Exception
{
super.setUp();
- _upgrader = new Upgrader(_environment, getVirtualHostName());
+ _upgrader = new Upgrader(_environment, getVirtualHost());
}
private int getStoreVersion(Environment environment)
@@ -108,7 +108,7 @@ public class UpgraderTest extends AbstractUpgradeTestCase
Environment emptyEnvironment = createEnvironment(nonExistentStoreLocation);
try
{
- _upgrader = new Upgrader(emptyEnvironment, getVirtualHostName());
+ _upgrader = new Upgrader(emptyEnvironment, getVirtualHost());
_upgrader.upgradeIfNecessary();
List<String> databaseNames = emptyEnvironment.getDatabaseNames();
diff --git a/qpid/java/bdbstore/systests/pom.xml b/qpid/java/bdbstore/systests/pom.xml
index e8620d3426..fe718f9dac 100644
--- a/qpid/java/bdbstore/systests/pom.xml
+++ b/qpid/java/bdbstore/systests/pom.xml
@@ -33,6 +33,7 @@
<test.log4j.configuration.file>${project.basedir}${file.separator}..${file.separator}..${file.separator}test-profiles${file.separator}log4j-test.xml</test.log4j.configuration.file>
<test.working.directory>${basedir}/../..</test.working.directory>
<test.resource.directory>${basedir}/../..</test.resource.directory>
+ <test.systest.resource.directory>${basedir}/../../systests</test.systest.resource.directory>
</properties>
<dependencies>
@@ -65,6 +66,66 @@
<groupId>com.sleepycat</groupId>
<artifactId>je</artifactId>
</dependency>
+
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-bdbstore</artifactId>
+ <version>${project.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <!--version specified in parent pluginManagement -->
+ <executions>
+ <!-- copy the bdbstore bin contents to where the tests expect them -->
+ <execution>
+ <id>copy-bdbstore-bin-resources</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${qpid.home}</outputDirectory>
+ <resources>
+ <resource>
+ <directory>${basedir}/..</directory>
+ <includes>
+ <include>bin/</include>
+ </includes>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <executions>
+ <!-- fix the fact that the maven-resources-plugin copy-resources doesn't maintain file permissions in unix -->
+ <execution>
+ <id>fix-bdb-script-permissions</id>
+ <phase>package</phase>
+ <configuration>
+ <target>
+ <chmod perm="755">
+ <fileset dir="${qpid.home}">
+ <include name="bin/**"/>
+ </fileset>
+ </chmod>
+ </target>
+ </configuration>
+ <goals><goal>run</goal></goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
</project>
diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
index c8fcfe0826..ba84d0682a 100644
--- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
+++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java
@@ -236,6 +236,7 @@ public class BDBMessageStoreTest extends MessageStoreTest
{
messageStore.closeMessageStore();
+
BDBMessageStore newStore = new BDBMessageStore();
MessageStoreRecoveryHandler recoveryHandler = mock(MessageStoreRecoveryHandler.class);
@@ -243,7 +244,7 @@ public class BDBMessageStoreTest extends MessageStoreTest
VirtualHost<?> virtualHost = getVirtualHostModel();
newStore.openMessageStore(virtualHost.getName(), virtualHost.getMessageStoreSettings());
- newStore.recoverMessageStore(recoveryHandler, null);
+ newStore.recoverMessageStore(getVirtualHostModel(), recoveryHandler, null);
return newStore;
}
diff --git a/qpid/java/broker-core/src/main/java/broker.bnd b/qpid/java/broker-core/src/main/java/broker.bnd
index 1a371a5efd..8b3f663ec6 100755
--- a/qpid/java/broker-core/src/main/java/broker.bnd
+++ b/qpid/java/broker-core/src/main/java/broker.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.27.0
+ver: 0.29.0
Bundle-SymbolicName: qpid-broker
Bundle-Version: ${ver}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
index ffa1d65ec2..0ec6a31253 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java
@@ -29,6 +29,7 @@ import java.util.List;
import java.util.Properties;
import java.util.Set;
+import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.PropertyConfigurator;
import org.apache.qpid.server.configuration.ConfigurationEntryStore;
@@ -41,7 +42,6 @@ import org.apache.qpid.server.logging.messages.BrokerMessages;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.TaskPrincipal;
import javax.security.auth.Subject;
@@ -52,6 +52,7 @@ public class Broker
private volatile Thread _shutdownHookThread;
private volatile IApplicationRegistry _applicationRegistry;
private EventLogger _eventLogger;
+ private boolean _configuringOwnLogging = false;
protected static class InitException extends RuntimeException
{
@@ -71,11 +72,20 @@ public class Broker
}
finally
{
- if (_applicationRegistry != null)
+ try
{
- _applicationRegistry.close();
+ if (_applicationRegistry != null)
+ {
+ _applicationRegistry.close();
+ }
+ }
+ finally
+ {
+ if (_configuringOwnLogging)
+ {
+ LogManager.shutdown();
+ }
}
-
}
}
@@ -166,6 +176,7 @@ public class Broker
private void configureLogging(File logConfigFile, int logWatchTime) throws InitException, IOException
{
+ _configuringOwnLogging = true;
if (logConfigFile.exists() && logConfigFile.canRead())
{
_eventLogger.message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath()));
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java
index 8eec88d556..46f3cd458b 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java
@@ -32,6 +32,7 @@ import org.apache.qpid.server.model.AuthenticationProvider;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.PreferencesProvider;
+import org.apache.qpid.server.model.User;
import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory;
public class AuthenticationProviderRecoverer implements ConfiguredObjectRecoverer<AuthenticationProvider>
@@ -68,9 +69,24 @@ public class AuthenticationProviderRecoverer implements ConfiguredObjectRecovere
Map<String, Collection<ConfigurationEntry>> childEntries,
String type)
{
- ConfiguredObjectRecoverer<?> recoverer = recovererProvider.getRecoverer(type);
+ ConfiguredObjectRecoverer<?> recoverer = null;
+
+ if(authenticationProvider instanceof RecovererProvider)
+ {
+ recoverer = ((RecovererProvider)authenticationProvider).getRecoverer(type);
+ }
+
+ if(recoverer == null)
+ {
+ recoverer = recovererProvider.getRecoverer(type);
+ }
+
if (recoverer == null)
{
+ if(authenticationProvider instanceof RecovererProvider)
+ {
+ ((RecovererProvider)authenticationProvider).getRecoverer(type);
+ }
throw new IllegalConfigurationException("Cannot recover entry for the type '" + type + "' from broker");
}
Collection<ConfigurationEntry> entries = childEntries.get(type);
@@ -85,6 +101,10 @@ public class AuthenticationProviderRecoverer implements ConfiguredObjectRecovere
{
authenticationProvider.setPreferencesProvider((PreferencesProvider)object);
}
+ else if(object instanceof User)
+ {
+ authenticationProvider.recoverUser((User)object);
+ }
else
{
throw new IllegalConfigurationException("Cannot associate " + object + " with authentication provider " + authenticationProvider);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java
index e030d50e56..addc42e6f9 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java
@@ -87,7 +87,7 @@ public class StoreConfigurationChangeListener implements ConfigurationChangeList
private ConfigurationEntry toConfigurationEntry(ConfiguredObject object)
{
- Class<? extends ConfiguredObject> objectType = getConfiguredObjectType(object);
+ Class<? extends ConfiguredObject> objectType = object.getCategoryClass();
Set<UUID> childrenIds = getChildrenIds(object, objectType);
ConfigurationEntry entry = new ConfigurationEntry(object.getId(), objectType.getSimpleName(),
object.getActualAttributes(), childrenIds, _store);
@@ -120,98 +120,6 @@ public class StoreConfigurationChangeListener implements ConfigurationChangeList
return childrenIds;
}
- private Class<? extends ConfiguredObject> getConfiguredObjectType(ConfiguredObject object)
- {
- if (object instanceof Broker)
- {
- return Broker.class;
- }
- else if (object instanceof VirtualHost)
- {
- return VirtualHost.class;
- }
- else if (object instanceof Port)
- {
- return Port.class;
- }
- else if (object instanceof AuthenticationProvider)
- {
- return AuthenticationProvider.class;
- }
- return getConfiguredObjectTypeFromImplementedInterfaces(object.getClass());
- }
-
- @SuppressWarnings("unchecked")
- private Class<? extends ConfiguredObject> getConfiguredObjectTypeFromImplementedInterfaces(Class<?> objectClass)
- {
- // get all implemented interfaces extending ConfiguredObject
- Set<Class<?>> interfaces = getImplementedInterfacesExtendingSuper(objectClass, ConfiguredObject.class);
-
- if (interfaces.size() == 0)
- {
- throw new StoreException("Can not identify the configured object type");
- }
-
- if (interfaces.size() == 1)
- {
- return (Class<? extends ConfiguredObject>)interfaces.iterator().next();
- }
-
- Set<Class<?>> superInterfaces = new HashSet<Class<?>>();
-
- // find all super interfaces
- for (Class<?> interfaceClass : interfaces)
- {
- for (Class<?> interfaceClass2 : interfaces)
- {
- if (interfaceClass != interfaceClass2)
- {
- if (interfaceClass.isAssignableFrom(interfaceClass2))
- {
- superInterfaces.add(interfaceClass);
- }
- }
- }
- }
-
- // remove super interfaces
- for (Class<?> superInterface : superInterfaces)
- {
- interfaces.remove(superInterface);
- }
-
- if (interfaces.size() == 1)
- {
- return (Class<? extends ConfiguredObject>)interfaces.iterator().next();
- }
- else
- {
- throw new StoreException("Can not identify the configured object type as an it implements"
- + " more than one configured object interfaces: " + interfaces);
- }
-
- }
-
- private Set<Class<?>> getImplementedInterfacesExtendingSuper(Class<?> classInstance, Class<?> superInterface)
- {
- Set<Class<?>> interfaces = new HashSet<Class<?>>();
- Class<?>[] classInterfaces = classInstance.getInterfaces();
- for (Class<?> interfaceClass : classInterfaces)
- {
- if (interfaceClass!= superInterface && superInterface.isAssignableFrom(interfaceClass))
- {
- interfaces.add(interfaceClass);
- }
- }
- Class<?> superClass = classInstance.getSuperclass();
- if (superClass != null)
- {
- Set<Class<?>> superClassInterfaces = getImplementedInterfacesExtendingSuper(superClass, superInterface);
- interfaces.addAll(superClassInterfaces);
- }
- return interfaces;
- }
-
@Override
public String toString()
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index a30806d810..25f20ba1ee 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -612,7 +612,7 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>>
}
// Check access
- _virtualHost.getSecurityManager().authoriseUnbind(this, bindingKey, queue);
+ _virtualHost.getSecurityManager().authoriseUnbind(binding);
BindingImpl b = _bindingsMap.remove(new BindingIdentifier(bindingKey,queue));
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
index 8e1ea39cec..fc0a8ab7e5 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java
@@ -55,4 +55,6 @@ public interface AuthenticationProvider<X extends AuthenticationProvider<X>> ext
* @param preferencesProvider
*/
void setPreferencesProvider(PreferencesProvider preferencesProvider);
+
+ void recoverUser(User user);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
index b674f1e7db..7e3e5c9bbe 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.model;
import org.apache.qpid.server.model.adapter.AbstractConfiguredObject;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
import java.security.AccessControlException;
import java.util.Collection;
@@ -276,4 +277,10 @@ public interface ConfiguredObject<X extends ConfiguredObject<X>>
ConfiguredObject... otherParents);
void setAttributes(Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException;
+
+ Class<? extends ConfiguredObject> getCategoryClass();
+
+ // TODO - remove this when objects become responsible for their own storage
+ ConfiguredObjectRecord asObjectRecord();
+
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
index 6e8932d3ba..103602edf5 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
@@ -26,9 +26,10 @@ import java.util.Map;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.message.MessageInstance;
-import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.store.MessageStore;
+import java.util.UUID;
+
@ManagedObject( managesChildren = true )
public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject<X>
{
@@ -173,15 +174,11 @@ public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject<
void executeTransaction(TransactionalOperation op);
- /**
- * A temporary hack to expose host security manager.
- * TODO We need to add and implement an authorization provider configured object instead
- */
- SecurityManager getSecurityManager();
-
// TODO - remove this
TaskExecutor getTaskExecutor();
+ Exchange getExchange(UUID id);
+
MessageStore getMessageStore();
String getType();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java
index d263bb45b2..52208f7d7f 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AbstractConfiguredObject.java
@@ -26,6 +26,7 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessControlException;
import java.security.AccessController;
+import java.security.PrivilegedAction;
import java.util.*;
import org.apache.qpid.server.model.*;
@@ -37,6 +38,7 @@ import org.apache.qpid.server.configuration.updater.SetAttributeTask;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.util.MapValueConverter;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
@@ -212,7 +214,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
final AuthenticatedPrincipal currentUser = SecurityManager.getCurrentUser();
if(currentUser != null)
{
- _attributes.put(CREATED_BY, currentUser);
+ _attributes.put(CREATED_BY, currentUser.getName());
}
}
if(!_attributes.containsKey(CREATED_TIME))
@@ -256,6 +258,11 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
return _name;
}
+ public Class<? extends ConfiguredObject> getCategoryClass()
+ {
+ return getCategory(getClass());
+ }
+
public State getDesiredState()
{
return null; //TODO
@@ -558,6 +565,61 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
return getClass().getSimpleName() + " [id=" + _id + ", name=" + getName() + "]";
}
+ public ConfiguredObjectRecord asObjectRecord()
+ {
+ return new ConfiguredObjectRecord()
+ {
+ @Override
+ public UUID getId()
+ {
+ return AbstractConfiguredObject.this.getId();
+ }
+
+ @Override
+ public String getType()
+ {
+ return getCategoryClass().getSimpleName();
+ }
+
+ @Override
+ public Map<String, Object> getAttributes()
+ {
+ return Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Map<String, Object>>()
+ {
+ @Override
+ public Map<String, Object> run()
+ {
+ Map<String,Object> actualAttributes = new HashMap<String, Object>(getActualAttributes());
+ for(Map.Entry<String,Object> entry : actualAttributes.entrySet())
+ {
+ if(entry.getValue() instanceof ConfiguredObject)
+ {
+ entry.setValue(((ConfiguredObject)entry.getValue()).getId());
+ }
+ }
+ actualAttributes.remove(ID);
+ return actualAttributes;
+ }
+ });
+ }
+
+ @Override
+ public Map<String, ConfiguredObjectRecord> getParents()
+ {
+ Map<String, ConfiguredObjectRecord> parents = new LinkedHashMap<String, ConfiguredObjectRecord>();
+ for(Class<? extends ConfiguredObject> parentClass : Model.getInstance().getParentTypes(getCategoryClass()))
+ {
+ ConfiguredObject parent = getParent(parentClass);
+ if(parent != null)
+ {
+ parents.put(parentClass.getSimpleName(), parent.asObjectRecord());
+ }
+ }
+ return parents;
+ }
+ };
+ }
+
@SuppressWarnings("unchecked")
@Override
public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
index 2e86d834bb..fafe081226 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java
@@ -42,7 +42,6 @@ import org.apache.qpid.server.plugin.ExchangeType;
import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.ConflationQueue;
-import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.stats.StatisticsGatherer;
import org.apache.qpid.server.store.MessageStore;
@@ -1042,12 +1041,6 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo
}
@Override
- public SecurityManager getSecurityManager()
- {
- return _virtualHost.getSecurityManager();
- }
-
- @Override
public MessageStore getMessageStore()
{
return _virtualHost.getMessageStore();
@@ -1089,9 +1082,15 @@ public final class VirtualHostAdapter extends AbstractConfiguredObject<VirtualHo
}
}
+ @Override
public TaskExecutor getTaskExecutor()
{
return super.getTaskExecutor();
}
+ @Override
+ public Exchange getExchange(UUID id)
+ {
+ return _virtualHost.getExchange(id);
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
index 77886e9030..478499fe6c 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SecurityManager.java
@@ -18,27 +18,6 @@
*/
package org.apache.qpid.server.security;
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.server.binding.BindingImpl;
-import org.apache.qpid.server.consumer.ConsumerImpl;
-import org.apache.qpid.server.exchange.ExchangeImpl;
-
-import org.apache.qpid.server.model.*;
-import org.apache.qpid.server.plugin.AccessControlFactory;
-import org.apache.qpid.server.plugin.QpidServiceLoader;
-import org.apache.qpid.server.protocol.AMQConnectionModel;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.security.access.FileAccessControlProviderConstants;
-import org.apache.qpid.server.security.access.ObjectProperties;
-import org.apache.qpid.server.security.access.ObjectType;
-import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.security.access.OperationLoggingDetails;
-import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
-import org.apache.qpid.server.security.auth.TaskPrincipal;
-
-import javax.security.auth.Subject;
-
import static org.apache.qpid.server.security.access.ObjectType.BROKER;
import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE;
import static org.apache.qpid.server.security.access.ObjectType.GROUP;
@@ -62,54 +41,48 @@ import java.security.AccessController;
import java.security.Principal;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.binding.BindingImpl;
+import org.apache.qpid.server.consumer.ConsumerImpl;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.model.AccessControlProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ConfigurationChangeListener;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectProperties.Property;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.access.OperationLoggingDetails;
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.security.auth.TaskPrincipal;
+
public class SecurityManager implements ConfigurationChangeListener
{
- private static final Logger _logger = Logger.getLogger(SecurityManager.class);
-
private static final Subject SYSTEM = new Subject(true,
Collections.singleton(new SystemPrincipal()),
Collections.emptySet(),
Collections.emptySet());
+ private final ConcurrentHashMap<String, AccessControl> _plugins = new ConcurrentHashMap<String, AccessControl>();
+ private final boolean _managementMode;
+ private final Broker<?> _broker;
- private ConcurrentHashMap<String, AccessControl> _globalPlugins = new ConcurrentHashMap<String, AccessControl>();
- private ConcurrentHashMap<String, AccessControl> _hostPlugins = new ConcurrentHashMap<String, AccessControl>();
-
- private boolean _managementMode;
-
- private Broker _broker;
+ private final ConcurrentHashMap<PublishAccessCheckCacheEntry, PublishAccessCheck> _publishAccessCheckCache = new ConcurrentHashMap<SecurityManager.PublishAccessCheckCacheEntry, SecurityManager.PublishAccessCheck>();
- /*
- * Used by the Broker.
- */
- public SecurityManager(Broker broker, boolean managementMode)
+ public SecurityManager(Broker<?> broker, boolean managementMode)
{
_managementMode = managementMode;
_broker = broker;
}
- /*
- * Used by the VirtualHost to allow deferring to the broker level security plugins if required.
- */
- public SecurityManager(SecurityManager parent, String aclFile, String vhostName)
- {
- _managementMode = parent._managementMode;
- _broker = parent._broker;
- if(!_managementMode)
- {
- configureVirtualHostAclPlugin(aclFile, vhostName);
-
- // our global plugins are the parent's host plugins
- _globalPlugins = parent._hostPlugins;
- }
- }
-
public static Subject getSubjectWithAddedSystemRights()
{
Subject subject = Subject.getSubject(AccessController.getContext());
@@ -135,50 +108,11 @@ public class SecurityManager implements ConfigurationChangeListener
return subject;
}
- private void configureVirtualHostAclPlugin(String aclFile, String vhostName)
- {
- if(aclFile != null)
- {
- Map<String, Object> attributes = new HashMap<String, Object>();
-
- attributes.put(AccessControlProvider.TYPE, FileAccessControlProviderConstants.ACL_FILE_PROVIDER_TYPE);
- attributes.put(FileAccessControlProviderConstants.PATH, aclFile);
-
- for (AccessControlFactory provider : (new QpidServiceLoader<AccessControlFactory>()).instancesOf(AccessControlFactory.class))
- {
- AccessControl accessControl = provider.createInstance(attributes, _broker);
- accessControl.open();
- if(accessControl != null)
- {
- String pluginTypeName = getPluginTypeName(accessControl);
- _hostPlugins.put(pluginTypeName, accessControl);
-
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Added access control to host plugins with name: " + vhostName);
- }
-
- break;
- }
- }
- }
-
- if(_logger.isDebugEnabled())
- {
- _logger.debug("Configured " + _hostPlugins.size() + " access control plugins");
- }
- }
-
private String getPluginTypeName(AccessControl accessControl)
{
return accessControl.getClass().getName();
}
- public static Logger getLogger()
- {
- return _logger;
- }
-
public static boolean isSystemProcess()
{
Subject subject = Subject.getSubject(AccessController.getContext());
@@ -234,71 +168,14 @@ public class SecurityManager implements ConfigurationChangeListener
return true;
}
- Map<String, AccessControl> remainingPlugins = _globalPlugins.isEmpty()
- ? Collections.<String, AccessControl>emptyMap()
- : _hostPlugins.isEmpty() ? _globalPlugins : new HashMap<String, AccessControl>(_globalPlugins);
-
- if(!_hostPlugins.isEmpty())
- {
- for (Entry<String, AccessControl> hostEntry : _hostPlugins.entrySet())
- {
- // Create set of global only plugins
- AccessControl globalPlugin = remainingPlugins.get(hostEntry.getKey());
- if (globalPlugin != null)
- {
- remainingPlugins.remove(hostEntry.getKey());
- }
-
- Result host = checker.allowed(hostEntry.getValue());
-
- if (host == Result.DENIED)
- {
- // Something vetoed the access, we're done
- return false;
- }
-
- // host allow overrides global allow, so only check global on abstain or defer
- if (host != Result.ALLOWED)
- {
- if (globalPlugin == null)
- {
- if (host == Result.DEFER)
- {
- host = hostEntry.getValue().getDefault();
- }
- if (host == Result.DENIED)
- {
- return false;
- }
- }
- else
- {
- Result global = checker.allowed(globalPlugin);
- if (global == Result.DEFER)
- {
- global = globalPlugin.getDefault();
- }
- if (global == Result.ABSTAIN && host == Result.DEFER)
- {
- global = hostEntry.getValue().getDefault();
- }
- if (global == Result.DENIED)
- {
- return false;
- }
- }
- }
- }
- }
-
- for (AccessControl plugin : remainingPlugins.values())
+ for (AccessControl plugin : _plugins.values())
{
Result remaining = checker.allowed(plugin);
- if (remaining == Result.DEFER)
+ if (remaining == Result.DEFER)
{
remaining = plugin.getDefault();
}
- if (remaining == Result.DENIED)
+ if (remaining == Result.DENIED)
{
return false;
}
@@ -308,28 +185,23 @@ public class SecurityManager implements ConfigurationChangeListener
return true;
}
- public void authoriseCreateBinding(BindingImpl binding)
+ public void authoriseCreateBinding(final BindingImpl binding)
{
- final ExchangeImpl exch = binding.getExchange();
- final AMQQueue queue = binding.getAMQQueue();
- final String bindingKey = binding.getBindingKey();
-
- boolean allowed =
- checkAllPlugins(new AccessCheck()
+ boolean allowed = checkAllPlugins(new AccessCheck()
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(BIND, EXCHANGE, new ObjectProperties(exch, queue, bindingKey));
+ return plugin.authorise(BIND, EXCHANGE, new ObjectProperties(binding));
}
});
if(!allowed)
{
- throw new AccessControlException("Permission denied: binding " + bindingKey);
+ throw new AccessControlException("Permission denied: binding " + binding.getBindingKey());
}
}
- public void authoriseMethod(final Operation operation, final String componentName, final String methodName)
+ public void authoriseMethod(final Operation operation, final String componentName, final String methodName, final String virtualHostName)
{
boolean allowed = checkAllPlugins(new AccessCheck()
{
@@ -339,8 +211,11 @@ public class SecurityManager implements ConfigurationChangeListener
properties.setName(methodName);
if (componentName != null)
{
- // Only set the property if there is a component name
- properties.put(ObjectProperties.Property.COMPONENT, componentName);
+ properties.put(ObjectProperties.Property.COMPONENT, componentName);
+ }
+ if (virtualHostName != null)
+ {
+ properties.put(ObjectProperties.Property.VIRTUALHOST_NAME, virtualHostName);
}
return plugin.authorise(operation, METHOD, properties);
}
@@ -367,15 +242,19 @@ public class SecurityManager implements ConfigurationChangeListener
public void authoriseCreateConnection(final AMQConnectionModel connection)
{
+ final String virtualHostName = connection.getVirtualHostName();
if(!checkAllPlugins(new AccessCheck()
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(Operation.ACCESS, VIRTUALHOST, ObjectProperties.EMPTY);
+ // We put the name into the properties under both name and virtualhost_name so the user may express predicates using either.
+ ObjectProperties properties = new ObjectProperties(virtualHostName);
+ properties.put(Property.VIRTUALHOST_NAME, virtualHostName);
+ return plugin.authorise(Operation.ACCESS, VIRTUALHOST, properties);
}
}))
{
- throw new AccessControlException("Permission denied: " + connection.getVirtualHostName());
+ throw new AccessControlException("Permission denied: " + virtualHostName);
}
}
@@ -403,10 +282,7 @@ public class SecurityManager implements ConfigurationChangeListener
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(CREATE, EXCHANGE, new ObjectProperties(exchange.isAutoDelete(),
- exchange.isDurable(),
- exchangeName,
- exchange.getTypeName()));
+ return plugin.authorise(CREATE, EXCHANGE, new ObjectProperties(exchange));
}
}))
{
@@ -421,11 +297,7 @@ public class SecurityManager implements ConfigurationChangeListener
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(CREATE, QUEUE, new ObjectProperties(queue.getAttribute(Queue.LIFETIME_POLICY) != LifetimePolicy.PERMANENT,
- Boolean.TRUE.equals(queue.getAttribute(Queue.DURABLE)),
- queue.getAttribute(Queue.EXCLUSIVE) != ExclusivityPolicy.NONE,
- queueName,
- queue.getOwner()));
+ return plugin.authorise(CREATE, QUEUE, new ObjectProperties(queue));
}
}))
{
@@ -470,7 +342,7 @@ public class SecurityManager implements ConfigurationChangeListener
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(UPDATE, EXCHANGE, new ObjectProperties(exchange.getName()));
+ return plugin.authorise(UPDATE, EXCHANGE, new ObjectProperties(exchange));
}
}))
{
@@ -484,7 +356,7 @@ public class SecurityManager implements ConfigurationChangeListener
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(DELETE, EXCHANGE, new ObjectProperties(exchange.getName()));
+ return plugin.authorise(DELETE, EXCHANGE, new ObjectProperties(exchange));
}
}))
{
@@ -522,39 +394,15 @@ public class SecurityManager implements ConfigurationChangeListener
}
}
- private ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> _immediatePublishPropsCache
- = new ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>>();
- private ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> _publishPropsCache
- = new ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>>();
-
- public void authorisePublish(final boolean immediate, String routingKey, String exchangeName)
+ public void authorisePublish(final boolean immediate, String routingKey, String exchangeName, String virtualHostName)
{
- if(routingKey == null)
+ PublishAccessCheckCacheEntry key = new PublishAccessCheckCacheEntry(immediate, routingKey, exchangeName, virtualHostName);
+ PublishAccessCheck check = _publishAccessCheckCache.get(key);
+ if (check == null)
{
- routingKey = "";
+ check = new PublishAccessCheck(new ObjectProperties(virtualHostName, exchangeName, routingKey, immediate));
+ _publishAccessCheckCache.putIfAbsent(key, check);
}
- if(exchangeName == null)
- {
- exchangeName = "";
- }
- PublishAccessCheck check;
- ConcurrentHashMap<String, ConcurrentHashMap<String, PublishAccessCheck>> cache =
- immediate ? _immediatePublishPropsCache : _publishPropsCache;
-
- ConcurrentHashMap<String, PublishAccessCheck> exchangeMap = cache.get(exchangeName);
- if(exchangeMap == null)
- {
- cache.putIfAbsent(exchangeName, new ConcurrentHashMap<String, PublishAccessCheck>());
- exchangeMap = cache.get(exchangeName);
- }
-
- check = exchangeMap.get(routingKey);
- if(check == null)
- {
- check = new PublishAccessCheck(new ObjectProperties(exchangeName, routingKey, immediate));
- exchangeMap.put(routingKey, check);
- }
-
if(!checkAllPlugins(check))
{
throw new AccessControlException("Permission denied, publish to: exchange-name '" + exchangeName + "'");
@@ -575,17 +423,17 @@ public class SecurityManager implements ConfigurationChangeListener
}
}
- public void authoriseUnbind(final ExchangeImpl exch, final String routingKey, final AMQQueue queue)
+ public void authoriseUnbind(final BindingImpl binding)
{
if(! checkAllPlugins(new AccessCheck()
{
Result allowed(AccessControl plugin)
{
- return plugin.authorise(UNBIND, EXCHANGE, new ObjectProperties(exch, queue, routingKey));
+ return plugin.authorise(UNBIND, EXCHANGE, new ObjectProperties(binding));
}
}))
{
- throw new AccessControlException("Permission denied: unbinding " + routingKey);
+ throw new AccessControlException("Permission denied: unbinding " + binding.getBindingKey());
}
}
@@ -618,29 +466,29 @@ public class SecurityManager implements ConfigurationChangeListener
{
if(newState == State.ACTIVE)
{
- synchronized (_hostPlugins)
+ synchronized (_plugins)
{
AccessControl accessControl = ((AccessControlProvider)object).getAccessControl();
String pluginTypeName = getPluginTypeName(accessControl);
- _hostPlugins.put(pluginTypeName, accessControl);
+ _plugins.put(pluginTypeName, accessControl);
}
}
else if(newState == State.DELETED)
{
- synchronized (_hostPlugins)
+ synchronized (_plugins)
{
AccessControl control = ((AccessControlProvider)object).getAccessControl();
String pluginTypeName = getPluginTypeName(control);
// Remove the type->control mapping for this type key only if the
// given control is actually referred to.
- if(_hostPlugins.containsValue(control))
+ if(_plugins.containsValue(control))
{
// If we are removing this control, check if another of the same
// type already exists on the broker and use it in instead.
AccessControl other = null;
- Collection<AccessControlProvider> providers = _broker.getAccessControlProviders();
+ Collection<AccessControlProvider<?>> providers = _broker.getAccessControlProviders();
for(AccessControlProvider p : providers)
{
if(p == object || p.getState() != State.ACTIVE)
@@ -660,12 +508,12 @@ public class SecurityManager implements ConfigurationChangeListener
if(other != null)
{
//Another control of this type was found, use it instead
- _hostPlugins.replace(pluginTypeName, control, other);
+ _plugins.replace(pluginTypeName, control, other);
}
else
{
//No other was found, remove the type entirely
- _hostPlugins.remove(pluginTypeName);
+ _plugins.remove(pluginTypeName);
}
}
}
@@ -718,4 +566,90 @@ public class SecurityManager implements ConfigurationChangeListener
});
}
+ public static class PublishAccessCheckCacheEntry
+ {
+ private final boolean _immediate;
+ private final String _routingKey;
+ private final String _exchangeName;
+ private final String _virtualHostName;
+
+ public PublishAccessCheckCacheEntry(boolean immediate, String routingKey, String exchangeName, String virtualHostName)
+ {
+ super();
+ _immediate = immediate;
+ _routingKey = routingKey;
+ _exchangeName = exchangeName;
+ _virtualHostName = virtualHostName;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((_exchangeName == null) ? 0 : _exchangeName.hashCode());
+ result = prime * result + (_immediate ? 1231 : 1237);
+ result = prime * result + ((_routingKey == null) ? 0 : _routingKey.hashCode());
+ result = prime * result + ((_virtualHostName == null) ? 0 : _virtualHostName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (obj == null)
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ PublishAccessCheckCacheEntry other = (PublishAccessCheckCacheEntry) obj;
+ if (_exchangeName == null)
+ {
+ if (other._exchangeName != null)
+ {
+ return false;
+ }
+ }
+ else if (!_exchangeName.equals(other._exchangeName))
+ {
+ return false;
+ }
+ if (_immediate != other._immediate)
+ {
+ return false;
+ }
+ if (_routingKey == null)
+ {
+ if (other._routingKey != null)
+ {
+ return false;
+ }
+ }
+ else if (!_routingKey.equals(other._routingKey))
+ {
+ return false;
+ }
+ if (_virtualHostName == null)
+ {
+ if (other._virtualHostName != null)
+ {
+ return false;
+ }
+ }
+ else if (!_virtualHostName.equals(other._virtualHostName))
+ {
+ return false;
+ }
+ return true;
+ }
+
+
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
index ae0241314f..6122cef5c1 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
@@ -26,8 +26,10 @@ import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.qpid.server.binding.BindingImpl;
import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.queue.AMQQueue;
/**
@@ -39,7 +41,7 @@ import org.apache.qpid.server.queue.AMQQueue;
*/
public class ObjectProperties
{
- public static final String STAR= "*";
+ public static final String WILD_CARD = "*";
public static final ObjectProperties EMPTY = new ObjectProperties();
@@ -65,7 +67,8 @@ public class ObjectProperties
PACKAGE,
CLASS,
FROM_NETWORK,
- FROM_HOSTNAME;
+ FROM_HOSTNAME,
+ VIRTUALHOST_NAME;
private static final Map<String, Property> _canonicalNameToPropertyMap = new HashMap<String, ObjectProperties.Property>();
@@ -152,60 +155,49 @@ public class ObjectProperties
{
put(Property.OWNER, queue.getOwner());
}
-
+ put(Property.VIRTUALHOST_NAME, queue.getParent(VirtualHost.class).getName());
}
- public ObjectProperties(ExchangeImpl exch, AMQQueue queue, String routingKey)
+ public ObjectProperties(BindingImpl binding)
{
- this(queue);
+ ExchangeImpl<?> exch = binding.getExchange();
+ AMQQueue<?> queue = binding.getAMQQueue();
+ String routingKey = binding.getBindingKey();
setName(exch.getName());
- put(Property.QUEUE_NAME, queue.getName());
+ put(Property.QUEUE_NAME, queue.getName());
put(Property.ROUTING_KEY, routingKey);
- }
-
- public ObjectProperties(String exchangeName, String routingKey, Boolean immediate)
- {
- this(exchangeName, routingKey);
+ put(Property.VIRTUALHOST_NAME, queue.getParent(VirtualHost.class).getName());
- put(Property.IMMEDIATE, immediate);
+ // The temporary attribute (inherited from the binding's queue) seems to exist to allow the user to
+ // express rules about the binding of temporary queues (whose names cannot be predicted).
+ put(Property.TEMPORARY, queue.getLifetimePolicy() != LifetimePolicy.PERMANENT);
+ put(Property.DURABLE, queue.isDurable());
}
- public ObjectProperties(String exchangeName, String routingKey)
+ public ObjectProperties(String virtualHostName, String exchangeName, String routingKey, Boolean immediate)
{
super();
setName(exchangeName);
put(Property.ROUTING_KEY, routingKey);
+ put(Property.IMMEDIATE, immediate);
+ put(Property.VIRTUALHOST_NAME, virtualHostName);
}
- public ObjectProperties(Boolean autoDelete, Boolean durable, String exchangeName,
- String exchangeType)
- {
- super();
-
- setName(exchangeName);
-
- put(Property.AUTO_DELETE, autoDelete);
- put(Property.TEMPORARY, autoDelete);
- put(Property.DURABLE, durable);
- put(Property.TYPE, exchangeType);
- }
-
- public ObjectProperties(Boolean autoDelete, Boolean durable, Boolean exclusive,
- String queueName, String owner)
+ public ObjectProperties(ExchangeImpl<?> exchange)
{
super();
- setName(queueName);
+ setName(exchange.getName());
- put(Property.AUTO_DELETE, autoDelete);
- put(Property.TEMPORARY, autoDelete);
- put(Property.DURABLE, durable);
- put(Property.EXCLUSIVE, exclusive);
- put(Property.OWNER, owner);
+ put(Property.AUTO_DELETE, exchange.isAutoDelete());
+ put(Property.TEMPORARY, exchange.getLifetimePolicy() != LifetimePolicy.PERMANENT);
+ put(Property.DURABLE, exchange.isDurable());
+ put(Property.TYPE, exchange.getTypeName());
+ put(Property.VIRTUALHOST_NAME, exchange.getParent(VirtualHost.class).getName());
}
public ObjectProperties(Boolean exclusive, Boolean noAck, Boolean noLocal, Boolean nowait, AMQQueue queue)
@@ -283,8 +275,8 @@ public class ObjectProperties
{
return (StringUtils.isEmpty(ruleValue)
|| StringUtils.equals(thisValue, ruleValue))
- || ruleValue.equals(STAR)
- || (ruleValue.endsWith(STAR)
+ || ruleValue.equals(WILD_CARD)
+ || (ruleValue.endsWith(WILD_CARD)
&& thisValue != null
&& thisValue.length() >= ruleValue.length() - 1
&& thisValue.startsWith(ruleValue.substring(0, ruleValue.length() - 1)));
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java
index a683199abc..f36695cb86 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/access/OperationLoggingDetails.java
@@ -32,6 +32,42 @@ public class OperationLoggingDetails extends ObjectProperties
}
@Override
+ public int hashCode()
+ {
+ return super.hashCode() + ((_description == null) ? 0 : _description.hashCode());
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ if (!super.equals(obj))
+ {
+ return false;
+ }
+ if (getClass() != obj.getClass())
+ {
+ return false;
+ }
+ OperationLoggingDetails other = (OperationLoggingDetails) obj;
+ if (_description == null)
+ {
+ if (other._description != null)
+ {
+ return false;
+ }
+ }
+ else if (!_description.equals(other._description))
+ {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
public String toString()
{
StringBuilder sb = new StringBuilder("(");
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
index 17c9a19e50..2274ddb189 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.security.auth.manager;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.configuration.updater.TaskExecutor;
import org.apache.qpid.server.model.*;
import org.apache.qpid.server.model.adapter.AbstractConfiguredObject;
@@ -85,8 +86,11 @@ public abstract class AbstractAuthenticationManager<T extends AbstractAuthentica
_preferencesProvider = preferencesProvider;
}
-
-
+ @Override
+ public void recoverUser(final User user)
+ {
+ throw new IllegalConfigurationException("Cannot associate " + user + " with authentication provider " + this);
+ }
@Override
public String setName(final String currentName, final String desiredName)
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java
new file mode 100644
index 0000000000..097d0bfb9d
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManager.java
@@ -0,0 +1,696 @@
+/*
+ *
+ * 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 org.apache.qpid.server.configuration.ConfigurationEntry;
+import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer;
+import org.apache.qpid.server.configuration.RecovererProvider;
+import org.apache.qpid.server.configuration.updater.ChangeAttributesTask;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.*;
+import org.apache.qpid.server.model.adapter.AbstractConfiguredObject;
+import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.server.security.auth.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.sasl.scram.ScramSHA1SaslServer;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.security.auth.login.AccountNotFoundException;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.xml.bind.DatatypeConverter;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.security.AccessControlException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class ScramSHA1AuthenticationManager
+ extends AbstractAuthenticationManager<ScramSHA1AuthenticationManager>
+ implements PasswordCredentialManagingAuthenticationProvider<ScramSHA1AuthenticationManager>,
+ RecovererProvider
+{
+ public static final String SCRAM_USER_TYPE = "scram";
+ private static final Charset ASCII = Charset.forName("ASCII");
+ public static final String HMAC_SHA_1 = "HmacSHA1";
+ private final SecureRandom _random = new SecureRandom();
+ private int _iterationCount = 4096;
+ private Map<String, ScramAuthUser> _users = new ConcurrentHashMap<String, ScramAuthUser>();
+
+
+ protected ScramSHA1AuthenticationManager(final Broker broker,
+ final Map<String, Object> defaults,
+ final Map<String, Object> attributes,
+ final boolean recovering)
+ {
+ super(broker, defaults, attributes);
+ }
+
+ @Override
+ public void initialise()
+ {
+
+ }
+
+ @Override
+ public String getMechanisms()
+ {
+ return ScramSHA1SaslServer.MECHANISM;
+ }
+
+ @Override
+ public SaslServer createSaslServer(final String mechanism,
+ final String localFQDN,
+ final Principal externalPrincipal)
+ throws SaslException
+ {
+ return new ScramSHA1SaslServer(this);
+ }
+
+ @Override
+ public AuthenticationResult authenticate(final SaslServer server, final byte[] response)
+ {
+ try
+ {
+ // Process response from the client
+ byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]);
+
+ if (server.isComplete())
+ {
+ final String userId = server.getAuthorizationID();
+ return new AuthenticationResult(new UsernamePrincipal(userId));
+ }
+ else
+ {
+ return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE);
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e);
+ }
+ }
+
+ @Override
+ public AuthenticationResult authenticate(final String username, final String password)
+ {
+ ScramAuthUser user = getUser(username);
+ if(user != null)
+ {
+ final String[] usernamePassword = user.getPassword().split(",");
+ byte[] salt = DatatypeConverter.parseBase64Binary(usernamePassword[0]);
+ try
+ {
+ if(Arrays.equals(DatatypeConverter.parseBase64Binary(usernamePassword[1]),createSaltedPassword(salt, password)))
+ {
+ return new AuthenticationResult(new UsernamePrincipal(username));
+ }
+ }
+ catch (SaslException e)
+ {
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,e);
+ }
+
+ }
+
+ return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR);
+
+
+ }
+
+ @Override
+ public void delete()
+ {
+
+ }
+
+ @Override
+ public void close()
+ {
+
+ }
+
+ public int getIterationCount()
+ {
+ return _iterationCount;
+ }
+
+ public byte[] getSalt(final String username)
+ {
+ ScramAuthUser user = getUser(username);
+
+ if(user == null)
+ {
+ // don't disclose that the user doesn't exist, just generate random data so the failure is indistinguishable
+ // from the "wrong password" case
+
+ byte[] salt = new byte[32];
+ _random.nextBytes(salt);
+ return salt;
+ }
+ else
+ {
+ return DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[0]);
+ }
+ }
+
+ private static final byte[] INT_1 = new byte[]{0, 0, 0, 1};
+
+ public byte[] getSaltedPassword(final String username) throws SaslException
+ {
+ ScramAuthUser user = getUser(username);
+ if(user == null)
+ {
+ throw new SaslException("Authentication Failed");
+ }
+ else
+ {
+ return DatatypeConverter.parseBase64Binary(user.getPassword().split(",")[1]);
+ }
+ }
+
+ private ScramAuthUser getUser(final String username)
+ {
+ return _users.get(username);
+ }
+
+ private byte[] createSaltedPassword(byte[] salt, String password) throws SaslException
+ {
+ Mac mac = createSha1Hmac(password.getBytes(ASCII));
+
+ mac.update(salt);
+ mac.update(INT_1);
+ byte[] result = mac.doFinal();
+
+ byte[] previous = null;
+ for(int i = 1; i < getIterationCount(); i++)
+ {
+ mac.update(previous != null? previous: result);
+ previous = mac.doFinal();
+ for(int x = 0; x < result.length; x++)
+ {
+ result[x] ^= previous[x];
+ }
+ }
+
+ return result;
+
+ }
+
+ private Mac createSha1Hmac(final byte[] keyBytes)
+ throws SaslException
+ {
+ try
+ {
+ SecretKeySpec key = new SecretKeySpec(keyBytes, HMAC_SHA_1);
+ Mac mac = Mac.getInstance(HMAC_SHA_1);
+ mac.init(key);
+ return mac;
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean createUser(final String username, final String password, final Map<String, String> attributes)
+ {
+ if (getTaskExecutor().isTaskExecutorThread())
+ {
+ getSecurityManager().authoriseUserOperation(Operation.CREATE, username);
+ if(_users.containsKey(username))
+ {
+ throw new IllegalArgumentException("User '"+username+"' already exists");
+ }
+ try
+ {
+ Map<String,Object> userAttrs = new HashMap<String, Object>();
+ userAttrs.put(User.ID, UUID.randomUUID());
+ userAttrs.put(User.NAME, username);
+ userAttrs.put(User.PASSWORD, createStoredPassword(password));
+ userAttrs.put(User.TYPE, SCRAM_USER_TYPE);
+ ScramAuthUser user = new ScramAuthUser(userAttrs);
+ _users.put(username, user);
+
+ return true;
+ }
+ catch (SaslException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ else
+ {
+ return getTaskExecutor().submitAndWait(new TaskExecutor.Task<Boolean>()
+ {
+ @Override
+ public Boolean call()
+ {
+ return createUser(username, password, attributes);
+ }
+ });
+ }
+
+ }
+
+ private SecurityManager getSecurityManager()
+ {
+ return getBroker().getSecurityManager();
+ }
+
+ @Override
+ public void deleteUser(final String user) throws AccountNotFoundException
+ {
+ if (getTaskExecutor().isTaskExecutorThread())
+ {
+
+ final ScramAuthUser authUser = getUser(user);
+ if(authUser != null)
+ {
+ authUser.setState(State.ACTIVE, State.DELETED);
+ }
+ else
+ {
+ throw new AccountNotFoundException("No such user: '" + user + "'");
+ }
+ }
+ else
+ {
+ AccountNotFoundException e =
+ getTaskExecutor().submitAndWait(new TaskExecutor.Task<AccountNotFoundException>() {
+
+ @Override
+ public AccountNotFoundException call()
+ {
+ try
+ {
+ deleteUser(user);
+ return null;
+ }
+ catch (AccountNotFoundException e)
+ {
+ return e;
+ }
+
+ }
+ });
+
+ if(e != null)
+ {
+ throw e;
+ }
+ }
+ }
+
+ @Override
+ public void setPassword(final String username, final String password) throws AccountNotFoundException
+ {
+ if (getTaskExecutor().isTaskExecutorThread())
+ {
+ final ScramAuthUser authUser = getUser(username);
+ if(authUser != null)
+ {
+ authUser.setPassword(password);
+ }
+ else
+ {
+ throw new AccountNotFoundException("No such user: '" + username + "'");
+ }
+ }
+ else
+ {
+ AccountNotFoundException e =
+ getTaskExecutor().submitAndWait(new TaskExecutor.Task<AccountNotFoundException>()
+ {
+
+ @Override
+ public AccountNotFoundException call()
+ {
+ try
+ {
+ setPassword(username, password);
+ return null;
+ }
+ catch (AccountNotFoundException e)
+ {
+ return e;
+ }
+
+ }
+ });
+
+ if (e != null)
+ {
+ throw e;
+ }
+ }
+
+ }
+
+ @Override
+ public Map<String, Map<String, String>> getUsers()
+ {
+ if (getTaskExecutor().isTaskExecutorThread())
+ {
+ Map<String, Map<String,String>> users = new HashMap<String, Map<String, String>>();
+ for(String user : _users.keySet())
+ {
+ users.put(user, Collections.<String,String>emptyMap());
+ }
+ return users;
+ }
+ else
+ {
+ return getTaskExecutor().submitAndWait(new TaskExecutor.Task<Map<String, Map<String, String>>>()
+ {
+ @Override
+ public Map<String, Map<String, String>> call()
+ {
+ return getUsers();
+ }
+ });
+ }
+ }
+
+ @Override
+ public void reload() throws IOException
+ {
+
+ }
+
+ private static Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> parentsMap(final ScramSHA1AuthenticationManager scramSHA1AuthenticationManager)
+ {
+
+ final Map<Class<? extends ConfiguredObject>, ConfiguredObject<?>> map = new HashMap<Class<? extends ConfiguredObject>, ConfiguredObject<?>>();
+ map.put(AuthenticationProvider.class, scramSHA1AuthenticationManager);
+ return map;
+ }
+
+ @Override
+ public ConfiguredObjectRecoverer<? extends ConfiguredObject> getRecoverer(final String type)
+ {
+ if("User".equals(type))
+ {
+ return new UserRecoverer();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ private class ScramAuthUser extends AbstractConfiguredObject<ScramAuthUser> implements User<ScramAuthUser>
+ {
+
+
+ protected ScramAuthUser(final Map<String, Object> attributes)
+ {
+ super(parentsMap(ScramSHA1AuthenticationManager.this),
+ Collections.<String,Object>emptyMap(),
+ attributes, ScramSHA1AuthenticationManager.this.getTaskExecutor());
+
+ if(!ASCII.newEncoder().canEncode(getName()))
+ {
+ throw new IllegalArgumentException("Scram SHA1 user names are restricted to characters in the ASCII charset");
+ }
+ }
+
+ @Override
+ protected boolean setState(final State currentState, final State desiredState)
+ {
+ if(desiredState == State.DELETED)
+ {
+ getSecurityManager().authoriseUserOperation(Operation.DELETE, getName());
+ _users.remove(getName());
+ ScramSHA1AuthenticationManager.this.childRemoved(this);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public void setAttributes(final Map<String, Object> attributes)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ if (getTaskExecutor().isTaskExecutorThread())
+ {
+ Map<String,Object> modifiedAttributes = new HashMap<String, Object>(attributes);
+ final String newPassword = (String) attributes.get(User.PASSWORD);
+ if(attributes.containsKey(User.PASSWORD) && !newPassword.equals(getActualAttributes().get(User.PASSWORD)))
+ {
+ try
+ {
+ modifiedAttributes.put(User.PASSWORD, createStoredPassword(newPassword));
+ }
+ catch (SaslException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+ super.setAttributes(modifiedAttributes);
+ }
+ else
+ {
+ getTaskExecutor().submitAndWait(new ChangeAttributesTask(this, attributes));
+ }
+
+ }
+
+ @Override
+ public Object getAttribute(final String name)
+ {
+ if(PASSWORD.equals(name))
+ {
+ return null; // for security reasons we don't expose the password
+ }
+ return super.getAttribute(name);
+ }
+
+ @Override
+ public String getPassword()
+ {
+ return (String) getActualAttributes().get(PASSWORD);
+ }
+
+ @Override
+ public void setPassword(final String password)
+ {
+ getSecurityManager().authoriseUserOperation(Operation.UPDATE, getName());
+
+ try
+ {
+ changeAttribute(User.PASSWORD, getAttribute(User.PASSWORD), createStoredPassword(password));
+ }
+ catch (SaslException e)
+ {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public String setName(final String currentName, final String desiredName)
+ throws IllegalStateException, AccessControlException
+ {
+ throw new IllegalStateException("Names cannot be updated");
+ }
+
+ @Override
+ public State getState()
+ {
+ return State.ACTIVE;
+ }
+
+ @Override
+ public boolean isDurable()
+ {
+ return true;
+ }
+
+ @Override
+ public void setDurable(final boolean durable)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+
+ }
+
+ @Override
+ public LifetimePolicy getLifetimePolicy()
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+
+ @Override
+ public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired)
+ throws IllegalStateException, AccessControlException, IllegalArgumentException
+ {
+ if(expected == desired && expected == LifetimePolicy.PERMANENT)
+ {
+ return LifetimePolicy.PERMANENT;
+ }
+ throw new IllegalArgumentException("Cannot change lifetime policy of a user");
+
+ }
+
+ @Override
+ public <C extends ConfiguredObject> Collection<C> getChildren(final Class<C> clazz)
+ {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public Map<String, Object> getPreferences()
+ {
+ PreferencesProvider preferencesProvider = getPreferencesProvider();
+ if (preferencesProvider == null)
+ {
+ return null;
+ }
+ return preferencesProvider.getPreferences(this.getName());
+ }
+
+ @Override
+ public Object getPreference(String name)
+ {
+ Map<String, Object> preferences = getPreferences();
+ if (preferences == null)
+ {
+ return null;
+ }
+ return preferences.get(name);
+ }
+
+ @Override
+ public Map<String, Object> setPreferences(Map<String, Object> preferences)
+ {
+ PreferencesProvider preferencesProvider = getPreferencesProvider();
+ if (preferencesProvider == null)
+ {
+ return null;
+ }
+ return preferencesProvider.setPreferences(this.getName(), preferences);
+ }
+
+ @Override
+ public boolean deletePreferences()
+ {
+ PreferencesProvider preferencesProvider = getPreferencesProvider();
+ if (preferencesProvider == null)
+ {
+ return false;
+ }
+ String[] deleted = preferencesProvider.deletePreferences(this.getName());
+ return deleted.length == 1;
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return getAttributeNames(getClass());
+ }
+ }
+
+ @Override
+ public void recoverUser(final User user)
+ {
+ _users.put(user.getName(), (ScramAuthUser) user);
+ }
+
+ protected String createStoredPassword(final String password) throws SaslException
+ {
+ byte[] salt = new byte[32];
+ _random.nextBytes(salt);
+ byte[] passwordBytes = createSaltedPassword(salt, password);
+ return DatatypeConverter.printBase64Binary(salt) + "," + DatatypeConverter.printBase64Binary(passwordBytes);
+ }
+
+ @Override
+ public <C extends ConfiguredObject> C addChild(final Class<C> childClass,
+ final Map<String, Object> attributes,
+ final ConfiguredObject... otherParents)
+ {
+ if(childClass == User.class)
+ {
+ String username = (String) attributes.get("name");
+ String password = (String) attributes.get("password");
+ Principal p = new UsernamePrincipal(username);
+
+ if(createUser(username, password,null))
+ {
+ @SuppressWarnings("unchecked")
+ C principalAdapter = (C) _users.get(username);
+ return principalAdapter;
+ }
+ else
+ {
+ return null;
+
+ }
+ }
+ return super.addChild(childClass, attributes, otherParents);
+ }
+
+ public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz)
+ {
+ if(clazz == User.class)
+ {
+ return new ArrayList(_users.values());
+ }
+ else
+ {
+ return super.getChildren(clazz);
+ }
+ }
+
+ private class UserRecoverer implements ConfiguredObjectRecoverer<ScramAuthUser>
+ {
+ @Override
+ public ScramAuthUser create(final RecovererProvider recovererProvider,
+ final ConfigurationEntry entry,
+ final ConfiguredObject... parents)
+ {
+
+ Map<String,Object> attributes = new HashMap<String, Object>(entry.getAttributes());
+ attributes.put(User.ID,entry.getId());
+ return new ScramAuthUser(attributes);
+ }
+ }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerFactory.java
new file mode 100644
index 0000000000..dd6f77e474
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerFactory.java
@@ -0,0 +1,74 @@
+/*
+ * 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 org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.plugin.AuthenticationManagerFactory;
+import org.apache.qpid.server.util.ResourceBundleLoader;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+public class ScramSHA1AuthenticationManagerFactory implements AuthenticationManagerFactory
+{
+
+ public static final String PROVIDER_TYPE = "SCRAM-SHA1";
+
+ public static final String ATTRIBUTE_NAME = "name";
+
+ public static final Collection<String> ATTRIBUTES = Collections.<String> unmodifiableList(Arrays.asList(
+ AuthenticationProvider.TYPE
+ ));
+
+ @Override
+ public ScramSHA1AuthenticationManager createInstance(Broker broker,
+ Map<String, Object> attributes,
+ final boolean recovering)
+ {
+ if (attributes == null || !PROVIDER_TYPE.equals(attributes.get(AuthenticationProvider.TYPE)))
+ {
+ return null;
+ }
+
+
+ return new ScramSHA1AuthenticationManager(broker, Collections.<String,Object>emptyMap(),attributes, false);
+ }
+
+ @Override
+ public Collection<String> getAttributeNames()
+ {
+ return ATTRIBUTES;
+ }
+
+ @Override
+ public String getType()
+ {
+ return PROVIDER_TYPE;
+ }
+
+ @Override
+ public Map<String, String> getAttributeDescriptions()
+ {
+ return Collections.emptyMap();
+ }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSHA1SaslServer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSHA1SaslServer.java
new file mode 100644
index 0000000000..71ef386e3e
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSHA1SaslServer.java
@@ -0,0 +1,273 @@
+/*
+ *
+ * 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.sasl.scram;
+
+import org.apache.qpid.server.security.auth.manager.ScramSHA1AuthenticationManager;
+
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.xml.bind.DatatypeConverter;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.security.InvalidKeyException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.UUID;
+
+public class ScramSHA1SaslServer implements SaslServer
+{
+ public static final String MECHANISM = "SCRAM-SHA-1";
+
+ private static final Charset ASCII = Charset.forName("ASCII");
+
+ private final ScramSHA1AuthenticationManager _authManager;
+ private State _state = State.INITIAL;
+ private String _nonce;
+ private String _username;
+ private byte[] _gs2Header;
+ private String _serverFirstMessage;
+ private String _clientFirstMessageBare;
+ private byte[] _serverSignature;
+
+ public ScramSHA1SaslServer(final ScramSHA1AuthenticationManager authenticationManager)
+ {
+ _authManager = authenticationManager;
+ }
+
+ enum State
+ {
+ INITIAL,
+ SERVER_FIRST_MESSAGE_SENT,
+ COMPLETE
+ }
+
+ @Override
+ public String getMechanismName()
+ {
+ return MECHANISM;
+ }
+
+ @Override
+ public byte[] evaluateResponse(final byte[] response) throws SaslException
+ {
+ byte[] challenge;
+ switch (_state)
+ {
+ case INITIAL:
+ challenge = generateServerFirstMessage(response);
+ _state = State.SERVER_FIRST_MESSAGE_SENT;
+ break;
+ case SERVER_FIRST_MESSAGE_SENT:
+ challenge = generateServerFinalMessage(response);
+ _state = State.COMPLETE;
+ break;
+ default:
+ throw new SaslException("No response expected in state " + _state);
+
+ }
+ return challenge;
+ }
+
+ private byte[] generateServerFirstMessage(final byte[] response) throws SaslException
+ {
+ String clientFirstMessage = new String(response, ASCII);
+ if(!clientFirstMessage.startsWith("n"))
+ {
+ throw new SaslException("Cannot parse gs2-header");
+ }
+ String[] parts = clientFirstMessage.split(",");
+ if(parts.length < 4)
+ {
+ throw new SaslException("Cannot parse client first message");
+ }
+ _gs2Header = ("n,"+parts[1]+",").getBytes(ASCII);
+ _clientFirstMessageBare = clientFirstMessage.substring(_gs2Header.length);
+ if(!parts[2].startsWith("n="))
+ {
+ throw new SaslException("Cannot parse client first message");
+ }
+ _username = decodeUsername(parts[2].substring(2));
+ if(!parts[3].startsWith("r="))
+ {
+ throw new SaslException("Cannot parse client first message");
+ }
+ _nonce = parts[3].substring(2) + UUID.randomUUID().toString();
+
+ int count = _authManager.getIterationCount();
+ byte[] saltBytes = _authManager.getSalt(_username);
+ _serverFirstMessage = "r="+_nonce+",s="+ DatatypeConverter.printBase64Binary(saltBytes)+",i=" + count;
+ return _serverFirstMessage.getBytes(ASCII);
+ }
+
+ private String decodeUsername(String username) throws SaslException
+ {
+ if(username.contains("="))
+ {
+ String check = username;
+ while (check.contains("="))
+ {
+ check = check.substring(check.indexOf('=') + 1);
+ if (!(check.startsWith("2C") || check.startsWith("3D")))
+ {
+ throw new SaslException("Invalid username");
+ }
+ }
+ username = username.replace("=2C", ",");
+ username = username.replace("=3D","=");
+ }
+ return username;
+ }
+
+
+ private byte[] generateServerFinalMessage(final byte[] response) throws SaslException
+ {
+ try
+ {
+ String clientFinalMessage = new String(response, ASCII);
+ String[] parts = clientFinalMessage.split(",");
+ if(!parts[0].startsWith("c="))
+ {
+ throw new SaslException("Cannot parse client final message");
+ }
+ if(!Arrays.equals(_gs2Header,DatatypeConverter.parseBase64Binary(parts[0].substring(2))))
+ {
+ throw new SaslException("Client final message channel bind data invalid");
+ }
+ if(!parts[1].startsWith("r="))
+ {
+ throw new SaslException("Cannot parse client final message");
+ }
+ if(!parts[1].substring(2).equals(_nonce))
+ {
+ throw new SaslException("Client final message has incorrect nonce value");
+ }
+ if(!parts[parts.length-1].startsWith("p="))
+ {
+ throw new SaslException("Client final message does not have proof");
+ }
+
+ String clientFinalMessageWithoutProof = clientFinalMessage.substring(0,clientFinalMessage.length()-(1+parts[parts.length-1].length()));
+ byte[] proofBytes = DatatypeConverter.parseBase64Binary(parts[parts.length-1].substring(2));
+
+ String authMessage = _clientFirstMessageBare + "," + _serverFirstMessage + "," + clientFinalMessageWithoutProof;
+
+ byte[] saltedPassword = _authManager.getSaltedPassword(_username);
+
+ byte[] clientKey = computeHmacSHA1(saltedPassword, "Client Key");
+
+ byte[] storedKey = MessageDigest.getInstance("SHA1").digest(clientKey);
+
+ byte[] clientSignature = computeHmacSHA1(storedKey, authMessage);
+
+ byte[] clientProof = clientKey.clone();
+ for(int i = 0 ; i < clientProof.length; i++)
+ {
+ clientProof[i] ^= clientSignature[i];
+ }
+
+ if(!Arrays.equals(clientProof, proofBytes))
+ {
+ throw new SaslException("Authentication failed");
+ }
+ byte[] serverKey = computeHmacSHA1(saltedPassword, "Server Key");
+ String finalResponse = "v=" + DatatypeConverter.printBase64Binary(computeHmacSHA1(serverKey, authMessage));
+
+ return finalResponse.getBytes(ASCII);
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean isComplete()
+ {
+ return _state == State.COMPLETE;
+ }
+
+ @Override
+ public String getAuthorizationID()
+ {
+ return _username;
+ }
+
+ @Override
+ public byte[] unwrap(final byte[] incoming, final int offset, final int len) throws SaslException
+ {
+ throw new IllegalStateException("No security layer supported");
+ }
+
+ @Override
+ public byte[] wrap(final byte[] outgoing, final int offset, final int len) throws SaslException
+ {
+ throw new IllegalStateException("No security layer supported");
+ }
+
+ @Override
+ public Object getNegotiatedProperty(final String propName)
+ {
+ return null;
+ }
+
+ @Override
+ public void dispose() throws SaslException
+ {
+
+ }
+
+ private byte[] computeHmacSHA1(final byte[] key, final String string)
+ throws SaslException, UnsupportedEncodingException
+ {
+ Mac mac = createSha1Hmac(key);
+ mac.update(string.getBytes(ASCII));
+ return mac.doFinal();
+ }
+
+
+ private Mac createSha1Hmac(final byte[] keyBytes)
+ throws SaslException
+ {
+ try
+ {
+ SecretKeySpec key = new SecretKeySpec(keyBytes, "HmacSHA1");
+ Mac mac = Mac.getInstance("HmacSHA1");
+ mac.init(key);
+ return mac;
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ catch (InvalidKeyException e)
+ {
+ throw new SaslException(e.getMessage(), e);
+ }
+ }
+
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java
index dbe8bf22a0..da84580a94 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java
@@ -27,10 +27,9 @@ public abstract class AbstractDurableConfiguredObjectRecoverer<T> implements Dur
{
@Override
public void load(final DurableConfigurationRecoverer durableConfigurationRecoverer,
- final UUID id,
- final Map<String, Object> attributes)
+ final ConfiguredObjectRecord record)
{
- final UnresolvedObject obj = createUnresolvedObject(id, getType(), attributes);
+ final UnresolvedObject obj = createUnresolvedObject(record);
UnresolvedDependency[] dependencies = obj.getUnresolvedDependencies();
for(final UnresolvedDependency dependency : dependencies)
{
@@ -53,7 +52,7 @@ public abstract class AbstractDurableConfiguredObjectRecoverer<T> implements Dur
dependency.resolve(o);
if(obj.getUnresolvedDependencies().length == 0)
{
- durableConfigurationRecoverer.resolve(getType(), id, obj.resolve());
+ durableConfigurationRecoverer.resolve(getType(), record.getId(), obj.resolve());
}
}
});
@@ -61,17 +60,15 @@ public abstract class AbstractDurableConfiguredObjectRecoverer<T> implements Dur
}
if(obj.getUnresolvedDependencies().length == 0)
{
- durableConfigurationRecoverer.resolve(getType(), id, obj.resolve());
+ durableConfigurationRecoverer.resolve(getType(), record.getId(), obj.resolve());
}
else
{
- durableConfigurationRecoverer.addUnresolvedObject(getType(), id, obj);
+ durableConfigurationRecoverer.addUnresolvedObject(getType(), record.getId(), obj);
}
}
- public abstract UnresolvedObject<T> createUnresolvedObject(final UUID id,
- final String type,
- final Map<String, Object> attributes);
+ public abstract UnresolvedObject<T> createUnresolvedObject(final ConfiguredObjectRecord record);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
index a6424a3d28..ad3e685004 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java
@@ -24,6 +24,8 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
@@ -37,6 +39,8 @@ import java.sql.Types;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -49,6 +53,7 @@ import org.apache.qpid.server.message.EnqueueableMessage;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.plugin.MessageMetaDataType;
import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.transport.ConnectionOpen;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParseException;
@@ -71,20 +76,22 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
private static final String META_DATA_TABLE_NAME = "QPID_MESSAGE_METADATA";
private static final String MESSAGE_CONTENT_TABLE_NAME = "QPID_MESSAGE_CONTENT";
- private static final String LINKS_TABLE_NAME = "QPID_LINKS";
- private static final String BRIDGES_TABLE_NAME = "QPID_BRIDGES";
private static final String XID_TABLE_NAME = "QPID_XIDS";
private static final String XID_ACTIONS_TABLE_NAME = "QPID_XID_ACTIONS";
private static final String CONFIGURED_OBJECTS_TABLE_NAME = "QPID_CONFIGURED_OBJECTS";
+ private static final String CONFIGURED_OBJECT_HIERARCHY_TABLE_NAME = "QPID_CONFIGURED_OBJECT_HIERARCHY";
+
private static final int DEFAULT_CONFIG_VERSION = 0;
public static final Set<String> CONFIGURATION_STORE_TABLE_NAMES = new HashSet<String>(Arrays.asList(CONFIGURED_OBJECTS_TABLE_NAME, CONFIGURATION_VERSION_TABLE_NAME));
- public static final Set<String> MESSAGE_STORE_TABLE_NAMES = new HashSet<String>(Arrays.asList(DB_VERSION_TABLE_NAME, META_DATA_TABLE_NAME, MESSAGE_CONTENT_TABLE_NAME, QUEUE_ENTRY_TABLE_NAME, BRIDGES_TABLE_NAME, LINKS_TABLE_NAME, XID_TABLE_NAME, XID_ACTIONS_TABLE_NAME));
-
+ public static final Set<String> MESSAGE_STORE_TABLE_NAMES = new HashSet<String>(Arrays.asList(DB_VERSION_TABLE_NAME,
+ META_DATA_TABLE_NAME, MESSAGE_CONTENT_TABLE_NAME,
+ QUEUE_ENTRY_TABLE_NAME,
+ XID_TABLE_NAME, XID_ACTIONS_TABLE_NAME));
- private static final int DB_VERSION = 7;
+ private static final int DB_VERSION = 8;
private final AtomicLong _messageId = new AtomicLong(0);
@@ -116,34 +123,6 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
private static final String DELETE_FROM_META_DATA = "DELETE FROM " + META_DATA_TABLE_NAME + " WHERE message_id = ?";
private static final String SELECT_ALL_FROM_META_DATA = "SELECT message_id, meta_data FROM " + META_DATA_TABLE_NAME;
- private static final String SELECT_FROM_LINKS =
- "SELECT create_time, arguments FROM " + LINKS_TABLE_NAME + " WHERE id_lsb = ? and id_msb";
- private static final String DELETE_FROM_LINKS = "DELETE FROM " + LINKS_TABLE_NAME
- + " WHERE id_lsb = ? and id_msb = ?";
- private static final String SELECT_ALL_FROM_LINKS = "SELECT id_lsb, id_msb, create_time, "
- + "arguments FROM " + LINKS_TABLE_NAME;
- private static final String FIND_LINK = "SELECT id_lsb, id_msb FROM " + LINKS_TABLE_NAME + " WHERE id_lsb = ? and"
- + " id_msb = ?";
- private static final String INSERT_INTO_LINKS = "INSERT INTO " + LINKS_TABLE_NAME + "( id_lsb, "
- + "id_msb, create_time, arguments ) values (?, ?, ?, ?)";
- private static final String SELECT_FROM_BRIDGES =
- "SELECT create_time, link_id_lsb, link_id_msb, arguments FROM "
- + BRIDGES_TABLE_NAME + " WHERE id_lsb = ? and id_msb = ?";
- private static final String DELETE_FROM_BRIDGES = "DELETE FROM " + BRIDGES_TABLE_NAME
- + " WHERE id_lsb = ? and id_msb = ?";
- private static final String SELECT_ALL_FROM_BRIDGES = "SELECT id_lsb, id_msb, "
- + " create_time,"
- + " link_id_lsb, link_id_msb, "
- + "arguments FROM " + BRIDGES_TABLE_NAME
- + " WHERE link_id_lsb = ? and link_id_msb = ?";
- private static final String FIND_BRIDGE = "SELECT id_lsb, id_msb FROM " + BRIDGES_TABLE_NAME +
- " WHERE id_lsb = ? and id_msb = ?";
- private static final String INSERT_INTO_BRIDGES = "INSERT INTO " + BRIDGES_TABLE_NAME + "( id_lsb, id_msb, "
- + "create_time, "
- + "link_id_lsb, link_id_msb, "
- + "arguments )"
- + " values (?, ?, ?, ?, ?, ?)";
-
private static final String INSERT_INTO_XIDS =
"INSERT INTO "+ XID_TABLE_NAME +" ( format, global_id, branch_id ) values (?, ?, ?)";
private static final String DELETE_FROM_XIDS = "DELETE FROM " + XID_TABLE_NAME
@@ -167,6 +146,14 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
+ " where id = ?";
private static final String SELECT_FROM_CONFIGURED_OBJECTS = "SELECT id, object_type, attributes FROM " + CONFIGURED_OBJECTS_TABLE_NAME;
+
+ private static final String INSERT_INTO_CONFIGURED_OBJECT_HIERARCHY = "INSERT INTO " + CONFIGURED_OBJECT_HIERARCHY_TABLE_NAME
+ + " ( child_id, parent_type, parent_id) VALUES (?,?,?)";
+
+ private static final String DELETE_FROM_CONFIGURED_OBJECT_HIERARCHY = "DELETE FROM " + CONFIGURED_OBJECT_HIERARCHY_TABLE_NAME
+ + " where child_id = ?";
+ private static final String SELECT_FROM_CONFIGURED_OBJECT_HIERARCHY = "SELECT child_id, parent_type, parent_id FROM " + CONFIGURED_OBJECT_HIERARCHY_TABLE_NAME;
+
protected static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
@@ -198,6 +185,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
private StateManager _configurationStoreStateManager;
private boolean _initialized;
+
public AbstractJDBCMessageStore()
{
_messageStoreStateManager = new StateManager(_eventManager);
@@ -233,13 +221,13 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
@Override
- public void recoverConfigurationStore(ConfigurationRecoveryHandler recoveryHandler)
+ public void recoverConfigurationStore(ConfiguredObject<?> parent, ConfigurationRecoveryHandler recoveryHandler)
{
_configurationStoreStateManager.attainState(State.ACTIVATING);
-
try
{
createOrOpenConfigurationStoreDatabase();
+ upgradeIfVersionTableExists(parent);
recoveryHandler.beginConfigurationRecovery(this, getConfigVersion());
loadConfiguredObjects(recoveryHandler);
setConfigVersion(recoveryHandler.completeConfigurationRecovery());
@@ -251,6 +239,25 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
_configurationStoreStateManager.attainState(State.ACTIVE);
}
+ private void upgradeIfVersionTableExists(ConfiguredObject<?> parent)
+ throws SQLException {
+ Connection conn = newAutoCommitConnection();
+ try
+ {
+ if (tableExists(DB_VERSION_TABLE_NAME, conn))
+ {
+ upgradeIfNecessary(parent);
+ }
+ }
+ finally
+ {
+ if (conn != null)
+ {
+ conn.close();
+ }
+ }
+ }
+
@Override
public void openMessageStore(String virtualHostName, Map<String, Object> messageStoreSettings)
{
@@ -260,13 +267,13 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
@Override
- public void recoverMessageStore(MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
+ public void recoverMessageStore(ConfiguredObject<?> parent, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
{
_messageStoreStateManager.attainState(State.ACTIVATING);
try
{
createOrOpenMessageStoreDatabase();
- upgradeIfNecessary();
+ upgradeIfNecessary(parent);
}
catch (SQLException e)
{
@@ -302,7 +309,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
_messageStoreStateManager.attainState(State.ACTIVE);
}
- protected void upgradeIfNecessary() throws SQLException
+ protected void upgradeIfNecessary(ConfiguredObject<?> parent) throws SQLException
{
Connection conn = newAutoCommitConnection();
try
@@ -323,6 +330,8 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
{
case 6:
upgradeFromV6();
+ case 7:
+ upgradeFromV7(parent);
case DB_VERSION:
return;
default:
@@ -351,6 +360,135 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
updateDbVersion(7);
}
+
+ private void upgradeFromV7(ConfiguredObject<?> parent) throws SQLException
+ {
+ Connection connection = newConnection();
+ try
+ {
+ Map<UUID,Map<String,Object>> bindingsToUpdate = new HashMap<UUID, Map<String, Object>>();
+ List<UUID> others = new ArrayList<UUID>();
+ final ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.registerModule(_module);
+
+ PreparedStatement stmt = connection.prepareStatement(SELECT_FROM_CONFIGURED_OBJECTS);
+ try
+ {
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ while (rs.next())
+ {
+ UUID id = UUID.fromString(rs.getString(1));
+ String objectType = rs.getString(2);
+ Map<String,Object> attributes = objectMapper.readValue(getBlobAsString(rs, 3),Map.class);
+ if(objectType.endsWith("Binding"))
+ {
+ bindingsToUpdate.put(id,attributes);
+ }
+ else
+ {
+ others.add(id);
+ }
+ }
+ }
+ catch (JsonMappingException e)
+ {
+ throw new StoreException("Error recovering persistent state: " + e.getMessage(), e);
+ }
+ catch (JsonParseException e)
+ {
+ throw new StoreException("Error recovering persistent state: " + e.getMessage(), e);
+ }
+ catch (IOException e)
+ {
+ throw new StoreException("Error recovering persistent state: " + e.getMessage(), e);
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
+ stmt = connection.prepareStatement(INSERT_INTO_CONFIGURED_OBJECT_HIERARCHY);
+ try
+ {
+ for (UUID id : others)
+ {
+ stmt.setString(1, id.toString());
+ stmt.setString(2, "VirtualHost");
+ stmt.setString(3, parent.getId().toString());
+ stmt.execute();
+ }
+ for(Map.Entry<UUID, Map<String,Object>> bindingEntry : bindingsToUpdate.entrySet())
+ {
+ stmt.setString(1, bindingEntry.getKey().toString());
+ stmt.setString(2,"Queue");
+ stmt.setString(3, bindingEntry.getValue().remove("queue").toString());
+ stmt.execute();
+
+ stmt.setString(1, bindingEntry.getKey().toString());
+ stmt.setString(2,"Exchange");
+ stmt.setString(3, bindingEntry.getValue().remove("exchange").toString());
+ stmt.execute();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+ stmt = connection.prepareStatement(UPDATE_CONFIGURED_OBJECTS);
+ try
+ {
+ for(Map.Entry<UUID, Map<String,Object>> bindingEntry : bindingsToUpdate.entrySet())
+ {
+ stmt.setString(1, "Binding");
+ byte[] attributesAsBytes = objectMapper.writeValueAsBytes(bindingEntry.getValue());
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
+ stmt.setBinaryStream(2, bis, attributesAsBytes.length);
+ stmt.setString(3, bindingEntry.getKey().toString());
+ stmt.execute();
+ }
+ }
+ catch (JsonMappingException e)
+ {
+ throw new StoreException("Error recovering persistent state: " + e.getMessage(), e);
+ }
+ catch (JsonGenerationException e)
+ {
+ throw new StoreException("Error recovering persistent state: " + e.getMessage(), e);
+ }
+ catch (IOException e)
+ {
+ throw new StoreException("Error recovering persistent state: " + e.getMessage(), e);
+ }
+ finally
+ {
+ stmt.close();
+ }
+ stmt = connection.prepareStatement(UPDATE_DB_VERSION);
+ try
+ {
+ stmt.setInt(1, 8);
+ stmt.execute();
+ }
+ finally
+ {
+ stmt.close();
+ }
+ connection.commit();
+ }
+ finally
+ {
+ connection.close();
+ }
+ }
+
private void updateDbVersion(int newVersion) throws SQLException
{
Connection conn = newAutoCommitConnection();
@@ -392,8 +530,6 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
createQueueEntryTable(conn);
createMetaDataTable(conn);
createMessageContentTable(conn);
- createLinkTable(conn);
- createBridgeTable(conn);
createXidTable(conn);
createXidActionTable(conn);
conn.close();
@@ -405,6 +541,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
createConfigVersionTable(conn);
createConfiguredObjectsTable(conn);
+ createConfiguredObjectHierarchyTable(conn);
conn.close();
}
@@ -480,6 +617,23 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
}
+ private void createConfiguredObjectHierarchyTable(final Connection conn) throws SQLException
+ {
+ if(!tableExists(CONFIGURED_OBJECT_HIERARCHY_TABLE_NAME, conn))
+ {
+ Statement stmt = conn.createStatement();
+ try
+ {
+ stmt.execute("CREATE TABLE " + CONFIGURED_OBJECT_HIERARCHY_TABLE_NAME
+ + " ( child_id VARCHAR(36) not null, parent_type varchar(255), parent_id VARCHAR(36), PRIMARY KEY (child_id, parent_type))");
+ }
+ finally
+ {
+ stmt.close();
+ }
+ }
+ }
+
private void createQueueEntryTable(final Connection conn) throws SQLException
@@ -546,45 +700,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
- private void createLinkTable(final Connection conn) throws SQLException
- {
- if(!tableExists(LINKS_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute("CREATE TABLE "+ LINKS_TABLE_NAME +" ( id_lsb " + getSqlBigIntType() + " not null,"
- + " id_msb " + getSqlBigIntType() + " not null,"
- + " create_time " + getSqlBigIntType() + " not null,"
- + " arguments "+getSqlBlobType()+", PRIMARY KEY ( id_lsb, id_msb ))");
- }
- finally
- {
- stmt.close();
- }
- }
- }
- private void createBridgeTable(final Connection conn) throws SQLException
- {
- if(!tableExists(BRIDGES_TABLE_NAME, conn))
- {
- Statement stmt = conn.createStatement();
- try
- {
- stmt.execute("CREATE TABLE "+ BRIDGES_TABLE_NAME +" ( id_lsb " + getSqlBigIntType() + " not null,"
- + " id_msb " + getSqlBigIntType() + " not null,"
- + " create_time " + getSqlBigIntType() + " not null,"
- + " link_id_lsb " + getSqlBigIntType() + " not null,"
- + " link_id_msb " + getSqlBigIntType() + " not null,"
- + " arguments "+getSqlBlobType()+", PRIMARY KEY ( id_lsb, id_msb ))");
- }
- finally
- {
- stmt.close();
- }
- }
- }
private void createXidTable(final Connection conn) throws SQLException
{
@@ -826,38 +942,28 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
@Override
- public void create(UUID id, String type, Map<String,Object> attributes) throws StoreException
- {
- if (_configurationStoreStateManager.isInState(State.ACTIVE))
- {
- insertConfiguredObject(new ConfiguredObjectRecord(id, type, attributes));
- }
-
- }
-
- @Override
- public void remove(UUID id, String type) throws StoreException
- {
- int results = removeConfiguredObject(id);
- if (results == 0)
- {
- throw new StoreException(type + " with id " + id + " not found");
- }
- }
-
- @Override
- public void update(UUID id, String type, Map<String, Object> attributes) throws StoreException
+ public void create(ConfiguredObjectRecord object) throws StoreException
{
if (_configurationStoreStateManager.isInState(State.ACTIVE))
{
- ConfiguredObjectRecord queueConfiguredObject = loadConfiguredObject(id);
- if (queueConfiguredObject != null)
+ try
{
- ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(id, type, attributes);
- updateConfiguredObject(newQueueRecord);
+ Connection conn = newConnection();
+ try
+ {
+ insertConfiguredObject(object, conn);
+ conn.commit();
+ }
+ finally
+ {
+ conn.close();
+ }
+ }
+ catch (SQLException e)
+ {
+ throw new StoreException("Error creating ConfiguredObject " + object);
}
}
-
}
/**
@@ -1997,66 +2103,65 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
_eventManager.addEventListener(eventListener, events);
}
- private void insertConfiguredObject(ConfiguredObjectRecord configuredObject) throws StoreException
+ private void insertConfiguredObject(ConfiguredObjectRecord configuredObject, final Connection conn) throws StoreException
{
if (_configurationStoreStateManager.isInState(State.ACTIVE))
{
try
{
- Connection conn = newAutoCommitConnection();
+ PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
try
{
- PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
+ stmt.setString(1, configuredObject.getId().toString());
+ ResultSet rs = stmt.executeQuery();
+ boolean exists;
try
{
- stmt.setString(1, configuredObject.getId().toString());
- ResultSet rs = stmt.executeQuery();
+ exists = rs.next();
+
+ }
+ finally
+ {
+ rs.close();
+ }
+ // If we don't have any data in the result set then we can add this configured object
+ if (!exists)
+ {
+ PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_CONFIGURED_OBJECTS);
try
{
- // If we don't have any data in the result set then we can add this configured object
- if (!rs.next())
+ insertStmt.setString(1, configuredObject.getId().toString());
+ insertStmt.setString(2, configuredObject.getType());
+ if(configuredObject.getAttributes() == null)
{
- PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_CONFIGURED_OBJECTS);
- try
- {
- insertStmt.setString(1, configuredObject.getId().toString());
- insertStmt.setString(2, configuredObject.getType());
- if(configuredObject.getAttributes() == null)
- {
- insertStmt.setNull(3, Types.BLOB);
- }
- else
- {
- final Map<String, Object> attributes = configuredObject.getAttributes();
- final ObjectMapper objectMapper = new ObjectMapper();
- objectMapper.registerModule(_module);
- byte[] attributesAsBytes = objectMapper.writeValueAsBytes(attributes);
-
- ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
- insertStmt.setBinaryStream(3, bis, attributesAsBytes.length);
- }
- insertStmt.execute();
- }
- finally
- {
- insertStmt.close();
- }
+ insertStmt.setNull(3, Types.BLOB);
}
+ else
+ {
+ final Map<String, Object> attributes = configuredObject.getAttributes();
+ final ObjectMapper objectMapper = new ObjectMapper();
+ objectMapper.registerModule(_module);
+ byte[] attributesAsBytes = objectMapper.writeValueAsBytes(attributes);
+
+ ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes);
+ insertStmt.setBinaryStream(3, bis, attributesAsBytes.length);
+ }
+ insertStmt.execute();
}
finally
{
- rs.close();
+ insertStmt.close();
}
+
+ writeHierarchy(configuredObject, conn);
}
- finally
- {
- stmt.close();
- }
+
}
finally
{
- conn.close();
+ stmt.close();
}
+
}
catch (JsonMappingException e)
{
@@ -2075,31 +2180,11 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
throw new StoreException("Error inserting of configured object " + configuredObject + " into database: " + e.getMessage(), e);
}
}
- }
- private int removeConfiguredObject(UUID id) throws StoreException
- {
- int results = 0;
- try
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- results = removeConfiguredObject(id, conn);
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new StoreException("Error deleting of configured object with id " + id + " from database: " + e.getMessage(), e);
- }
- return results;
}
- public UUID[] removeConfiguredObjects(UUID... objects) throws StoreException
+ @Override
+ public UUID[] remove(ConfiguredObjectRecord... objects) throws StoreException
{
Collection<UUID> removed = new ArrayList<UUID>(objects.length);
try
@@ -2108,11 +2193,11 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
Connection conn = newAutoCommitConnection();
try
{
- for(UUID id : objects)
+ for(ConfiguredObjectRecord record : objects)
{
- if(removeConfiguredObject(id, conn) != 0)
+ if(removeConfiguredObject(record.getId(), conn) != 0)
{
- removed.add(id);
+ removed.add(record.getId());
}
}
}
@@ -2130,7 +2215,8 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
private int removeConfiguredObject(final UUID id, final Connection conn) throws SQLException
{
- final int results;PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_CONFIGURED_OBJECTS);
+ final int results;
+ PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_CONFIGURED_OBJECTS);
try
{
stmt.setString(1, id.toString());
@@ -2140,30 +2226,18 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
{
stmt.close();
}
- return results;
- }
-
- private void updateConfiguredObject(final ConfiguredObjectRecord configuredObject) throws StoreException
- {
- if (_configurationStoreStateManager.isInState(State.ACTIVE))
+ stmt = conn.prepareStatement(DELETE_FROM_CONFIGURED_OBJECT_HIERARCHY);
+ try
{
- try
- {
- Connection conn = newAutoCommitConnection();
- try
- {
- updateConfiguredObject(configuredObject, false, conn);
- }
- finally
- {
- conn.close();
- }
- }
- catch (SQLException e)
- {
- throw new StoreException("Error updating configured object " + configuredObject + " in database: " + e.getMessage(), e);
- }
+ stmt.setString(1, id.toString());
+ stmt.executeUpdate();
+ }
+ finally
+ {
+ stmt.close();
}
+
+ return results;
}
public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException
@@ -2258,6 +2332,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
{
insertStmt.close();
}
+ writeHierarchy(configuredObject, conn);
}
}
finally
@@ -2284,72 +2359,31 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
- private ConfiguredObjectRecord loadConfiguredObject(final UUID id) throws StoreException
+ private void writeHierarchy(final ConfiguredObjectRecord configuredObject, final Connection conn) throws SQLException, StoreException
{
- ConfiguredObjectRecord result = null;
+ PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_CONFIGURED_OBJECT_HIERARCHY);
try
{
- Connection conn = newAutoCommitConnection();
- try
+ for(Map.Entry<String,ConfiguredObjectRecord> parentEntry : configuredObject.getParents().entrySet())
{
- PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT);
- try
- {
- stmt.setString(1, id.toString());
- ResultSet rs = stmt.executeQuery();
- try
- {
- if (rs.next())
- {
- String type = rs.getString(1);
- String attributes = getBlobAsString(rs, 2);
- result = new ConfiguredObjectRecord(id, type,
- (new ObjectMapper()).readValue(attributes,Map.class));
- }
- }
- finally
- {
- rs.close();
- }
- }
- finally
- {
- stmt.close();
- }
- }
- finally
- {
- conn.close();
+ insertStmt.setString(1, configuredObject.getId().toString());
+ insertStmt.setString(2, parentEntry.getKey());
+ insertStmt.setString(3, parentEntry.getValue().getId().toString());
+
+ insertStmt.execute();
}
}
- catch (JsonMappingException e)
- {
- throw new StoreException("Error loading of configured object with id " + id + " from database: "
- + e.getMessage(), e);
- }
- catch (JsonParseException e)
- {
- throw new StoreException("Error loading of configured object with id " + id + " from database: "
- + e.getMessage(), e);
- }
- catch (IOException e)
- {
- throw new StoreException("Error loading of configured object with id " + id + " from database: "
- + e.getMessage(), e);
- }
- catch (SQLException e)
+ finally
{
- throw new StoreException("Error loading of configured object with id " + id + " from database: "
- + e.getMessage(), e);
+ insertStmt.close();
}
- return result;
}
private void loadConfiguredObjects(ConfigurationRecoveryHandler recoveryHandler) throws SQLException,
StoreException
{
Connection conn = newAutoCommitConnection();
-
+ Map<UUID, ConfiguredObjectRecordImpl> configuredObjects = new HashMap<UUID, ConfiguredObjectRecordImpl>();
final ObjectMapper objectMapper = new ObjectMapper();
try
{
@@ -2364,8 +2398,11 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
String id = rs.getString(1);
String objectType = rs.getString(2);
String attributes = getBlobAsString(rs, 3);
- recoveryHandler.configuredObject(UUID.fromString(id), objectType,
- objectMapper.readValue(attributes,Map.class));
+ final ConfiguredObjectRecordImpl configuredObjectRecord =
+ new ConfiguredObjectRecordImpl(UUID.fromString(id), objectType,
+ objectMapper.readValue(attributes, Map.class));
+ configuredObjects.put(configuredObjectRecord.getId(),configuredObjectRecord);
+
}
}
catch (JsonMappingException e)
@@ -2389,11 +2426,53 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
{
stmt.close();
}
+ stmt = conn.prepareStatement(SELECT_FROM_CONFIGURED_OBJECT_HIERARCHY);
+ try
+ {
+ ResultSet rs = stmt.executeQuery();
+ try
+ {
+ while (rs.next())
+ {
+ UUID childId = UUID.fromString(rs.getString(1));
+ String parentType = rs.getString(2);
+ UUID parentId = UUID.fromString(rs.getString(3));
+
+ ConfiguredObjectRecordImpl child = configuredObjects.get(childId);
+ ConfiguredObjectRecordImpl parent = configuredObjects.get(parentId);
+
+ if(child != null && parent != null)
+ {
+ child.addParent(parentType, parent);
+ }
+ else if(child != null && child.getType().endsWith("Binding") && parentType.equals("Exchange"))
+ {
+ // TODO - remove this hack for amq. exchanges
+ child.addParent(parentType, new ConfiguredObjectRecordImpl(parentId, parentType, Collections.<String,Object>emptyMap()));
+ }
+
+ }
+ }
+ finally
+ {
+ rs.close();
+ }
+ }
+ finally
+ {
+ stmt.close();
+ }
+
}
finally
{
conn.close();
}
+
+ for(ConfiguredObjectRecord record : configuredObjects.values())
+ {
+ recoveryHandler.configuredObject(record);
+ }
}
protected abstract String getBlobAsString(ResultSet rs, int col) throws SQLException;
@@ -2441,4 +2520,51 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC
}
}
+
+ private static final class ConfiguredObjectRecordImpl implements ConfiguredObjectRecord
+ {
+
+ private final UUID _id;
+ private final String _type;
+ private final Map<String, Object> _attributes;
+ private final Map<String, ConfiguredObjectRecord> _parents = new HashMap<String, ConfiguredObjectRecord>();
+
+ private ConfiguredObjectRecordImpl(final UUID id,
+ final String type,
+ final Map<String, Object> attributes)
+ {
+ _id = id;
+ _type = type;
+ _attributes = Collections.unmodifiableMap(attributes);
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ @Override
+ public String getType()
+ {
+ return _type;
+ }
+
+ private void addParent(String parentType, ConfiguredObjectRecord parent)
+ {
+ _parents.put(parentType, parent);
+ }
+
+ @Override
+ public Map<String, Object> getAttributes()
+ {
+ return _attributes;
+ }
+
+ @Override
+ public Map<String, ConfiguredObjectRecord> getParents()
+ {
+ return Collections.unmodifiableMap(_parents);
+ }
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java
index afdeb257e0..bf538e4592 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java
@@ -24,6 +24,7 @@ import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.model.ConfiguredObject;
/** A simple message store that stores the messages in a thread-safe structure in memory. */
abstract public class AbstractMemoryMessageStore extends NullMessageStore
@@ -83,7 +84,7 @@ abstract public class AbstractMemoryMessageStore extends NullMessageStore
}
@Override
- public void recoverConfigurationStore(ConfigurationRecoveryHandler recoveryHandler)
+ public void recoverConfigurationStore(ConfiguredObject<?> parent, ConfigurationRecoveryHandler recoveryHandler)
{
}
@@ -96,7 +97,7 @@ abstract public class AbstractMemoryMessageStore extends NullMessageStore
}
@Override
- public void recoverMessageStore(MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
+ public void recoverMessageStore(ConfiguredObject<?> parent, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
{
_stateManager.attainState(State.ACTIVATING);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
index c6ebe90802..c8aef92a95 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java
@@ -27,7 +27,7 @@ public interface ConfigurationRecoveryHandler
{
void beginConfigurationRecovery(DurableConfigurationStore store, int configVersion);
- void configuredObject(UUID id, String type, Map<String, Object> attributes);
+ void configuredObject(ConfiguredObjectRecord object);
/**
*
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java
index 44490385d9..99f8f0f04a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java
@@ -20,69 +20,16 @@
*/
package org.apache.qpid.server.store;
-import java.util.Collections;
-import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
-public class ConfiguredObjectRecord
+public interface ConfiguredObjectRecord
{
- private UUID _id;
- private String _type;
- private Map<String,Object> _attributes;
+ UUID getId();
- public ConfiguredObjectRecord(UUID id, String type, Map<String,Object> attributes)
- {
- super();
- _id = id;
- _type = type;
- _attributes = Collections.unmodifiableMap(new LinkedHashMap<String,Object>(attributes));
- }
+ String getType();
- public UUID getId()
- {
- return _id;
- }
+ Map<String,Object> getAttributes();
- public String getType()
- {
- return _type;
- }
-
- public Map<String,Object> getAttributes()
- {
- return _attributes;
- }
-
- @Override
- public String toString()
- {
- return "ConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + "]";
- }
-
- @Override
- public boolean equals(Object o)
- {
- if(this == o)
- {
- return true;
- }
- if(o == null || getClass() != o.getClass())
- {
- return false;
- }
-
- ConfiguredObjectRecord that = (ConfiguredObjectRecord) o;
-
- return _type.equals(that._type) && _id.equals(that._id) && _attributes.equals(that._attributes);
- }
-
- @Override
- public int hashCode()
- {
- int result = _id.hashCode();
- result = 31 * result + _type.hashCode();
- result = 31 * result + _attributes.hashCode();
- return result;
- }
+ Map<String, ConfiguredObjectRecord> getParents();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java
new file mode 100644
index 0000000000..ed553aa823
--- /dev/null
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordImpl.java
@@ -0,0 +1,104 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.store;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class ConfiguredObjectRecordImpl implements ConfiguredObjectRecord
+{
+ private UUID _id;
+ private String _type;
+ private final Map<String,Object> _attributes;
+ private final Map<String,ConfiguredObjectRecord> _parents;
+
+ public ConfiguredObjectRecordImpl(UUID id, String type, Map<String, Object> attributes)
+ {
+ this(id,type,attributes,Collections.<String,ConfiguredObjectRecord>emptyMap());
+ }
+
+ public ConfiguredObjectRecordImpl(UUID id, String type, Map<String, Object> attributes, Map<String,ConfiguredObjectRecord> parents)
+ {
+ super();
+ _id = id;
+ _type = type;
+ _attributes = Collections.unmodifiableMap(new LinkedHashMap<String,Object>(attributes));
+ _parents = Collections.unmodifiableMap(new LinkedHashMap<String, ConfiguredObjectRecord>(parents));
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ @Override
+ public String getType()
+ {
+ return _type;
+ }
+
+ @Override
+ public Map<String,Object> getAttributes()
+ {
+ return _attributes;
+ }
+
+ @Override
+ public Map<String, ConfiguredObjectRecord> getParents()
+ {
+ return _parents;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + "]";
+ }
+
+ @Override
+ public boolean equals(Object o)
+ {
+ if(this == o)
+ {
+ return true;
+ }
+ if(o == null || getClass() != o.getClass())
+ {
+ return false;
+ }
+
+ ConfiguredObjectRecordImpl that = (ConfiguredObjectRecordImpl) o;
+
+ return _type.equals(that._type) && _id.equals(that._id) && _attributes.equals(that._attributes);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ int result = _id.hashCode();
+ result = 31 * result + _type.hashCode();
+ result = 31 * result + _attributes.hashCode();
+ return result;
+ }
+}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java
index 6696426c0e..f8d8ecdd7c 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java
@@ -23,6 +23,7 @@ package org.apache.qpid.server.store;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -76,19 +77,19 @@ public class DurableConfigurationRecoverer implements ConfigurationRecoveryHandl
}
@Override
- public void configuredObject(final UUID id, final String type, final Map<String, Object> attributes)
+ public void configuredObject(ConfiguredObjectRecord record)
{
- _upgrader.configuredObject(id, type, attributes);
+ _upgrader.configuredObject(record);
}
- void onConfiguredObject(final UUID id, final String type, final Map<String, Object> attributes)
+ void onConfiguredObject(ConfiguredObjectRecord record)
{
- DurableConfiguredObjectRecoverer recoverer = getRecoverer(type);
+ DurableConfiguredObjectRecoverer recoverer = getRecoverer(record.getType());
if(recoverer == null)
{
- throw new IllegalConfigurationException("Unknown type for configured object: " + type);
+ throw new IllegalConfigurationException("Unknown type for configured object: " + record.getType());
}
- recoverer.load(this, id, attributes);
+ recoverer.load(this, record);
}
private DurableConfiguredObjectRecoverer getRecoverer(final String type)
@@ -111,19 +112,12 @@ public class DurableConfigurationRecoverer implements ConfigurationRecoveryHandl
private void applyUpgrade()
{
- final Collection<ConfiguredObjectRecord> updates = new ArrayList<ConfiguredObjectRecord>();
- final Collection<UUID> deletes = new ArrayList<UUID>();
- for(Map.Entry<UUID,ConfiguredObjectRecord> entry : _upgrader.getUpdatedRecords().entrySet())
- {
- if(entry.getValue() != null)
- {
- updates.add(entry.getValue());
- }
- else
- {
- deletes.add(entry.getKey());
- }
- }
+ final Collection<ConfiguredObjectRecord> updates = new HashSet<ConfiguredObjectRecord>(_upgrader.getUpdatedRecords().values());
+ final Collection<ConfiguredObjectRecord> deletes = new HashSet<ConfiguredObjectRecord>(_upgrader.getDeletedRecords().values());
+
+ // Due to the way the upgraders work it is possible that the updates list may contain nulls
+ updates.remove(null);
+ deletes.remove(null);
if(!updates.isEmpty())
{
@@ -131,7 +125,7 @@ public class DurableConfigurationRecoverer implements ConfigurationRecoveryHandl
}
if(!deletes.isEmpty())
{
- _store.removeConfiguredObjects(deletes.toArray(new UUID[deletes.size()]));
+ _store.remove(deletes.toArray(new ConfiguredObjectRecord[deletes.size()]));
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java
index 10e56f1f71..918a9b0134 100755
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java
@@ -23,6 +23,8 @@ package org.apache.qpid.server.store;
import java.util.Map;
import java.util.UUID;
+import org.apache.qpid.server.model.ConfiguredObject;
+
public interface DurableConfigurationStore
{
String STORE_TYPE = "storeType";
@@ -43,48 +45,40 @@ public interface DurableConfigurationStore
/**
* Recovers configuration from the store using given recovery handler
- *
+ * @param parent parent
* @param recoveryHandler recovery handler
*/
- void recoverConfigurationStore(ConfigurationRecoveryHandler recoveryHandler) throws StoreException;
+ void recoverConfigurationStore(ConfiguredObject<?> parent, ConfigurationRecoveryHandler recoveryHandler) throws StoreException;
/**
* Makes the specified object persistent.
*
- * @param id The id of the object to persist.
- * @param type The type of the object to persist
- * @param attributes the attributes of the object to persist
+ * @param object The object to persist.
*
* @throws StoreException If the operation fails for any reason.
*/
- void create(UUID id, String type, Map<String, Object> attributes) throws StoreException;
+ void create(ConfiguredObjectRecord object) throws StoreException;
/**
- * Removes the specified persistent configured object.
+ * Removes the specified persistent configured objects.
*
- * @param id The id of the object to remove.
- * @param type The type of the object to remove
+ * @param objects The objects to remove.
*
* @throws StoreException If the operation fails for any reason.
*/
- void remove(UUID id, String type) throws StoreException;
-
- public UUID[] removeConfiguredObjects(UUID... objects) throws StoreException;
+ public UUID[] remove(ConfiguredObjectRecord... objects) throws StoreException;
/**
- * Updates the specified object in the persistent store, IF it is already present. If the object
- * is not present in the store, it will not be added.
+ * Updates the specified objects in the persistent store, IF it is already present. If the object
+ * is not present in the store, it will only be added if createIfNecessary is set to true, otherwise an exception
+ * will be thrown.
*
- * @param id The id of the object to update.
- * @param type The type of the object to update
- * @param attributes the updated attributes
+ * @param createIfNecessary if false then will fail if the object does not exist.
+ * @param records the records to update
*
* @throws StoreException If the operation fails for any reason.
*/
- void update(UUID id, String type, Map<String, Object> attributes) throws StoreException;
-
-
void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException;
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java
index f914389b0e..9410006d65 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java
@@ -20,12 +20,8 @@
*/
package org.apache.qpid.server.store;
-import java.security.PrivilegedAction;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
@@ -35,12 +31,8 @@ import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.model.Binding;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Exchange;
-import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.security.*;
-
-import javax.security.auth.Subject;
public class DurableConfigurationStoreHelper
{
@@ -58,7 +50,7 @@ public class DurableConfigurationStoreHelper
{
attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId());
}
- store.update(queue.getId(), QUEUE, attributesMap);
+ store.update(false, new ConfiguredObjectRecordImpl(queue.getId(), QUEUE, attributesMap));
}
public static void createQueue(DurableConfigurationStore store, AMQQueue<?> queue)
@@ -71,49 +63,33 @@ public class DurableConfigurationStoreHelper
attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId());
}
- store.create(queue.getId(), QUEUE, attributesMap);
+ store.create(new ConfiguredObjectRecordImpl(queue.getId(), QUEUE, attributesMap));
}
public static void removeQueue(DurableConfigurationStore store, AMQQueue queue)
{
- store.remove(queue.getId(), QUEUE);
+ store.remove(queue.asObjectRecord());
}
public static void createExchange(DurableConfigurationStore store, ExchangeImpl exchange)
{
- Map<String, Object> attributesMap = exchange.getActualAttributes();
- attributesMap.remove(ConfiguredObject.ID);
-
- store.create(exchange.getId(), EXCHANGE, attributesMap);
-
+ store.create(exchange.asObjectRecord());
}
-
public static void removeExchange(DurableConfigurationStore store, ExchangeImpl exchange)
{
- store.remove(exchange.getId(), EXCHANGE);
+ store.remove(exchange.asObjectRecord());
}
public static void createBinding(DurableConfigurationStore store, final BindingImpl binding)
{
- Map<String, Object> attributesMap = binding.getActualAttributes();
- attributesMap.remove(ConfiguredObject.ID);
- if(!attributesMap.containsKey(Binding.EXCHANGE))
- {
- attributesMap.put(Binding.EXCHANGE, binding.getExchange());
- }
- if(!attributesMap.containsKey(Binding.QUEUE))
- {
- attributesMap.put(Binding.QUEUE, binding.getQueue());
- }
-
- store.create(binding.getId(), BINDING, attributesMap);
+ store.create(binding.asObjectRecord());
}
public static void removeBinding(DurableConfigurationStore store, BindingImpl binding)
{
- store.remove(binding.getId(), BINDING);
+ store.remove(binding.asObjectRecord());
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreUpgrader.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreUpgrader.java
index 1d3e4cc672..45b2ff56d7 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreUpgrader.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreUpgrader.java
@@ -25,11 +25,12 @@ import java.util.UUID;
public interface DurableConfigurationStoreUpgrader
{
- void configuredObject(UUID id, String type, Map<String, Object> attributes);
+ void configuredObject(ConfiguredObjectRecord record);
void complete();
void setNextUpgrader(DurableConfigurationStoreUpgrader upgrader);
Map<UUID, ConfiguredObjectRecord> getUpdatedRecords();
+ Map<UUID, ConfiguredObjectRecord> getDeletedRecords();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java
index e065728bd3..4c618f5089 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java
@@ -26,8 +26,7 @@ import java.util.UUID;
public interface DurableConfiguredObjectRecoverer
{
public void load(final DurableConfigurationRecoverer durableConfigurationRecoverer,
- final UUID id,
- final Map<String, Object> attributes);
+ final ConfiguredObjectRecord record);
public String getType();
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
index a1512bbc22..97559c8286 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
@@ -26,22 +26,22 @@ import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
+import java.util.*;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Model;
import org.apache.qpid.server.model.VirtualHost;
+import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.JsonProcessingException;
+import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.JsonSerializer;
+import org.codehaus.jackson.map.Module;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
+import org.codehaus.jackson.map.SerializerProvider;
+import org.codehaus.jackson.map.module.SimpleModule;
public class JsonFileConfigStore implements DurableConfigurationStore
{
@@ -61,8 +61,30 @@ public class JsonFileConfigStore implements DurableConfigurationStore
private String _backupFileName;
private int _configVersion;
+ private static final Module _module;
+ static
+ {
+ SimpleModule module= new SimpleModule("ConfiguredObjectSerializer", new Version(1,0,0,null));
+
+ final JsonSerializer<ConfiguredObject> serializer = new JsonSerializer<ConfiguredObject>()
+ {
+ @Override
+ public void serialize(final ConfiguredObject value,
+ final JsonGenerator jgen,
+ final SerializerProvider provider)
+ throws IOException, JsonProcessingException
+ {
+ jgen.writeString(value.getId().toString());
+ }
+ };
+ module.addSerializer(ConfiguredObject.class, serializer);
+
+ _module = module;
+ }
+
public JsonFileConfigStore()
{
+ _objectMapper.registerModule(_module);
_objectMapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
}
@@ -76,13 +98,13 @@ public class JsonFileConfigStore implements DurableConfigurationStore
}
@Override
- public void recoverConfigurationStore(ConfigurationRecoveryHandler recoveryHandler)
+ public void recoverConfigurationStore(ConfiguredObject<?> parent, ConfigurationRecoveryHandler recoveryHandler)
{
recoveryHandler.beginConfigurationRecovery(this,_configVersion);
List<ConfiguredObjectRecord> records = new ArrayList<ConfiguredObjectRecord>(_objectsById.values());
for(ConfiguredObjectRecord record : records)
{
- recoveryHandler.configuredObject(record.getId(), record.getType(), record.getAttributes());
+ recoveryHandler.configuredObject(record);
}
int oldConfigVersion = _configVersion;
_configVersion = recoveryHandler.completeConfigurationRecovery();
@@ -287,20 +309,21 @@ public class JsonFileConfigStore implements DurableConfigurationStore
}
}
+ Map<String,UUID> parentMap = new HashMap<String, UUID>();
if(parentId != null)
{
- data.put(parentClass.getSimpleName().toLowerCase(),parentId);
+ parentMap.put(parentClass.getSimpleName(),parentId);
for(Class<? extends ConfiguredObject> otherParent : MODEL.getParentTypes(clazz))
{
if(otherParent != parentClass)
{
final String otherParentAttr = otherParent.getSimpleName().toLowerCase();
- Object otherParentId = data.get(otherParentAttr);
+ Object otherParentId = data.remove(otherParentAttr);
if(otherParentId instanceof String)
{
try
{
- data.put(otherParentAttr, UUID.fromString((String) otherParentId));
+ parentMap.put(otherParent.getSimpleName(), UUID.fromString((String) otherParentId));
}
catch(IllegalArgumentException e)
{
@@ -312,7 +335,7 @@ public class JsonFileConfigStore implements DurableConfigurationStore
}
}
- _objectsById.put(id, new ConfiguredObjectRecord(id, type, data));
+ _objectsById.put(id, new ConfiguredObjectRecordImpl(id, type, data, parentMap));
List<UUID> idsForType = _idsByType.get(type);
if(idsForType == null)
{
@@ -324,28 +347,27 @@ public class JsonFileConfigStore implements DurableConfigurationStore
}
@Override
- public synchronized void create(final UUID id, final String type, final Map<String, Object> attributes) throws
- StoreException
+ public synchronized void create(ConfiguredObjectRecord record) throws StoreException
{
- if(_objectsById.containsKey(id))
+ if(_objectsById.containsKey(record.getId()))
{
- throw new StoreException("Object with id " + id + " already exists");
+ throw new StoreException("Object with id " + record.getId() + " already exists");
}
- else if(!CLASS_NAME_MAPPING.containsKey(type))
+ else if(!CLASS_NAME_MAPPING.containsKey(record.getType()))
{
- throw new StoreException("Cannot create object of unknown type " + type);
+ throw new StoreException("Cannot create object of unknown type " + record.getType());
}
else
{
- ConfiguredObjectRecord record = new ConfiguredObjectRecord(id, type, attributes);
- _objectsById.put(id, record);
- List<UUID> idsForType = _idsByType.get(type);
+
+ _objectsById.put(record.getId(), record);
+ List<UUID> idsForType = _idsByType.get(record.getType());
if(idsForType == null)
{
idsForType = new ArrayList<UUID>();
- _idsByType.put(type, idsForType);
+ _idsByType.put(record.getType(), idsForType);
}
- idsForType.add(id);
+ idsForType.add(record.getId());
save();
}
}
@@ -400,7 +422,21 @@ public class JsonFileConfigStore implements DurableConfigurationStore
Map<String,Object> map = new LinkedHashMap<String, Object>();
map.put("id", id);
map.putAll(record.getAttributes());
- map.remove(MODEL.getParentTypes(type).iterator().next().getSimpleName().toLowerCase());
+
+ Collection<Class<? extends ConfiguredObject>> parentTypes = MODEL.getParentTypes(type);
+ if(parentTypes.size() > 1)
+ {
+ Iterator<Class<? extends ConfiguredObject>> iter = parentTypes.iterator();
+ // skip the first parent, which is given by structure
+ iter.next();
+ // for all other parents add a fake attribute with name being the parent type in lower case, and the value
+ // being the parents id
+ while(iter.hasNext())
+ {
+ String parentType = iter.next().getSimpleName();
+ map.put(parentType.toLowerCase(), record.getParents().get(parentType).getId());
+ }
+ }
Collection<Class<? extends ConfiguredObject>> childClasses =
new ArrayList<Class<? extends ConfiguredObject>>(MODEL.getChildTypes(type));
@@ -418,8 +454,10 @@ public class JsonFileConfigStore implements DurableConfigurationStore
for(UUID childId : childIds)
{
ConfiguredObjectRecord childRecord = _objectsById.get(childId);
- final String parentArg = type.getSimpleName().toLowerCase();
- if(id.toString().equals(String.valueOf(childRecord.getAttributes().get(parentArg))))
+
+ final ConfiguredObjectRecord parent = childRecord.getParents().get(type.getSimpleName());
+ String parentId = parent.getId().toString();
+ if(id.toString().equals(parentId))
{
entities.add(build(childClass,childId));
}
@@ -436,34 +474,22 @@ public class JsonFileConfigStore implements DurableConfigurationStore
}
@Override
- public void remove(final UUID id, final String type) throws StoreException
- {
- removeConfiguredObjects(id);
- }
-
- @Override
- public synchronized UUID[] removeConfiguredObjects(final UUID... objects) throws StoreException
+ public synchronized UUID[] remove(final ConfiguredObjectRecord... objects) throws StoreException
{
List<UUID> removedIds = new ArrayList<UUID>();
- for(UUID id : objects)
+ for(ConfiguredObjectRecord requestedRecord : objects)
{
- ConfiguredObjectRecord record = _objectsById.remove(id);
+ ConfiguredObjectRecord record = _objectsById.remove(requestedRecord.getId());
if(record != null)
{
- removedIds.add(id);
- _idsByType.get(record.getType()).remove(id);
+ removedIds.add(record.getId());
+ _idsByType.get(record.getType()).remove(record.getId());
}
}
save();
return removedIds.toArray(new UUID[removedIds.size()]);
}
- @Override
- public void update(final UUID id, final String type, final Map<String, Object> attributes) throws
- StoreException
- {
- update(false, new ConfiguredObjectRecord(id, type, attributes));
- }
@Override
public void update(final boolean createIfNecessary, final ConfiguredObjectRecord... records)
@@ -554,5 +580,59 @@ public class JsonFileConfigStore implements DurableConfigurationStore
return map;
}
+ private class ConfiguredObjectRecordImpl implements ConfiguredObjectRecord
+ {
+
+ private final UUID _id;
+ private final String _type;
+ private final Map<String, Object> _attributes;
+ private final Map<String, UUID> _parents;
+
+ private ConfiguredObjectRecordImpl(final UUID id, final String type, final Map<String, Object> attributes,
+ final Map<String, UUID> parents)
+ {
+ _id = id;
+ _type = type;
+ _attributes = attributes;
+ _parents = parents;
+ }
+
+ @Override
+ public UUID getId()
+ {
+ return _id;
+ }
+
+ @Override
+ public String getType()
+ {
+ return _type;
+ }
+
+ @Override
+ public Map<String, Object> getAttributes()
+ {
+ return _attributes;
+ }
+
+ @Override
+ public Map<String, ConfiguredObjectRecord> getParents()
+ {
+ Map<String,ConfiguredObjectRecord> parents = new HashMap<String, ConfiguredObjectRecord>();
+ for(Map.Entry<String,UUID> entry : _parents.entrySet())
+ {
+ ConfiguredObjectRecord value = _objectsById.get(entry.getValue());
+
+ if(value == null && entry.getKey().equals("Exchange"))
+ {
+ // TODO - remove this hack for the defined exchanges
+ value = new ConfiguredObjectRecordImpl(entry.getValue(),entry.getKey(),Collections.<String,Object>emptyMap(), Collections.<String,UUID>emptyMap());
+ }
+
+ parents.put(entry.getKey(), value);
+ }
+ return parents;
+ }
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java
index fb99191477..7fb6c4df48 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java
@@ -22,6 +22,8 @@ package org.apache.qpid.server.store;
import java.util.Map;
+import org.apache.qpid.server.model.ConfiguredObject;
+
/**
* MessageStore defines the interface to a storage area, which can be used to preserve the state of messages.
*
@@ -43,11 +45,11 @@ public interface MessageStore
/**
* Called after opening to recover messages and transactions with given recovery handlers
- *
+ * @param parent TODO
* @param messageRecoveryHandler
* @param transactionLogRecoveryHandler
*/
- void recoverMessageStore(MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler);
+ void recoverMessageStore(ConfiguredObject<?> parent, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler);
public <T extends StorableMessageMetaData> StoredMessage<T> addMessage(T metaData);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NonNullUpgrader.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NonNullUpgrader.java
index a671e93b26..1abd3de34a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NonNullUpgrader.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NonNullUpgrader.java
@@ -28,6 +28,7 @@ public abstract class NonNullUpgrader implements DurableConfigurationStoreUpgrad
{
private DurableConfigurationStoreUpgrader _nextUpgrader;
private final Map<UUID, ConfiguredObjectRecord> _updates = new HashMap<UUID, ConfiguredObjectRecord>();
+ private final Map<UUID, ConfiguredObjectRecord> _deletes = new HashMap<UUID, ConfiguredObjectRecord>();
public final void setNextUpgrader(final DurableConfigurationStoreUpgrader upgrader)
{
@@ -50,6 +51,10 @@ public abstract class NonNullUpgrader implements DurableConfigurationStoreUpgrad
{
return _updates;
}
+ protected Map<UUID, ConfiguredObjectRecord> getDeleteMap()
+ {
+ return _deletes;
+ }
@Override
public final Map<UUID, ConfiguredObjectRecord> getUpdatedRecords()
@@ -59,4 +64,11 @@ public abstract class NonNullUpgrader implements DurableConfigurationStoreUpgrad
return updates;
}
+ @Override
+ public final Map<UUID, ConfiguredObjectRecord> getDeletedRecords()
+ {
+ final Map<UUID, ConfiguredObjectRecord> deletes = new HashMap<UUID, ConfiguredObjectRecord>(_deletes);
+ deletes.putAll(_nextUpgrader.getDeletedRecords());
+ return deletes;
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
index c095675602..66c3fe6cae 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
@@ -22,6 +22,8 @@ package org.apache.qpid.server.store;
import java.util.Map;
import java.util.UUID;
+import org.apache.qpid.server.model.ConfiguredObject;
+
public abstract class NullMessageStore implements MessageStore, DurableConfigurationStore
{
@Override
@@ -30,12 +32,7 @@ public abstract class NullMessageStore implements MessageStore, DurableConfigura
}
@Override
- public void recoverConfigurationStore(ConfigurationRecoveryHandler recoveryHandler)
- {
- }
-
- @Override
- public void update(UUID id, String type, Map<String, Object> attributes)
+ public void recoverConfigurationStore(ConfiguredObject<?> parent, ConfigurationRecoveryHandler recoveryHandler)
{
}
@@ -44,20 +41,19 @@ public abstract class NullMessageStore implements MessageStore, DurableConfigura
{
}
-
- @Override
- public void remove(UUID id, String type)
- {
- }
-
@Override
- public UUID[] removeConfiguredObjects(final UUID... objects)
+ public UUID[] remove(final ConfiguredObjectRecord... objects)
{
- return objects;
+ final UUID[] removed = new UUID[objects.length];
+ for(int i = 0; i < objects.length; i++)
+ {
+ removed[i] = objects[i].getId();
+ }
+ return removed;
}
@Override
- public void create(UUID id, String type, Map<String, Object> attributes)
+ public void create(ConfiguredObjectRecord record)
{
}
@@ -95,7 +91,7 @@ public abstract class NullMessageStore implements MessageStore, DurableConfigura
}
@Override
- public void recoverMessageStore(MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
+ public void recoverMessageStore(ConfiguredObject<?> parent, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
{
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java
index c8a812fa89..b17dd4a6f3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java
@@ -34,9 +34,9 @@ public final class NullUpgrader implements DurableConfigurationStoreUpgrader
}
@Override
- public void configuredObject(final UUID id, final String type, final Map<String, Object> attributes)
+ public void configuredObject(final ConfiguredObjectRecord record)
{
- _durableConfigurationRecoverer.onConfiguredObject(id, type, attributes);
+ _durableConfigurationRecoverer.onConfiguredObject(record);
}
@Override
@@ -55,4 +55,10 @@ public final class NullUpgrader implements DurableConfigurationStoreUpgrader
{
return Collections.emptyMap();
}
+
+ @Override
+ public Map<UUID, ConfiguredObjectRecord> getDeletedRecords()
+ {
+ return Collections.emptyMap();
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index a14b1ad8c1..e41ee051f3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -137,7 +137,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg
_eventLogger.message(VirtualHostMessages.CREATED(_name));
- _securityManager = new SecurityManager(parentSecurityManager, virtualHost.getSecurityAcl(), _name);
+ _securityManager = parentSecurityManager;
_connectionRegistry = new ConnectionRegistry();
_connectionRegistry.addRegistryChangeListener(this);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java
index e6577e04e4..58721ea8b2 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java
@@ -28,9 +28,11 @@ import org.apache.log4j.Logger;
import org.apache.qpid.server.binding.BindingImpl;
import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.store.AbstractDurableConfiguredObjectRecoverer;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.UnresolvedDependency;
import org.apache.qpid.server.store.UnresolvedObject;
@@ -49,11 +51,9 @@ public class BindingRecoverer extends AbstractDurableConfiguredObjectRecoverer<B
}
@Override
- public UnresolvedObject<BindingImpl> createUnresolvedObject(final UUID id,
- final String type,
- final Map<String, Object> attributes)
+ public UnresolvedObject<BindingImpl> createUnresolvedObject(ConfiguredObjectRecord record)
{
- return new UnresolvedBinding(id, attributes);
+ return new UnresolvedBinding(record);
}
@Override
@@ -76,12 +76,11 @@ public class BindingRecoverer extends AbstractDurableConfiguredObjectRecoverer<B
private ExchangeImpl _exchange;
private AMQQueue _queue;
- public UnresolvedBinding(final UUID id,
- final Map<String, Object> attributeMap)
+ public UnresolvedBinding(final ConfiguredObjectRecord record)
{
- _bindingId = id;
- _exchangeId = UUID.fromString(String.valueOf(attributeMap.get(org.apache.qpid.server.model.Binding.EXCHANGE)));
- _queueId = UUID.fromString(String.valueOf(attributeMap.get(org.apache.qpid.server.model.Binding.QUEUE)));
+ _bindingId = record.getId();
+ _exchangeId = record.getParents().get(Exchange.class.getSimpleName()).getId();
+ _queueId = record.getParents().get(Queue.class.getSimpleName()).getId();
_exchange = _exchangeRegistry.getExchange(_exchangeId);
if(_exchange == null)
{
@@ -93,8 +92,8 @@ public class BindingRecoverer extends AbstractDurableConfiguredObjectRecoverer<B
_unresolvedDependencies.add(new QueueDependency());
}
- _bindingName = (String) attributeMap.get(org.apache.qpid.server.model.Binding.NAME);
- _bindingArgumentsMap = (Map<String, Object>) attributeMap.get(org.apache.qpid.server.model.Binding.ARGUMENTS);
+ _bindingName = (String) record.getAttributes().get(org.apache.qpid.server.model.Binding.NAME);
+ _bindingArgumentsMap = (Map<String, Object>) record.getAttributes().get(org.apache.qpid.server.model.Binding.ARGUMENTS);
}
@Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java
index 2d824cbd2d..f6fa6344d3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java
@@ -39,6 +39,7 @@ import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.queue.QueueArgumentsConverter;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
import org.apache.qpid.server.store.DurableConfigurationRecoverer;
import org.apache.qpid.server.store.DurableConfigurationStoreUpgrader;
import org.apache.qpid.server.store.NonNullUpgrader;
@@ -133,9 +134,9 @@ public class DefaultUpgraderProvider implements UpgraderProvider
}
@Override
- public void configuredObject(final UUID id, final String type, Map<String, Object> attributes)
+ public void configuredObject(final ConfiguredObjectRecord record)
{
- _records.put(id, new ConfiguredObjectRecord(id, type, attributes));
+ _records.put(record.getId(), record);
}
private void removeSelectorArguments(Map<String, Object> binding)
@@ -147,9 +148,9 @@ public class DefaultUpgraderProvider implements UpgraderProvider
binding.put(Binding.ARGUMENTS, arguments);
}
- private boolean isTopicExchange(Map<String, Object> binding)
+ private boolean isTopicExchange(ConfiguredObjectRecord entry)
{
- UUID exchangeId = UUID.fromString((String)binding.get(Binding.EXCHANGE));
+ UUID exchangeId = entry.getParents().get("Exchange").getId();
if(_records.containsKey(exchangeId))
{
@@ -188,17 +189,17 @@ public class DefaultUpgraderProvider implements UpgraderProvider
String type = record.getType();
Map<String, Object> attributes = record.getAttributes();
UUID id = record.getId();
- if(type.equals(Binding.class.getName()) && hasSelectorArguments(attributes) && !isTopicExchange(attributes))
+ if(type.equals(Binding.class.getName()) && hasSelectorArguments(attributes) && !isTopicExchange(record))
{
attributes = new LinkedHashMap<String, Object>(attributes);
removeSelectorArguments(attributes);
- record = new ConfiguredObjectRecord(id, type, attributes);
+ record = new ConfiguredObjectRecordImpl(id, type, attributes, record.getParents());
getUpdateMap().put(id, record);
entry.setValue(record);
}
- getNextUpgrader().configuredObject(id, type, attributes);
+ getNextUpgrader().configuredObject(record);
}
getNextUpgrader().complete();
@@ -212,12 +213,14 @@ public class DefaultUpgraderProvider implements UpgraderProvider
*/
private class Version1Upgrader extends NonNullUpgrader
{
+
+
@Override
- public void configuredObject(final UUID id, String type, final Map<String, Object> attributes)
+ public void configuredObject(final ConfiguredObjectRecord record)
{
- type = type.substring(1+type.lastIndexOf('.'));
- getUpdateMap().put(id, new ConfiguredObjectRecord(id, type, attributes));
-
+ String type = record.getType().substring(1 + record.getType().lastIndexOf('.'));
+ getUpdateMap().put(record.getId(),
+ new ConfiguredObjectRecordImpl(record.getId(), type, record.getAttributes(), record.getParents()));
}
@Override
@@ -226,22 +229,24 @@ public class DefaultUpgraderProvider implements UpgraderProvider
for(Map.Entry<UUID, ConfiguredObjectRecord> entry : getUpdateMap().entrySet())
{
final ConfiguredObjectRecord record = entry.getValue();
- if(isBinding(record.getType()) && (unknownExchange((String) record.getAttributes().get(Binding.EXCHANGE))
- || unknownQueue((String) record.getAttributes().get(Binding.QUEUE))))
+ final ConfiguredObjectRecord exchangeParent = record.getParents().get(Exchange.class.getSimpleName());
+ final ConfiguredObjectRecord queueParent = record.getParents().get(Queue.class.getSimpleName());
+ if(isBinding(record.getType()) && (exchangeParent == null || unknownExchange(exchangeParent.getId())
+ || queueParent == null || unknownQueue(queueParent.getId())))
{
+ getDeleteMap().put(entry.getKey(), entry.getValue());
entry.setValue(null);
}
else
{
- getNextUpgrader().configuredObject(record.getId(), record.getType(), record.getAttributes());
+ getNextUpgrader().configuredObject(record);
}
}
getNextUpgrader().complete();
}
- private boolean unknownExchange(final String exchangeIdString)
+ private boolean unknownExchange(final UUID exchangeId)
{
- UUID exchangeId = UUID.fromString(exchangeIdString);
if (_defaultExchangeIds.containsValue(exchangeId))
{
return false;
@@ -251,9 +256,8 @@ public class DefaultUpgraderProvider implements UpgraderProvider
|| _exchangeRegistry.getExchange(exchangeId) != null);
}
- private boolean unknownQueue(final String queueIdString)
+ private boolean unknownQueue(final UUID queueId)
{
- UUID queueId = UUID.fromString(queueIdString);
ConfiguredObjectRecord localRecord = getUpdateMap().get(queueId);
return !((localRecord != null && localRecord.getType().equals(Queue.class.getSimpleName()))
|| _virtualHost.getQueue(queueId) != null);
@@ -277,22 +281,24 @@ public class DefaultUpgraderProvider implements UpgraderProvider
private static final String ARGUMENTS = "arguments";
@Override
- public void configuredObject(UUID id, String type, Map<String, Object> attributes)
+ public void configuredObject(ConfiguredObjectRecord record)
{
- if(Queue.class.getSimpleName().equals(type))
+
+ if(Queue.class.getSimpleName().equals(record.getType()))
{
Map<String, Object> newAttributes = new LinkedHashMap<String, Object>();
- if(attributes.get(ARGUMENTS) instanceof Map)
+ if(record.getAttributes().get(ARGUMENTS) instanceof Map)
{
- newAttributes.putAll(QueueArgumentsConverter.convertWireArgsToModel((Map<String, Object>) attributes
+ newAttributes.putAll(QueueArgumentsConverter.convertWireArgsToModel((Map<String, Object>) record.getAttributes()
.get(ARGUMENTS)));
}
- newAttributes.putAll(attributes);
- attributes = newAttributes;
- getUpdateMap().put(id, new ConfiguredObjectRecord(id,type,attributes));
+ newAttributes.putAll(record.getAttributes());
+
+ record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), newAttributes, record.getParents());
+ getUpdateMap().put(record.getId(), record);
}
- getNextUpgrader().configuredObject(id,type,attributes);
+ getNextUpgrader().configuredObject(record);
}
@Override
@@ -311,16 +317,17 @@ public class DefaultUpgraderProvider implements UpgraderProvider
{
@Override
- public void configuredObject(UUID id, String type, Map<String, Object> attributes)
+ public void configuredObject(ConfiguredObjectRecord record)
{
- if(Queue.class.getSimpleName().equals(type))
+
+ if(Queue.class.getSimpleName().equals(record.getType()))
{
- Map<String, Object> newAttributes = new LinkedHashMap<String, Object>(attributes);
- if(attributes.get(EXCLUSIVE) instanceof Boolean)
+ Map<String, Object> newAttributes = new LinkedHashMap<String, Object>(record.getAttributes());
+ if(record.getAttributes().get(EXCLUSIVE) instanceof Boolean)
{
- boolean isExclusive = (Boolean) attributes.get(EXCLUSIVE);
+ boolean isExclusive = (Boolean) record.getAttributes().get(EXCLUSIVE);
newAttributes.put(EXCLUSIVE, isExclusive ? "CONTAINER" : "NONE");
- if(!isExclusive && attributes.containsKey("owner"))
+ if(!isExclusive && record.getAttributes().containsKey("owner"))
{
newAttributes.remove("owner");
}
@@ -329,15 +336,16 @@ public class DefaultUpgraderProvider implements UpgraderProvider
{
newAttributes.remove("owner");
}
- if(!attributes.containsKey("durable"))
+ if(!record.getAttributes().containsKey("durable"))
{
newAttributes.put("durable","true");
}
- attributes = newAttributes;
- getUpdateMap().put(id, new ConfiguredObjectRecord(id,type,attributes));
+
+ record = new ConfiguredObjectRecordImpl(record.getId(),record.getType(),newAttributes, record.getParents());
+ getUpdateMap().put(record.getId(), record);
}
- getNextUpgrader().configuredObject(id,type,attributes);
+ getNextUpgrader().configuredObject(record);
}
@Override
@@ -352,15 +360,16 @@ public class DefaultUpgraderProvider implements UpgraderProvider
private Map<String, String> _missingAmqpExchanges = new HashMap<String, String>(DEFAULT_EXCHANGES);
@Override
- public void configuredObject(UUID id, String type, Map<String, Object> attributes)
+ public void configuredObject(ConfiguredObjectRecord record)
{
- if(Exchange.class.getSimpleName().equals(type))
+ if(Exchange.class.getSimpleName().equals(record.getType()))
{
+ Map<String, Object> attributes = record.getAttributes();
String name = (String)attributes.get(NAME);
_missingAmqpExchanges.remove(name);
}
- getNextUpgrader().configuredObject(id,type,attributes);
+ getNextUpgrader().configuredObject(record);
}
@Override
@@ -383,9 +392,11 @@ public class DefaultUpgraderProvider implements UpgraderProvider
attributes.put(org.apache.qpid.server.model.Exchange.DURABLE, true);
- getUpdateMap().put(id, new ConfiguredObjectRecord(id, Exchange.class.getSimpleName(), attributes));
+ ConfiguredObjectRecord virtualHostRecord = new ConfiguredObjectRecordImpl(_virtualHost.getId(), org.apache.qpid.server.model.VirtualHost.class.getSimpleName(), Collections.<String, Object>emptyMap());
+ ConfiguredObjectRecord record = new ConfiguredObjectRecordImpl(id, Exchange.class.getSimpleName(), attributes, Collections.singletonMap(virtualHostRecord.getType(), virtualHostRecord));
+ getUpdateMap().put(id, record);
- getNextUpgrader().configuredObject(id, Exchange.class.getSimpleName(), attributes);
+ getNextUpgrader().configuredObject(record);
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java
index 2743b0ef59..4431fc786d 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java
@@ -28,6 +28,7 @@ import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.exchange.ExchangeFactory;
import org.apache.qpid.server.exchange.ExchangeRegistry;
import org.apache.qpid.server.store.AbstractDurableConfiguredObjectRecoverer;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.UnresolvedDependency;
import org.apache.qpid.server.store.UnresolvedObject;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
@@ -50,11 +51,9 @@ public class ExchangeRecoverer extends AbstractDurableConfiguredObjectRecoverer<
}
@Override
- public UnresolvedObject<ExchangeImpl> createUnresolvedObject(final UUID id,
- final String type,
- final Map<String, Object> attributes)
+ public UnresolvedObject<ExchangeImpl> createUnresolvedObject(final ConfiguredObjectRecord record)
{
- return new UnresolvedExchange(id, attributes);
+ return new UnresolvedExchange(record.getId(), record.getAttributes());
}
private class UnresolvedExchange implements UnresolvedObject<ExchangeImpl>
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java
index 385f4e219e..eb1bc883ca 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java
@@ -32,6 +32,7 @@ import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.QueueFactory;
import org.apache.qpid.server.store.AbstractDurableConfiguredObjectRecoverer;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
import org.apache.qpid.server.store.UnresolvedDependency;
import org.apache.qpid.server.store.UnresolvedObject;
@@ -58,11 +59,9 @@ public class QueueRecoverer extends AbstractDurableConfiguredObjectRecoverer<AMQ
}
@Override
- public UnresolvedObject<AMQQueue> createUnresolvedObject(final UUID id,
- final String type,
- final Map<String, Object> attributes)
+ public UnresolvedObject<AMQQueue> createUnresolvedObject(final ConfiguredObjectRecord record)
{
- return new UnresolvedQueue(id, type, attributes);
+ return new UnresolvedQueue(record.getId(), record.getAttributes());
}
private class UnresolvedQueue implements UnresolvedObject<AMQQueue>
@@ -75,7 +74,6 @@ public class QueueRecoverer extends AbstractDurableConfiguredObjectRecoverer<AMQ
private ExchangeImpl _alternateExchange;
public UnresolvedQueue(final UUID id,
- final String type,
final Map<String, Object> attributes)
{
_attributes = attributes;
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java
index 58a0e689cb..bb3f8fc012 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java
@@ -96,13 +96,13 @@ public class StandardVirtualHost extends AbstractVirtualHost
_messageStore.openMessageStore(virtualHost.getName(), virtualHost.getMessageStoreSettings());
- _durableConfigurationStore.recoverConfigurationStore(configRecoverer);
+ _durableConfigurationStore.recoverConfigurationStore(getModel(), configRecoverer);
// If store does not have entries for standard exchanges (amq.*), the following will create them.
initialiseModel();
VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this);
- _messageStore.recoverMessageStore(recoveryHandler, recoveryHandler);
+ _messageStore.recoverMessageStore(getModel(), recoveryHandler, recoveryHandler);
attainActivation();
}
diff --git a/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory b/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory
index 8ff67030ef..a1139b386c 100644
--- a/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory
+++ b/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AuthenticationManagerFactory
@@ -22,3 +22,5 @@ org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManagerFactor
org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManagerFactory
org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory
org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManagerFactory
+org.apache.qpid.server.security.auth.manager.ScramSHA1AuthenticationManagerFactory
+
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java
index c23c4715e8..c5786fb981 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java
@@ -63,7 +63,9 @@ public class StoreConfigurationChangeListenerTest extends QpidTestCase
{
notifyBrokerStarted();
Broker broker = mock(Broker.class);
+ when(broker.getCategoryClass()).thenReturn(Broker.class);
VirtualHost child = mock(VirtualHost.class);
+ when(child.getCategoryClass()).thenReturn(VirtualHost.class);
_listener.childAdded(broker, child);
verify(_store).save(any(ConfigurationEntry.class), any(ConfigurationEntry.class));
}
@@ -72,7 +74,9 @@ public class StoreConfigurationChangeListenerTest extends QpidTestCase
{
notifyBrokerStarted();
Broker broker = mock(Broker.class);
+ when(broker.getCategoryClass()).thenReturn(Broker.class);
VirtualHost child = mock(VirtualHost.class);
+ when(child.getCategoryClass()).thenReturn(VirtualHost.class);
_listener.childRemoved(broker, child);
verify(_store).save(any(ConfigurationEntry.class));
}
@@ -81,6 +85,7 @@ public class StoreConfigurationChangeListenerTest extends QpidTestCase
{
notifyBrokerStarted();
Broker broker = mock(Broker.class);
+ when(broker.getCategoryClass()).thenReturn(Broker.class);
_listener.attributeSet(broker, Broker.QUEUE_FLOW_CONTROL_SIZE_BYTES, null, 1);
verify(_store).save(any(ConfigurationEntry.class));
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
new file mode 100644
index 0000000000..e27981d22c
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/SecurityManagerTest.java
@@ -0,0 +1,571 @@
+/*
+ *
+ * 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;
+
+import static org.apache.qpid.server.security.access.ObjectType.BROKER;
+import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE;
+import static org.apache.qpid.server.security.access.Operation.ACCESS_LOGS;
+import static org.apache.qpid.server.security.access.Operation.PUBLISH;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.security.AccessControlException;
+
+import org.apache.qpid.server.binding.BindingImpl;
+import org.apache.qpid.server.consumer.ConsumerImpl;
+import org.apache.qpid.server.exchange.ExchangeImpl;
+import org.apache.qpid.server.model.AccessControlProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.security.access.ObjectProperties;
+import org.apache.qpid.server.security.access.ObjectProperties.Property;
+import org.apache.qpid.server.security.access.ObjectType;
+import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.access.OperationLoggingDetails;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class SecurityManagerTest extends QpidTestCase
+{
+ private static final String TEST_EXCHANGE_TYPE = "testExchangeType";
+ private static final String TEST_VIRTUAL_HOST = "testVirtualHost";
+ private static final String TEST_EXCHANGE = "testExchange";
+ private static final String TEST_QUEUE = "testQueue";
+
+ private AccessControl _accessControl;
+ private SecurityManager _securityManager;
+ private VirtualHost<?> _virtualHost;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _accessControl = mock(AccessControl.class);
+ _virtualHost = mock(VirtualHost.class);
+
+ AccessControlProvider<?> aclProvider = mock(AccessControlProvider.class);
+ when(aclProvider.getAccessControl()).thenReturn(_accessControl);
+
+ when(_virtualHost.getName()).thenReturn(TEST_VIRTUAL_HOST);
+
+ _securityManager = new SecurityManager(mock(Broker.class), false);
+ _securityManager.stateChanged(aclProvider, State.INITIALISING, State.ACTIVE);
+ }
+
+ public void testAuthoriseCreateBinding()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+ when(queue.isDurable()).thenReturn(true);
+ when(queue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT);
+
+ BindingImpl binding = mock(BindingImpl.class);
+ when(binding.getExchange()).thenReturn(exchange);
+ when(binding.getAMQQueue()).thenReturn(queue);
+ when(binding.getBindingKey()).thenReturn("bindingKey");
+
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_EXCHANGE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.QUEUE_NAME, TEST_QUEUE);
+ properties.put(Property.ROUTING_KEY, "bindingKey");
+ properties.put(Property.TEMPORARY, false);
+ properties.put(Property.DURABLE, true);
+
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateBinding(binding);
+ verify(_accessControl).authorise(eq(Operation.BIND), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateBinding(binding);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.BIND), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+
+ public void testAuthoriseMethod()
+ {
+ ObjectProperties properties = new ObjectProperties("testMethod");
+ properties.put(ObjectProperties.Property.COMPONENT, "testComponent");
+ properties.put(ObjectProperties.Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseMethod(Operation.UPDATE, "testComponent", "testMethod", TEST_VIRTUAL_HOST);
+ verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.METHOD), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseMethod(Operation.UPDATE, "testComponent", "testMethod", TEST_VIRTUAL_HOST);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.UPDATE), eq(ObjectType.METHOD), eq(properties));
+ }
+
+ public void testAccessManagement()
+ {
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.accessManagement();
+ verify(_accessControl).authorise(Operation.ACCESS, ObjectType.MANAGEMENT, ObjectProperties.EMPTY);
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.accessManagement();
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(Operation.ACCESS, ObjectType.MANAGEMENT, ObjectProperties.EMPTY);
+ }
+
+ public void testAuthoriseCreateConnection()
+ {
+ AMQConnectionModel<?,?> connection = mock(AMQConnectionModel.class);
+ when(connection.getVirtualHostName()).thenReturn(TEST_VIRTUAL_HOST);
+
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateConnection(connection);
+ verify(_accessControl).authorise(eq(Operation.ACCESS), eq(ObjectType.VIRTUALHOST), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateConnection(connection);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.ACCESS), eq(ObjectType.VIRTUALHOST), eq(properties));
+ }
+
+ public void testAuthoriseCreateConsumer()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+ when(queue.isDurable()).thenReturn(true);
+ when(queue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT);
+
+ ConsumerImpl consumer = mock(ConsumerImpl.class);
+ when(consumer.getMessageSource()).thenReturn(queue);
+
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_QUEUE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.AUTO_DELETE, false);
+ properties.put(Property.TEMPORARY, false);
+ properties.put(Property.DURABLE, true);
+ properties.put(Property.EXCLUSIVE, false);
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateConsumer(consumer);
+ verify(_accessControl).authorise(eq(Operation.CONSUME), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateConsumer(consumer);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CONSUME), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+ public void testAuthoriseCreateExchange()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+ when(exchange.getTypeName()).thenReturn(TEST_EXCHANGE_TYPE);
+
+ ObjectProperties properties = createExpectedExchangeObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateExchange(exchange);
+ verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateExchange(exchange);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthoriseCreateQueue()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+
+ ObjectProperties properties = createExpectedQueueObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseCreateQueue(queue);
+ verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseCreateQueue(queue);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+ public void testAuthoriseDeleteQueue()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+
+ ObjectProperties properties = createExpectedQueueObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseDelete(queue);
+ verify(_accessControl).authorise(eq(Operation.DELETE), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseDelete(queue);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.DELETE), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+ public void testAuthoriseUpdateQueue()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+
+ ObjectProperties properties = createExpectedQueueObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseUpdate(queue);
+ verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseUpdate(queue);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.UPDATE), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+ public void testAuthoriseUpdateExchange()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+ when(exchange.getTypeName()).thenReturn(TEST_EXCHANGE_TYPE);
+
+ ObjectProperties properties = createExpectedExchangeObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseUpdate(exchange);
+ verify(_accessControl).authorise(eq(Operation.UPDATE), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseUpdate(exchange);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.UPDATE), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthoriseDeleteExchange()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+ when(exchange.getTypeName()).thenReturn(TEST_EXCHANGE_TYPE);
+
+ ObjectProperties properties = createExpectedExchangeObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseDelete(exchange);
+ verify(_accessControl).authorise(eq(Operation.DELETE), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseDelete(exchange);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.DELETE), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthoriseGroupOperation()
+ {
+ ObjectProperties properties = new ObjectProperties("testGroup");
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseGroupOperation(Operation.CREATE, "testGroup");
+ verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.GROUP), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseGroupOperation(Operation.CREATE, "testGroup");
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.GROUP), eq(properties));
+ }
+
+ public void testAuthoriseUserOperation()
+ {
+ ObjectProperties properties = new ObjectProperties("testUser");
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseUserOperation(Operation.CREATE, "testUser");
+ verify(_accessControl).authorise(eq(Operation.CREATE), eq(ObjectType.USER), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseUserOperation(Operation.CREATE, "testUser");
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.CREATE), eq(ObjectType.USER), eq(properties));
+ }
+
+ public void testAuthorisePublish()
+ {
+ String routingKey = "routingKey";
+ String exchangeName = "exchangeName";
+ boolean immediate = true;
+ ObjectProperties properties = new ObjectProperties(TEST_VIRTUAL_HOST, exchangeName, routingKey, immediate);
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authorisePublish(immediate, routingKey, exchangeName, TEST_VIRTUAL_HOST);
+ verify(_accessControl).authorise(eq(Operation.PUBLISH), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authorisePublish(immediate, routingKey, exchangeName, TEST_VIRTUAL_HOST);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.PUBLISH), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthorisePurge()
+ {
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+
+ ObjectProperties properties = createExpectedQueueObjectProperties();
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authorisePurge(queue);
+ verify(_accessControl).authorise(eq(Operation.PURGE), eq(ObjectType.QUEUE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authorisePurge(queue);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.PURGE), eq(ObjectType.QUEUE), eq(properties));
+ }
+
+
+ public void testAuthoriseUnbind()
+ {
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getName()).thenReturn(TEST_EXCHANGE);
+
+ AMQQueue<?> queue = mock(AMQQueue.class);
+ when(queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(queue.getName()).thenReturn(TEST_QUEUE);
+ when(queue.isDurable()).thenReturn(true);
+ when(queue.getLifetimePolicy()).thenReturn(LifetimePolicy.PERMANENT);
+
+ BindingImpl binding = mock(BindingImpl.class);
+ when(binding.getExchange()).thenReturn(exchange);
+ when(binding.getAMQQueue()).thenReturn(queue);
+ when(binding.getBindingKey()).thenReturn("bindingKey");
+
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_EXCHANGE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.QUEUE_NAME, TEST_QUEUE);
+ properties.put(Property.ROUTING_KEY, "bindingKey");
+ properties.put(Property.TEMPORARY, false);
+ properties.put(Property.DURABLE, true);
+
+
+ configureAccessPlugin(Result.ALLOWED);
+ _securityManager.authoriseUnbind(binding);
+ verify(_accessControl).authorise(eq(Operation.UNBIND), eq(ObjectType.EXCHANGE), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ try
+ {
+ _securityManager.authoriseUnbind(binding);
+ fail("AccessControlException is expected");
+ }
+ catch(AccessControlException e)
+ {
+ // pass
+ }
+ verify(_accessControl, times(2)).authorise(eq(Operation.UNBIND), eq(ObjectType.EXCHANGE), eq(properties));
+ }
+
+ public void testAuthoriseConfiguringBroker()
+ {
+ OperationLoggingDetails properties = new OperationLoggingDetails("create virtualhost 'test'");
+
+ configureAccessPlugin(Result.ALLOWED);
+ assertTrue(_securityManager.authoriseConfiguringBroker("test", VirtualHost.class, Operation.CREATE));
+ verify(_accessControl).authorise(eq(Operation.CONFIGURE), eq(ObjectType.BROKER), eq(properties));
+
+ configureAccessPlugin(Result.DENIED);
+ assertFalse(_securityManager.authoriseConfiguringBroker("test", VirtualHost.class, Operation.CREATE));
+ verify(_accessControl, times(2)).authorise(eq(Operation.CONFIGURE), eq(ObjectType.BROKER), eq(properties));
+ }
+
+ public void testAuthoriseLogsAccess()
+ {
+ configureAccessPlugin(Result.ALLOWED);
+ assertTrue(_securityManager.authoriseLogsAccess());
+ verify(_accessControl).authorise(ACCESS_LOGS, BROKER, ObjectProperties.EMPTY);
+
+ configureAccessPlugin(Result.DENIED);
+ assertFalse(_securityManager.authoriseLogsAccess());
+ verify(_accessControl, times(2)).authorise(ACCESS_LOGS, BROKER, ObjectProperties.EMPTY);
+ }
+
+ private void configureAccessPlugin(Result result)
+ {
+ when(_accessControl.authorise(any(Operation.class), any(ObjectType.class), any(ObjectProperties.class))).thenReturn(result);
+ }
+
+ private ObjectProperties createExpectedExchangeObjectProperties()
+ {
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_EXCHANGE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.AUTO_DELETE, false);
+ properties.put(Property.TEMPORARY, true);
+ properties.put(Property.DURABLE, false);
+ properties.put(Property.TYPE, TEST_EXCHANGE_TYPE);
+ return properties;
+ }
+
+ private ObjectProperties createExpectedQueueObjectProperties()
+ {
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.NAME, TEST_QUEUE);
+ properties.put(Property.VIRTUALHOST_NAME, TEST_VIRTUAL_HOST);
+ properties.put(Property.AUTO_DELETE, true);
+ properties.put(Property.TEMPORARY, true);
+ properties.put(Property.DURABLE, false);
+ properties.put(Property.EXCLUSIVE, false);
+ return properties;
+ }
+
+
+
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerTest.java
new file mode 100644
index 0000000000..033e0afde8
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/ScramSHA1AuthenticationManagerTest.java
@@ -0,0 +1,203 @@
+/*
+ *
+ * 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 org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.AuthenticationProvider;
+import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.State;
+import org.apache.qpid.server.model.User;
+import org.apache.qpid.server.security.auth.AuthenticationResult;
+import org.apache.qpid.test.utils.QpidTestCase;
+ import org.apache.qpid.server.security.SecurityManager;
+
+import javax.security.auth.login.AccountNotFoundException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ScramSHA1AuthenticationManagerTest extends QpidTestCase
+{
+ private ScramSHA1AuthenticationManager _authManager;
+ private Broker _broker;
+ private SecurityManager _securityManager;
+ private TaskExecutor _executor;
+
+ @Override
+ public void setUp() throws Exception
+ {
+ super.setUp();
+ _executor = new TaskExecutor();
+ _executor.start();
+ _broker = mock(Broker.class);
+ _securityManager = mock(SecurityManager.class);
+ when(_broker.getTaskExecutor()).thenReturn(_executor);
+ when(_broker.getSecurityManager()).thenReturn(_securityManager);
+ final Map<String, Object> attributesMap = new HashMap<String, Object>();
+ attributesMap.put(AuthenticationProvider.NAME, getTestName());
+ attributesMap.put(AuthenticationProvider.ID, UUID.randomUUID());
+ _authManager = new ScramSHA1AuthenticationManager(_broker, Collections.<String,Object>emptyMap(),attributesMap,false);
+ }
+
+ @Override
+ public void tearDown() throws Exception
+ {
+ _executor.stop();
+ super.tearDown();
+ }
+
+ public void testAddChildAndThenDelete()
+ {
+ // No children should be present before the test starts
+ assertEquals("No users should be present before the test starts", 0, _authManager.getChildren(User.class).size());
+ assertEquals("No users should be present before the test starts", 0, _authManager.getUsers().size());
+
+ final Map<String, Object> childAttrs = new HashMap<String, Object>();
+
+ childAttrs.put(User.NAME, getTestName());
+ childAttrs.put(User.PASSWORD, "password");
+ User user = _authManager.addChild(User.class, childAttrs);
+ assertNotNull("User should be created but addChild returned null", user);
+ assertEquals(getTestName(), user.getName());
+ // password shouldn't actually be the given string, but instead salt and the hashed value
+ assertFalse("Password shouldn't actually be the given string, but instead salt and the hashed value", "password".equals(user.getPassword()));
+
+ AuthenticationResult authResult =
+ _authManager.authenticate(getTestName(), "password");
+
+ assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus());
+
+ assertEquals("Manager should have exactly one user child",1, _authManager.getChildren(User.class).size());
+ assertEquals("Manager should have exactly one user child",1, _authManager.getUsers().size());
+
+
+ user.setDesiredState(State.ACTIVE, State.DELETED);
+
+ assertEquals("No users should be present after child deletion", 0, _authManager.getChildren(User.class).size());
+
+
+ authResult = _authManager.authenticate(getTestName(), "password");
+ assertEquals("User should no longer authenticate with given password", AuthenticationResult.AuthenticationStatus.ERROR, authResult.getStatus());
+
+ }
+
+ public void testCreateUser()
+ {
+ assertEquals("No users should be present before the test starts", 0, _authManager.getChildren(User.class).size());
+ assertTrue(_authManager.createUser(getTestName(), "password", Collections.<String, String>emptyMap()));
+ assertEquals("Manager should have exactly one user child",1, _authManager.getChildren(User.class).size());
+ User user = _authManager.getChildren(User.class).iterator().next();
+ assertEquals(getTestName(), user.getName());
+ // password shouldn't actually be the given string, but instead salt and the hashed value
+ assertFalse("Password shouldn't actually be the given string, but instead salt and the hashed value", "password".equals(user.getPassword()));
+ final Map<String, Object> childAttrs = new HashMap<String, Object>();
+
+ childAttrs.put(User.NAME, getTestName());
+ childAttrs.put(User.PASSWORD, "password");
+ try
+ {
+ user = _authManager.addChild(User.class, childAttrs);
+ fail("Should not be able to create a second user with the same name");
+ }
+ catch(IllegalArgumentException e)
+ {
+ // pass
+ }
+ try
+ {
+ _authManager.deleteUser(getTestName());
+ }
+ catch (AccountNotFoundException e)
+ {
+ fail("AccountNotFoundException thrown when none was expected: " + e.getMessage());
+ }
+ try
+ {
+ _authManager.deleteUser(getTestName());
+ fail("AccountNotFoundException not thrown when was expected");
+ }
+ catch (AccountNotFoundException e)
+ {
+ // pass
+ }
+ }
+
+ public void testUpdateUser()
+ {
+ assertTrue(_authManager.createUser(getTestName(), "password", Collections.<String, String>emptyMap()));
+ assertTrue(_authManager.createUser(getTestName()+"_2", "password", Collections.<String, String>emptyMap()));
+ assertEquals("Manager should have exactly two user children",2, _authManager.getChildren(User.class).size());
+
+ AuthenticationResult authResult = _authManager.authenticate(getTestName(), "password");
+
+ assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus());
+ authResult = _authManager.authenticate(getTestName()+"_2", "password");
+ assertEquals("User should authenticate with given password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus());
+
+ for(User user : _authManager.getChildren(User.class))
+ {
+ if(user.getName().equals(getTestName()))
+ {
+ user.setAttributes(Collections.singletonMap(User.PASSWORD, "newpassword"));
+ }
+ }
+
+ authResult = _authManager.authenticate(getTestName(), "newpassword");
+ assertEquals("User should authenticate with updated password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus());
+ authResult = _authManager.authenticate(getTestName()+"_2", "password");
+ assertEquals("User should authenticate with original password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus());
+
+ authResult = _authManager.authenticate(getTestName(), "password");
+ assertEquals("User not authenticate with original password", AuthenticationResult.AuthenticationStatus.ERROR, authResult.getStatus());
+
+ for(User user : _authManager.getChildren(User.class))
+ {
+ if(user.getName().equals(getTestName()))
+ {
+ user.setPassword("newerpassword");
+ }
+ }
+
+ authResult = _authManager.authenticate(getTestName(), "newerpassword");
+ assertEquals("User should authenticate with updated password", AuthenticationResult.AuthenticationStatus.SUCCESS, authResult.getStatus());
+
+
+
+ }
+
+ public void testNonASCIIUser()
+ {
+ try
+ {
+ _authManager.createUser(getTestName()+Character.toString((char)0xa3), "password", Collections.<String, String>emptyMap());
+ fail("Expected exception when attempting to create a user with a non ascii name");
+ }
+ catch(IllegalArgumentException e)
+ {
+ // pass
+ }
+ }
+
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
index b4dfbe837d..fbd26208d8 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
@@ -21,7 +21,6 @@
package org.apache.qpid.server.store;
import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
@@ -40,6 +39,9 @@ import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.server.binding.BindingImpl;
import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.ExclusivityPolicy;
import org.apache.qpid.server.model.LifetimePolicy;
import org.apache.qpid.server.model.Queue;
@@ -62,6 +64,10 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
private static final String BINDING = org.apache.qpid.server.model.Binding.class.getSimpleName();
private static final String QUEUE = Queue.class.getSimpleName();
+ private static final UUID ANY_UUID = UUID.randomUUID();
+ private static final Map ANY_MAP = new HashMap();
+
+
private String _storePath;
private String _storeName;
@@ -91,12 +97,16 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
setTestSystemProperty("QPID_WORK", TMP_FOLDER);
_recoveryHandler = mock(ConfigurationRecoveryHandler.class);
-
when(_exchange.getName()).thenReturn(EXCHANGE_NAME);
when(_exchange.getId()).thenReturn(_exchangeId);
when(_exchange.getExchangeType()).thenReturn(mock(ExchangeType.class));
when(_exchange.getEventLogger()).thenReturn(new EventLogger());
+ ConfiguredObjectRecord exchangeRecord = mock(ConfiguredObjectRecord.class);
+ when(exchangeRecord.getId()).thenReturn(_exchangeId);
+ when(exchangeRecord.getType()).thenReturn(Exchange.class.getSimpleName());
+ when(_exchange.asObjectRecord()).thenReturn(exchangeRecord);
+
_bindingArgs = new HashMap<String, Object>();
String argKey = AMQPFilterTypes.JMS_SELECTOR.toString();
String argValue = "some selector expression";
@@ -124,8 +134,8 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
DurableConfigurationStoreHelper.createExchange(_configStore, exchange);
reopenStore();
- verify(_recoveryHandler).configuredObject(eq(_exchangeId), eq(EXCHANGE),
- eq(map( org.apache.qpid.server.model.Exchange.NAME, getName(),
+ verify(_recoveryHandler).configuredObject(matchesRecord(_exchangeId, EXCHANGE,
+ map( org.apache.qpid.server.model.Exchange.NAME, getName(),
org.apache.qpid.server.model.Exchange.TYPE, getName()+"Type",
org.apache.qpid.server.model.Exchange.LIFETIME_POLICY, LifetimePolicy.DELETE_ON_NO_OUTBOUND_LINKS.name())));
}
@@ -158,7 +168,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
DurableConfigurationStoreHelper.removeExchange(_configStore, exchange);
reopenStore();
- verify(_recoveryHandler, never()).configuredObject(any(UUID.class), anyString(), anyMap());
+ verify(_recoveryHandler, never()).configuredObject(any(ConfiguredObjectRecord.class));
}
public void testBindQueue() throws Exception
@@ -166,42 +176,86 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false, null);
BindingImpl binding = new BindingImpl(UUIDGenerator.generateRandomUUID(), ROUTING_KEY, queue,
_exchange, _bindingArgs);
+ DurableConfigurationStoreHelper.createQueue(_configStore, queue);
DurableConfigurationStoreHelper.createBinding(_configStore, binding);
reopenStore();
Map<String,Object> map = new HashMap<String, Object>();
- map.put(org.apache.qpid.server.model.Binding.EXCHANGE, _exchange.getId().toString());
- map.put(org.apache.qpid.server.model.Binding.QUEUE, queue.getId().toString());
- map.put(org.apache.qpid.server.model.Binding.NAME, ROUTING_KEY);
- map.put(org.apache.qpid.server.model.Binding.ARGUMENTS,_bindingArgs);
+ map.put(Binding.NAME, ROUTING_KEY);
+ map.put(Binding.ARGUMENTS,_bindingArgs);
+
+ Map<String,UUID> parents = new HashMap<String, UUID>();
+
+ parents.put(Exchange.class.getSimpleName(), _exchange.getId());
+ parents.put(Queue.class.getSimpleName(), queue.getId());
+
+ verify(_recoveryHandler).configuredObject(matchesRecord(binding.getId(), BINDING, map, parents));
+ }
+
+
+ private ConfiguredObjectRecord matchesRecord(UUID id,
+ String type,
+ Map<String, Object> attributes,
+ final Map<String, UUID> parents)
+ {
+ return argThat(new ConfiguredObjectMatcher(id, type, attributes, parents));
+ }
- verify(_recoveryHandler).configuredObject(eq(binding.getId()), eq(BINDING),
- argThat(new IgnoreCreatedByMatcher(map)));
+ private ConfiguredObjectRecord matchesRecord(UUID id, String type, Map<String, Object> attributes)
+ {
+ return argThat(new ConfiguredObjectMatcher(id, type, attributes, ANY_MAP));
}
- private static class IgnoreCreatedByMatcher extends ArgumentMatcher<Map<String,Object>>
+ private static class ConfiguredObjectMatcher extends ArgumentMatcher<ConfiguredObjectRecord>
{
private final Map<String,Object> _matchingMap;
+ private final UUID _id;
+ private final String _name;
+ private final Map<String,UUID> _parents;
- private IgnoreCreatedByMatcher(final Map<String, Object> matchingMap)
+ private ConfiguredObjectMatcher(final UUID id, final String type, final Map<String, Object> matchingMap, Map<String,UUID> parents)
{
+ _id = id;
+ _name = type;
_matchingMap = matchingMap;
+ _parents = parents;
}
@Override
public boolean matches(final Object argument)
{
- if(argument instanceof Map)
+ if(argument instanceof ConfiguredObjectRecord)
{
- Map<String,Object> arg = new HashMap<String, Object>((Map<String,Object>) argument);
+ ConfiguredObjectRecord binding = (ConfiguredObjectRecord) argument;
+
+ Map<String,Object> arg = new HashMap<String, Object>(binding.getAttributes());
arg.remove("createdBy");
arg.remove("createdTime");
- return arg.equals(_matchingMap);
-
+ return (_id == ANY_UUID || _id.equals(binding.getId()))
+ && _name.equals(binding.getType())
+ && (_matchingMap == ANY_MAP || arg.equals(_matchingMap))
+ && (_parents == ANY_MAP || matchesParents(binding));
}
return false;
}
+
+ private boolean matchesParents(ConfiguredObjectRecord binding)
+ {
+ Map<String, ConfiguredObjectRecord> bindingParents = binding.getParents();
+ if(bindingParents.size() != _parents.size())
+ {
+ return false;
+ }
+ for(Map.Entry<String,UUID> entry : _parents.entrySet())
+ {
+ if(!bindingParents.get(entry.getKey()).getId().equals(entry.getValue()))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
}
public void testUnbindQueue() throws Exception
@@ -214,9 +268,8 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
DurableConfigurationStoreHelper.removeBinding(_configStore, binding);
reopenStore();
- verify(_recoveryHandler, never()).configuredObject(any(UUID.class),
- eq(BINDING),
- anyMap());
+ verify(_recoveryHandler, never()).configuredObject(matchesRecord(ANY_UUID, BINDING,
+ ANY_MAP));
}
public void testCreateQueueAMQQueue() throws Exception
@@ -229,7 +282,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
queueAttributes.put(Queue.NAME, getName());
queueAttributes.put(Queue.OWNER, getName()+"Owner");
queueAttributes.put(Queue.EXCLUSIVE, ExclusivityPolicy.CONTAINER.name());
- verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes));
+ verify(_recoveryHandler).configuredObject(matchesRecord(_queueId, QUEUE, queueAttributes));
}
public void testCreateQueueAMQQueueFieldTable() throws Exception
@@ -251,7 +304,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
queueAttributes.put(Queue.EXCLUSIVE, ExclusivityPolicy.CONTAINER.name());
queueAttributes.putAll(attributes);
- verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes));
+ verify(_recoveryHandler).configuredObject(matchesRecord(_queueId, QUEUE, queueAttributes));
}
public void testCreateQueueAMQQueueWithAlternateExchange() throws Exception
@@ -269,7 +322,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
queueAttributes.put(Queue.EXCLUSIVE, ExclusivityPolicy.CONTAINER.name());
queueAttributes.put(Queue.ALTERNATE_EXCHANGE, alternateExchange.getId().toString());
- verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes));
+ verify(_recoveryHandler).configuredObject(matchesRecord(_queueId, QUEUE, queueAttributes));
}
private ExchangeImpl createTestAlternateExchange()
@@ -302,7 +355,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
queueAttributes.put(Queue.NAME, getName());
queueAttributes.putAll(attributes);
- verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes));
+ verify(_recoveryHandler).configuredObject(matchesRecord(_queueId, QUEUE, queueAttributes));
}
@@ -329,7 +382,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
queueAttributes.putAll(attributes);
queueAttributes.put(Queue.ALTERNATE_EXCHANGE, alternateExchange.getId().toString());
- verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes));
+ verify(_recoveryHandler).configuredObject(matchesRecord(_queueId, QUEUE, queueAttributes));
}
public void testRemoveQueue() throws Exception
@@ -344,9 +397,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
// remove queue
DurableConfigurationStoreHelper.removeQueue(_configStore,queue);
reopenStore();
- verify(_recoveryHandler, never()).configuredObject(any(UUID.class),
- eq(org.apache.qpid.server.model.Queue.class.getName()),
- anyMap());
+ verify(_recoveryHandler, never()).configuredObject(any(ConfiguredObjectRecord.class));
}
private AMQQueue createTestQueue(String queueName,
@@ -399,6 +450,12 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
});
when(queue.getActualAttributes()).thenReturn(attributes);
+
+ ConfiguredObjectRecord objectRecord = mock(ConfiguredObjectRecord.class);
+ when(objectRecord.getId()).thenReturn(_queueId);
+ when(objectRecord.getType()).thenReturn(Queue.class.getSimpleName());
+ when(objectRecord.getAttributes()).thenReturn(attributes);
+ when(queue.asObjectRecord()).thenReturn(objectRecord);
return queue;
}
@@ -415,6 +472,13 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
when(exchange.getTypeName()).thenReturn(getName() + "Type");
when(exchange.isAutoDelete()).thenReturn(true);
when(exchange.getId()).thenReturn(_exchangeId);
+ ConfiguredObjectRecord exchangeRecord = mock(ConfiguredObjectRecord.class);
+ when(exchangeRecord.getId()).thenReturn(_exchangeId);
+ when(exchangeRecord.getType()).thenReturn(Exchange.class.getSimpleName());
+ Map<String,Object> actualAttributesExceptId = new HashMap<String, Object>(actualAttributes);
+ actualAttributesExceptId.remove("id");
+ when(exchangeRecord.getAttributes()).thenReturn(actualAttributesExceptId);
+ when(exchange.asObjectRecord()).thenReturn(exchangeRecord);
return exchange;
}
@@ -425,7 +489,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
_configStore = createConfigStore();
_configStore.openConfigurationStore("testName", _configurationStoreSettings);
- _configStore.recoverConfigurationStore(_recoveryHandler);
+ _configStore.recoverConfigurationStore(mock(ConfiguredObject.class), _recoveryHandler);
}
protected abstract DurableConfigurationStore createConfigStore() throws Exception;
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java
index 5d2998de86..bca16b6e70 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java
@@ -27,16 +27,19 @@ import java.util.Map;
import java.util.UUID;
import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.util.ServerScopedRuntimeException;
import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.test.utils.TestFileUtils;
import org.apache.qpid.util.FileUtils;
+import org.mockito.ArgumentMatcher;
import org.mockito.InOrder;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyMap;
import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.argThat;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
@@ -53,6 +56,10 @@ public class JsonFileConfigStoreTest extends QpidTestCase
private String _virtualHostName;
private File _storeLocation;
+
+ private static final UUID ANY_UUID = UUID.randomUUID();
+ private static final Map<String, Object> ANY_MAP = new HashMap<String, Object>();
+
@Override
public void setUp() throws Exception
{
@@ -110,10 +117,10 @@ public class JsonFileConfigStoreTest extends QpidTestCase
public void testStartFromNoStore() throws Exception
{
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
- _store.recoverConfigurationStore(_recoveryHandler);
+ _store.recoverConfigurationStore(mock(ConfiguredObject.class), _recoveryHandler);
InOrder inorder = inOrder(_recoveryHandler);
inorder.verify(_recoveryHandler).beginConfigurationRecovery(eq(_store), eq(0));
- inorder.verify(_recoveryHandler,never()).configuredObject(any(UUID.class),anyString(),anyMap());
+ inorder.verify(_recoveryHandler,never()).configuredObject(any(ConfiguredObjectRecord.class));
inorder.verify(_recoveryHandler).completeConfigurationRecovery();
_store.closeConfigurationStore();
}
@@ -124,11 +131,11 @@ public class JsonFileConfigStoreTest extends QpidTestCase
when(_recoveryHandler.completeConfigurationRecovery()).thenReturn(NEW_CONFIG_VERSION);
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
- _store.recoverConfigurationStore(_recoveryHandler);
+ _store.recoverConfigurationStore(mock(ConfiguredObject.class), _recoveryHandler);
_store.closeConfigurationStore();
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
- _store.recoverConfigurationStore(_recoveryHandler);
+ _store.recoverConfigurationStore(mock(ConfiguredObject.class), _recoveryHandler);
InOrder inorder = inOrder(_recoveryHandler);
// first time the config version should be the initial version - 0
@@ -147,12 +154,12 @@ public class JsonFileConfigStoreTest extends QpidTestCase
final String queueType = Queue.class.getSimpleName();
final Map<String,Object> queueAttr = Collections.singletonMap("name", (Object) "q1");
- _store.create(queueId, queueType, queueAttr);
+ _store.create(new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr));
_store.closeConfigurationStore();
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
- _store.recoverConfigurationStore(_recoveryHandler);
- verify(_recoveryHandler).configuredObject(eq(queueId), eq(queueType), eq(queueAttr));
+ _store.recoverConfigurationStore(mock(ConfiguredObject.class), _recoveryHandler);
+ verify(_recoveryHandler).configuredObject(matchesRecord(queueId, queueType, queueAttr));
_store.closeConfigurationStore();
}
@@ -163,18 +170,18 @@ public class JsonFileConfigStoreTest extends QpidTestCase
final String queueType = Queue.class.getSimpleName();
Map<String,Object> queueAttr = Collections.singletonMap("name", (Object) "q1");
- _store.create(queueId, queueType, queueAttr);
+ _store.create(new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr));
queueAttr = new HashMap<String,Object>(queueAttr);
queueAttr.put("owner", "theowner");
- _store.update(queueId, queueType, queueAttr);
+ _store.update(false, new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr));
_store.closeConfigurationStore();
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
- _store.recoverConfigurationStore(_recoveryHandler);
- verify(_recoveryHandler).configuredObject(eq(queueId), eq(queueType), eq(queueAttr));
+ _store.recoverConfigurationStore(mock(ConfiguredObject.class), _recoveryHandler);
+ verify(_recoveryHandler).configuredObject(matchesRecord(queueId, queueType, queueAttr));
_store.closeConfigurationStore();
}
@@ -186,16 +193,17 @@ public class JsonFileConfigStoreTest extends QpidTestCase
final String queueType = Queue.class.getSimpleName();
Map<String,Object> queueAttr = Collections.singletonMap("name", (Object) "q1");
- _store.create(queueId, queueType, queueAttr);
+ final ConfiguredObjectRecordImpl record = new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr);
+ _store.create(record);
- _store.remove(queueId, queueType);
+ _store.remove(record);
_store.closeConfigurationStore();
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
- _store.recoverConfigurationStore(_recoveryHandler);
- verify(_recoveryHandler, never()).configuredObject(any(UUID.class), anyString(), anyMap());
+ _store.recoverConfigurationStore(mock(ConfiguredObject.class), _recoveryHandler);
+ verify(_recoveryHandler, never()).configuredObject(any(ConfiguredObjectRecord.class));
_store.closeConfigurationStore();
}
@@ -204,7 +212,7 @@ public class JsonFileConfigStoreTest extends QpidTestCase
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
try
{
- _store.create(UUID.randomUUID(), "wibble", Collections.<String, Object>emptyMap());
+ _store.create(new ConfiguredObjectRecordImpl(UUID.randomUUID(), "wibble", Collections.<String, Object>emptyMap()));
fail("Should not be able to create instance of type wibble");
}
catch (StoreException e)
@@ -217,10 +225,10 @@ public class JsonFileConfigStoreTest extends QpidTestCase
{
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
final UUID id = UUID.randomUUID();
- _store.create(id, "Queue", Collections.<String, Object>emptyMap());
+ _store.create(new ConfiguredObjectRecordImpl(id, "Queue", Collections.<String, Object>emptyMap()));
try
{
- _store.create(id, "Exchange", Collections.<String, Object>emptyMap());
+ _store.create(new ConfiguredObjectRecordImpl(id, "Exchange", Collections.<String, Object>emptyMap()));
fail("Should not be able to create two objects with same id");
}
catch (StoreException e)
@@ -234,13 +242,13 @@ public class JsonFileConfigStoreTest extends QpidTestCase
{
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
final UUID id = UUID.randomUUID();
- _store.create(id, "Queue", Collections.<String, Object>emptyMap());
+ _store.create(new ConfiguredObjectRecordImpl(id, "Queue", Collections.<String, Object>emptyMap()));
_store.closeConfigurationStore();
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
try
{
- _store.update(id, "Exchange", Collections.<String, Object>emptyMap());
+ _store.update(false, new ConfiguredObjectRecordImpl(id, "Exchange", Collections.<String, Object>emptyMap()));
fail("Should not be able to update object to different type");
}
catch (StoreException e)
@@ -279,32 +287,76 @@ public class JsonFileConfigStoreTest extends QpidTestCase
final Map<String, Object> EMPTY_ATTR = Collections.emptyMap();
final UUID exchangeId = new UUID(0, 2);
- final Map<String, Object> bindingAttributes = new HashMap<String, Object>();
- bindingAttributes.put(Binding.EXCHANGE, exchangeId);
- bindingAttributes.put(Binding.QUEUE, queueId);
- final Map<String, Object> binding2Attributes = new HashMap<String, Object>();
- binding2Attributes.put(Binding.EXCHANGE, exchangeId);
- binding2Attributes.put(Binding.QUEUE, queue2Id);
final UUID bindingId = new UUID(0, 3);
final UUID binding2Id = new UUID(1, 3);
- _store.create(queueId, "Queue", EMPTY_ATTR);
- _store.create(queue2Id, "Queue", EMPTY_ATTR);
- _store.create(exchangeId, "Exchange", EMPTY_ATTR);
- _store.update(true,
- new ConfiguredObjectRecord(bindingId, "Binding", bindingAttributes),
- new ConfiguredObjectRecord(binding2Id, "Binding", binding2Attributes));
+ final ConfiguredObjectRecordImpl queueRecord = new ConfiguredObjectRecordImpl(queueId, "Queue", EMPTY_ATTR);
+ _store.create(queueRecord);
+ final ConfiguredObjectRecordImpl queue2Record = new ConfiguredObjectRecordImpl(queue2Id, "Queue", EMPTY_ATTR);
+ _store.create(queue2Record);
+ final ConfiguredObjectRecordImpl exchangeRecord = new ConfiguredObjectRecordImpl(exchangeId, "Exchange", EMPTY_ATTR);
+ _store.create(exchangeRecord);
+ Map<String,ConfiguredObjectRecord> bindingParents = new HashMap<String, ConfiguredObjectRecord>();
+ bindingParents.put("Exchange", exchangeRecord);
+ bindingParents.put("Queue", queueRecord);
+ final ConfiguredObjectRecordImpl bindingRecord =
+ new ConfiguredObjectRecordImpl(bindingId, "Binding", EMPTY_ATTR, bindingParents);
+
+
+ Map<String,ConfiguredObjectRecord> binding2Parents = new HashMap<String, ConfiguredObjectRecord>();
+ binding2Parents.put("Exchange", exchangeRecord);
+ binding2Parents.put("Queue", queue2Record);
+ final ConfiguredObjectRecordImpl binding2Record =
+ new ConfiguredObjectRecordImpl(binding2Id, "Binding", EMPTY_ATTR, binding2Parents);
+ _store.update(true, bindingRecord, binding2Record);
_store.closeConfigurationStore();
_store.openConfigurationStore(_virtualHostName, _configurationStoreSettings);
- _store.recoverConfigurationStore(_recoveryHandler);
- verify(_recoveryHandler).configuredObject(eq(queueId), eq("Queue"), eq(EMPTY_ATTR));
- verify(_recoveryHandler).configuredObject(eq(queue2Id), eq("Queue"), eq(EMPTY_ATTR));
- verify(_recoveryHandler).configuredObject(eq(exchangeId), eq("Exchange"), eq(EMPTY_ATTR));
- verify(_recoveryHandler).configuredObject(eq(bindingId),eq("Binding"), eq(bindingAttributes));
- verify(_recoveryHandler).configuredObject(eq(binding2Id),eq("Binding"), eq(binding2Attributes));
+ _store.recoverConfigurationStore(mock(ConfiguredObject.class), _recoveryHandler);
+ verify(_recoveryHandler).configuredObject(matchesRecord(queueId, "Queue", EMPTY_ATTR));
+ verify(_recoveryHandler).configuredObject(matchesRecord(queue2Id, "Queue", EMPTY_ATTR));
+ verify(_recoveryHandler).configuredObject(matchesRecord(exchangeId, "Exchange", EMPTY_ATTR));
+ verify(_recoveryHandler).configuredObject(matchesRecord(bindingId, "Binding", EMPTY_ATTR));
+ verify(_recoveryHandler).configuredObject(matchesRecord(binding2Id, "Binding", EMPTY_ATTR));
_store.closeConfigurationStore();
}
+ private ConfiguredObjectRecord matchesRecord(UUID id, String type, Map<String, Object> attributes)
+ {
+ return argThat(new ConfiguredObjectMatcher(id, type, attributes));
+ }
+
+ private static class ConfiguredObjectMatcher extends ArgumentMatcher<ConfiguredObjectRecord>
+ {
+ private final Map<String,Object> _matchingMap;
+ private final UUID _id;
+ private final String _name;
+
+ private ConfiguredObjectMatcher(final UUID id, final String type, final Map<String, Object> matchingMap)
+ {
+ _id = id;
+ _name = type;
+ _matchingMap = matchingMap;
+ }
+
+ @Override
+ public boolean matches(final Object argument)
+ {
+ if(argument instanceof ConfiguredObjectRecord)
+ {
+ ConfiguredObjectRecord binding = (ConfiguredObjectRecord) argument;
+
+ Map<String,Object> arg = new HashMap<String, Object>(binding.getAttributes());
+ arg.remove("createdBy");
+ arg.remove("createdTime");
+ return (_id == ANY_UUID || _id.equals(binding.getId()))
+ && _name.equals(binding.getType())
+ && (_matchingMap == ANY_MAP || arg.equals(_matchingMap));
+
+ }
+ return false;
+ }
+ }
+
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java
index e46a8939f4..fc69a53c85 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java
@@ -32,6 +32,8 @@ import java.util.UUID;
import org.apache.log4j.Logger;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler;
import org.apache.qpid.test.utils.QpidTestCase;
import org.apache.qpid.util.FileUtils;
@@ -64,11 +66,11 @@ public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase imple
Map<String, Object> storeSettings = createStoreSettings(_storeLocation.getAbsolutePath());
_store = createStore();
- ((DurableConfigurationStore)_store).openConfigurationStore("test", storeSettings);
+
MessageStoreRecoveryHandler recoveryHandler = mock(MessageStoreRecoveryHandler.class);
when(recoveryHandler.begin()).thenReturn(mock(StoredMessageRecoveryHandler.class));
_store.openMessageStore("test", storeSettings);
- _store.recoverMessageStore(recoveryHandler, null);
+ _store.recoverMessageStore(mock(ConfiguredObject.class), recoveryHandler, null);
_transactionResource = UUID.randomUUID();
_events = new ArrayList<Event>();
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java
index 45f7a2a39e..1d95133784 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java
@@ -30,6 +30,7 @@ import java.util.Map;
import java.util.UUID;
import org.apache.qpid.server.message.EnqueueableMessage;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.UUIDGenerator;
import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler;
import org.apache.qpid.server.store.Transaction.Record;
@@ -65,7 +66,7 @@ public abstract class MessageStoreTestCase extends QpidTestCase
_store = createMessageStore();
_store.openMessageStore("test", _storeSettings);
- _store.recoverMessageStore(_messageStoreRecoveryHandler, _logRecoveryHandler);
+ _store.recoverMessageStore(mock(ConfiguredObject.class), _messageStoreRecoveryHandler, _logRecoveryHandler);
}
protected abstract Map<String, Object> getStoreSettings() throws Exception;
@@ -106,7 +107,7 @@ public abstract class MessageStoreTestCase extends QpidTestCase
_store = createMessageStore();
_store.openMessageStore("test", _storeSettings);
- _store.recoverMessageStore(_messageStoreRecoveryHandler, _logRecoveryHandler);
+ _store.recoverMessageStore(mock(ConfiguredObject.class), _messageStoreRecoveryHandler, _logRecoveryHandler);
}
private Record getTestRecord(long messageNumber)
{
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java
index e3d56ab4bb..c90c6af220 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java
@@ -30,6 +30,7 @@ import java.util.UUID;
import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
import org.apache.qpid.server.store.StoreException;
import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.exchange.AMQUnknownExchangeType;
@@ -229,17 +230,16 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
_durableConfigurationRecoverer.beginConfigurationRecovery(_store, 0);
- _durableConfigurationRecoverer.configuredObject(new UUID(1, 0),
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0),
"org.apache.qpid.server.model.Binding",
createBinding("key",
- DIRECT_EXCHANGE_ID,
- QUEUE_ID,
"x-filter-jms-selector",
- "wibble"));
+ "wibble"),
+ createBindingParents(DIRECT_EXCHANGE_ID, QUEUE_ID)));
final ConfiguredObjectRecord[] expected = {
- new ConfiguredObjectRecord(new UUID(1, 0), "Binding",
- createBinding("key", DIRECT_EXCHANGE_ID, QUEUE_ID))
+ new ConfiguredObjectRecordImpl(new UUID(1, 0), "Binding",
+ createBinding("key"))
};
verifyCorrectUpdates(expected);
@@ -254,32 +254,30 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
_durableConfigurationRecoverer.beginConfigurationRecovery(_store, 0);
- _durableConfigurationRecoverer.configuredObject(new UUID(1, 0),
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0),
"org.apache.qpid.server.model.Binding",
createBinding("key",
- DIRECT_EXCHANGE_ID,
- QUEUE_ID,
"x-filter-jms-selector",
"wibble",
"not-a-selector",
- "moo"));
+ "moo"),
+ createBindingParents(DIRECT_EXCHANGE_ID, QUEUE_ID)));
final UUID customExchangeId = new UUID(3,0);
- _durableConfigurationRecoverer.configuredObject(new UUID(2, 0),
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(2, 0),
"org.apache.qpid.server.model.Binding",
createBinding("key",
- customExchangeId,
- QUEUE_ID,
"x-filter-jms-selector",
"wibble",
"not-a-selector",
- "moo"));
+ "moo"),
+ createBindingParents(customExchangeId,QUEUE_ID)));
- _durableConfigurationRecoverer.configuredObject(customExchangeId,
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(customExchangeId,
"org.apache.qpid.server.model.Exchange",
- createExchange(CUSTOM_EXCHANGE_NAME, HeadersExchange.TYPE));
+ createExchange(CUSTOM_EXCHANGE_NAME, HeadersExchange.TYPE)));
final ExchangeImpl customExchange = mock(ExchangeImpl.class);
@@ -323,10 +321,10 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
final ConfiguredObjectRecord[] expected = {
- new ConfiguredObjectRecord(new UUID(1, 0), "org.apache.qpid.server.model.Binding",
- createBinding("key", DIRECT_EXCHANGE_ID, QUEUE_ID, "not-a-selector", "moo")),
- new ConfiguredObjectRecord(new UUID(2, 0), "org.apache.qpid.server.model.Binding",
- createBinding("key", customExchangeId, QUEUE_ID, "not-a-selector", "moo"))
+ new ConfiguredObjectRecordImpl(new UUID(1, 0), "org.apache.qpid.server.model.Binding",
+ createBinding("key", "not-a-selector", "moo")),
+ new ConfiguredObjectRecordImpl(new UUID(2, 0), "org.apache.qpid.server.model.Binding",
+ createBinding("key", "not-a-selector", "moo"))
};
verifyCorrectUpdates(expected);
@@ -340,17 +338,16 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
_durableConfigurationRecoverer.beginConfigurationRecovery(_store, 0);
- _durableConfigurationRecoverer.configuredObject(new UUID(1, 0),
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0),
"org.apache.qpid.server.model.Binding",
createBinding("key",
- TOPIC_EXCHANGE_ID,
- QUEUE_ID,
"x-filter-jms-selector",
- "wibble"));
+ "wibble"),
+ createBindingParents(TOPIC_EXCHANGE_ID,QUEUE_ID)));
final ConfiguredObjectRecord[] expected = {
- new ConfiguredObjectRecord(new UUID(1, 0), "Binding",
- createBinding("key", TOPIC_EXCHANGE_ID, QUEUE_ID, "x-filter-jms-selector", "wibble"))
+ new ConfiguredObjectRecordImpl(new UUID(1, 0), "Binding",
+ createBinding("key", "x-filter-jms-selector", "wibble"))
};
verifyCorrectUpdates(expected);
@@ -363,16 +360,15 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
_durableConfigurationRecoverer.beginConfigurationRecovery(_store, 2);
- _durableConfigurationRecoverer.configuredObject(new UUID(1, 0),
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0),
"Binding",
createBinding("key",
- DIRECT_EXCHANGE_ID,
- QUEUE_ID,
"x-filter-jms-selector",
- "wibble"));
+ "wibble"),
+ createBindingParents(DIRECT_EXCHANGE_ID,QUEUE_ID)));
doThrow(new RuntimeException("Update Should not be called"))
- .when(_store).update(anyBoolean(), any(ConfiguredObjectRecord[].class));
+ .when(_store).update(anyBoolean(), any(ConfiguredObjectRecordImpl[].class));
_durableConfigurationRecoverer.completeConfigurationRecovery();
}
@@ -382,13 +378,13 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
_durableConfigurationRecoverer.beginConfigurationRecovery(_store, 2);
- _durableConfigurationRecoverer.configuredObject(new UUID(1, 0),
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0),
"Binding",
createBinding("key",
- new UUID(3,0),
- QUEUE_ID,
"x-filter-jms-selector",
- "wibble"));
+ "wibble"),
+ createBindingParents(new UUID(3,0),
+ QUEUE_ID)));
try
{
@@ -410,8 +406,8 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
try
{
final Map<String, Object> emptyArguments = Collections.emptyMap();
- _durableConfigurationRecoverer.configuredObject(new UUID(1, 0),
- "Wibble", emptyArguments);
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0),
+ "Wibble", emptyArguments));
_durableConfigurationRecoverer.completeConfigurationRecovery();
fail("Expected resolution to fail due to unknown object type");
}
@@ -474,11 +470,11 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
_durableConfigurationRecoverer.beginConfigurationRecovery(_store, 2);
- _durableConfigurationRecoverer.configuredObject(queueId, Queue.class.getSimpleName(),
- createQueue("testQueue", exchangeId));
- _durableConfigurationRecoverer.configuredObject(exchangeId,
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(queueId, Queue.class.getSimpleName(),
+ createQueue("testQueue", exchangeId)));
+ _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(exchangeId,
org.apache.qpid.server.model.Exchange.class.getSimpleName(),
- createExchange(CUSTOM_EXCHANGE_NAME, HeadersExchange.TYPE));
+ createExchange(CUSTOM_EXCHANGE_NAME, HeadersExchange.TYPE)));
_durableConfigurationRecoverer.completeConfigurationRecovery();
@@ -499,16 +495,14 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
return null;
}
- }).when(_store).update(anyBoolean(), any(ConfiguredObjectRecord[].class));
+ }).when(_store).update(anyBoolean(), any(ConfiguredObjectRecordImpl[].class));
}
- private Map<String,Object> createBinding(String bindingKey, UUID exchangeId, UUID queueId, String... args)
+ private Map<String,Object> createBinding(String bindingKey, String... args)
{
Map<String, Object> binding = new LinkedHashMap<String, Object>();
binding.put("name", bindingKey);
- binding.put(Binding.EXCHANGE, exchangeId.toString());
- binding.put(Binding.QUEUE, queueId.toString());
Map<String,String> argumentMap = new LinkedHashMap<String, String>();
if(args != null && args.length != 0)
{
@@ -530,6 +524,15 @@ public class DurableConfigurationRecovererTest extends QpidTestCase
return binding;
}
+ private Map<String,ConfiguredObjectRecord> createBindingParents(UUID exchangeId, UUID queueId)
+ {
+ Map<String,ConfiguredObjectRecord> parents = new HashMap<String, ConfiguredObjectRecord>();
+ parents.put("Exchange", new ConfiguredObjectRecordImpl(exchangeId,"Exchange",Collections.<String,Object>emptyMap()));
+ parents.put("Queue", new ConfiguredObjectRecordImpl(queueId,"Queue",Collections.<String,Object>emptyMap()));
+
+ return parents;
+ }
+
private Map<String, Object> createExchange(String name, ExchangeType<HeadersExchange> type)
{
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java
index 3a36ddef2c..072bd6a87f 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java
@@ -20,7 +20,9 @@
*/
package org.apache.qpid.server.security.access.plugins;
-import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@@ -181,7 +183,7 @@ public class DefaultAccessControlTest extends TestCase
final RuleSet rs = new RuleSet(mock(EventLoggerProvider.class));
// grant user4 access right on any method in any component
- rs.grant(1, "user4", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, new ObjectProperties(ObjectProperties.STAR));
+ rs.grant(1, "user4", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, new ObjectProperties(ObjectProperties.WILD_CARD));
configureAccessControl(rs);
Subject.doAs(TestPrincipalUtils.createTestSubject("user4"), new PrivilegedAction<Object>()
{
@@ -207,7 +209,7 @@ public class DefaultAccessControlTest extends TestCase
final RuleSet rs = new RuleSet(mock(EventLoggerProvider.class));
// grant user5 access right on any methods in "Test" component
- ObjectProperties ruleProperties = new ObjectProperties(ObjectProperties.STAR);
+ ObjectProperties ruleProperties = new ObjectProperties(ObjectProperties.WILD_CARD);
ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test");
rs.grant(1, "user5", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties);
configureAccessControl(rs);
@@ -234,6 +236,7 @@ public class DefaultAccessControlTest extends TestCase
public void testAccess() throws Exception
{
final Subject subject = TestPrincipalUtils.createTestSubject("user1");
+ final String testVirtualHost = getName();
final InetAddress inetAddress = InetAddress.getLocalHost();
final InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1);
@@ -249,13 +252,12 @@ public class DefaultAccessControlTest extends TestCase
{
RuleSet mockRuleSet = mock(RuleSet.class);
-
-
DefaultAccessControl accessControl = new DefaultAccessControl(mockRuleSet);
- accessControl.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ ObjectProperties properties = new ObjectProperties(testVirtualHost);
+ accessControl.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, properties);
- verify(mockRuleSet).check(subject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY, inetAddress);
+ verify(mockRuleSet).check(subject, Operation.ACCESS, ObjectType.VIRTUALHOST, properties, inetAddress);
return null;
}
});
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
index caf9b2fb61..32037807cd 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
@@ -21,24 +21,26 @@
package org.apache.qpid.server.security.access.plugins;
-import java.security.Principal;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
import javax.security.auth.Subject;
-import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.exchange.ExchangeImpl;
import org.apache.qpid.server.logging.EventLoggerProvider;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.security.Result;
import org.apache.qpid.server.security.access.ObjectProperties;
import org.apache.qpid.server.security.access.ObjectType;
import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.security.access.Permission;
+import org.apache.qpid.server.security.access.ObjectProperties.Property;
import org.apache.qpid.server.security.access.config.Rule;
import org.apache.qpid.server.security.access.config.RuleSet;
import org.apache.qpid.server.security.auth.TestPrincipalUtils;
import org.apache.qpid.test.utils.QpidTestCase;
-import static org.mockito.Mockito.mock;
-
/**
* This test checks that the {@link RuleSet} object which forms the core of the access control plugin performs correctly.
*
@@ -51,6 +53,9 @@ import static org.mockito.Mockito.mock;
*/
public class RuleSetTest extends QpidTestCase
{
+ private static final String DENIED_VH = "deniedVH";
+ private static final String ALLOWED_VH = "allowedVH";
+
private RuleSet _ruleSet; // Object under test
private static final String TEST_USER = "user";
@@ -60,6 +65,8 @@ public class RuleSetTest extends QpidTestCase
private String _exchangeName = "amq.direct";
private String _exchangeType = "direct";
private Subject _testSubject = TestPrincipalUtils.createTestSubject(TEST_USER);
+ private AMQQueue<?> _queue;
+ private VirtualHost<?> _virtualHost;
@Override
public void setUp() throws Exception
@@ -67,6 +74,11 @@ public class RuleSetTest extends QpidTestCase
super.setUp();
_ruleSet = new RuleSet(mock(EventLoggerProvider.class));
+
+ _virtualHost = mock(VirtualHost.class);
+ _queue = mock(AMQQueue.class);
+ when(_queue.getName()).thenReturn(_queueName);
+ when(_queue.getParent(VirtualHost.class)).thenReturn(_virtualHost);
}
@Override
@@ -83,10 +95,8 @@ public class RuleSetTest extends QpidTestCase
public void assertDenyGrantAllow(Subject subject, Operation operation, ObjectType objectType, ObjectProperties properties)
{
- final Principal identity = subject.getPrincipals().iterator().next();
-
assertEquals(Result.DENIED, _ruleSet.check(subject, operation, objectType, properties));
- _ruleSet.grant(0, identity.getName(), Permission.ALLOW, operation, objectType, properties);
+ _ruleSet.grant(0, TEST_USER, Permission.ALLOW, operation, objectType, properties);
assertEquals(1, _ruleSet.getRuleCount());
assertEquals(Result.ALLOWED, _ruleSet.check(subject, operation, objectType, properties));
}
@@ -98,17 +108,77 @@ public class RuleSetTest extends QpidTestCase
assertEquals(_ruleSet.getDefault(), _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
- public void testVirtualHostAccess() throws Exception
+ public void testVirtualHostAccessAllowPermissionWithVirtualHostName() throws Exception
{
- assertDenyGrantAllow(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST);
+ _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ALLOWED_VH));
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ALLOWED_VH)));
+ assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(DENIED_VH)));
}
+ public void testVirtualHostAccessAllowPermissionWithNameSetToWildCard() throws Exception
+ {
+ _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ObjectProperties.WILD_CARD));
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ALLOWED_VH)));
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(DENIED_VH)));
+ }
+
+ public void testVirtualHostAccessAllowPermissionWithNoName() throws Exception
+ {
+ _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ALLOWED_VH)));
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(DENIED_VH)));
+ }
+
+ public void testVirtualHostAccessDenyPermissionWithNoName() throws Exception
+ {
+ _ruleSet.grant(0, TEST_USER, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ALLOWED_VH)));
+ assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(DENIED_VH)));
+ }
+
+ public void testVirtualHostAccessDenyPermissionWithNameSetToWildCard() throws Exception
+ {
+ _ruleSet.grant(0, TEST_USER, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ObjectProperties.WILD_CARD));
+ assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ALLOWED_VH)));
+ assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(DENIED_VH)));
+ }
+
+ public void testVirtualHostAccessAllowDenyPermissions() throws Exception
+ {
+ _ruleSet.grant(0, TEST_USER, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(DENIED_VH));
+ _ruleSet.grant(1, TEST_USER, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ALLOWED_VH));
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(ALLOWED_VH)));
+ assertEquals(Result.DENIED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(DENIED_VH)));
+ }
+
+ public void testVirtualHostAccessAllowPermissionWithVirtualHostNameOtherPredicate() throws Exception
+ {
+ ObjectProperties properties = new ObjectProperties();
+ properties.put(Property.VIRTUALHOST_NAME, ALLOWED_VH);
+
+ _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, properties);
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, properties));
+ assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.ACCESS, ObjectType.VIRTUALHOST, new ObjectProperties(DENIED_VH)));
+ }
+
+
public void testQueueCreateNamed() throws Exception
{
assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(_queueName));
}
- public void testQueueCreatenamedNullRoutingKey()
+ public void testQueueCreateNamedVirtualHost() throws Exception
+ {
+ _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(Property.VIRTUALHOST_NAME, ALLOWED_VH));
+
+ when(_virtualHost.getName()).thenReturn(ALLOWED_VH);
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(_queue)));
+
+ when(_virtualHost.getName()).thenReturn(DENIED_VH);
+ assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.QUEUE, new ObjectProperties(_queue)));
+ }
+
+ public void testQueueCreateNamedNullRoutingKey()
{
ObjectProperties properties = new ObjectProperties(_queueName);
properties.put(ObjectProperties.Property.ROUTING_KEY, (String) null);
@@ -116,6 +186,21 @@ public class RuleSetTest extends QpidTestCase
assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.QUEUE, properties);
}
+ public void testExchangeCreateNamedVirtualHost()
+ {
+ _ruleSet.grant(0, TEST_USER, Permission.ALLOW, Operation.CREATE, ObjectType.EXCHANGE, new ObjectProperties(Property.VIRTUALHOST_NAME, ALLOWED_VH));
+
+ ExchangeImpl<?> exchange = mock(ExchangeImpl.class);
+ when(exchange.getParent(VirtualHost.class)).thenReturn(_virtualHost);
+ when(exchange.getTypeName()).thenReturn(_exchangeType);
+ when(_virtualHost.getName()).thenReturn(ALLOWED_VH);
+
+ assertEquals(Result.ALLOWED, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, new ObjectProperties(exchange)));
+
+ when(_virtualHost.getName()).thenReturn(DENIED_VH);
+ assertEquals(Result.DEFER, _ruleSet.check(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, new ObjectProperties(exchange)));
+ }
+
public void testExchangeCreate()
{
ObjectProperties properties = new ObjectProperties(_exchangeName);
diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
index 040be92ceb..999da2da6c 100644
--- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
+++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java
@@ -291,7 +291,7 @@ public class ServerSessionDelegate extends SessionDelegate
final VirtualHost virtualHost = getVirtualHost(ssn);
try
{
- virtualHost.getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName());
+ virtualHost.getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName(), virtualHost.getName());
}
catch (AccessControlException e)
{
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
index baf5eceef7..7bde83cc99 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java
@@ -303,9 +303,10 @@ public class AMQChannel<T extends AMQProtocolSession<T>>
public void setPublishFrame(MessagePublishInfo info, final MessageDestination e)
{
String routingKey = info.getRoutingKey() == null ? null : info.getRoutingKey().asString();
- SecurityManager securityManager = getVirtualHost().getSecurityManager();
+ VirtualHost virtualHost = getVirtualHost();
+ SecurityManager securityManager = virtualHost.getSecurityManager();
- securityManager.authorisePublish(info.isImmediate(), routingKey, e.getName());
+ securityManager.authorisePublish(info.isImmediate(), routingKey, e.getName(), virtualHost.getName());
_currentMessage = new IncomingMessage(info);
_currentMessage.setMessageDestination(e);
diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java
index a29d56605a..1a29806f62 100644
--- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java
+++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java
@@ -80,6 +80,8 @@ public class ConnectionOpenMethodHandler implements StateAwareMethodListener<Con
}
else
{
+ session.setVirtualHost(virtualHost);
+
// Check virtualhost access
try
{
@@ -95,7 +97,6 @@ public class ConnectionOpenMethodHandler implements StateAwareMethodListener<Con
throw body.getConnectionException(AMQConstant.CONNECTION_FORCED, "Virtual host '" + virtualHost.getName() + "' is not active");
}
- session.setVirtualHost(virtualHost);
// See Spec (0.8.2). Section 3.1.2 Virtual Hosts
if (session.getContextKey() == null)
diff --git a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html
index 0a83bd9f6f..5b053849a3 100644
--- a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html
+++ b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html
@@ -20,7 +20,7 @@
<td class="tableContainer-labelCell" style="width: 300px;"><strong>Partition Count: </strong></td>
<td class="tableContainer-valueCell">
<input data-dojo-type="dijit/form/NumberSpinner" id="formAddVirtualHost.specific.store.pool.parititions"
- name="minConnectionsPerPartition" value="4" smallDelta="1" constraints="{min:1,max:1000,places:0}"/>
+ name="partitionCount" value="4" smallDelta="1" constraints="{min:1,max:1000,places:0}"/>
</td>
</tr>
<tr>
diff --git a/qpid/java/broker-plugins/management-http/pom.xml b/qpid/java/broker-plugins/management-http/pom.xml
index 4bfaf5e5d2..afb295f7cd 100644
--- a/qpid/java/broker-plugins/management-http/pom.xml
+++ b/qpid/java/broker-plugins/management-http/pom.xml
@@ -69,6 +69,12 @@
<type>zip</type>
</dependency>
+ <dependency>
+ <groupId>org.webjars</groupId>
+ <artifactId>cryptojs</artifactId>
+ <version>3.1.2</version>
+ </dependency>
+
<!-- test dependencies -->
<dependency>
<groupId>org.apache.qpid</groupId>
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java
index 618aaed319..72e9bac29b 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/FileServlet.java
@@ -89,6 +89,10 @@ public class FileServlet extends HttpServlet
}
URL resourceURL = getClass().getResource(_resourcePathPrefix + filename);
+ if(resourceURL == null)
+ {
+ resourceURL = getClass().getResource("/META-INF" + _resourcePathPrefix + filename);
+ }
if(resourceURL != null)
{
response.setStatus(HttpServletResponse.SC_OK);
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
index 0947ae2a89..b23f0cb168 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
@@ -485,10 +485,10 @@ public class MessageServlet extends AbstractServlet
}
- private void authorizeMethod(String methodName, VirtualHost host)
+ private void authorizeMethod(String methodName, VirtualHost<?> vhost)
{
- SecurityManager securityManager = host.getSecurityManager();
- securityManager.authoriseMethod(Operation.UPDATE, "VirtualHost.Queue", methodName);
+ SecurityManager securityManager = getBroker().getSecurityManager();
+ securityManager.authoriseMethod(Operation.UPDATE, "VirtualHost.Queue", methodName, vhost.getName());
}
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
index 2ca67fadc9..af3973c7b3 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
+++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
@@ -59,7 +59,7 @@ public class SaslServlet extends AbstractServlet
private static final String ATTR_ID = "SaslServlet.ID";
private static final String ATTR_SASL_SERVER = "SaslServlet.SaslServer";
private static final String ATTR_EXPIRY = "SaslServlet.Expiry";
- private static final long SASL_EXCHANGE_EXPIRY = 1000L;
+ private static final long SASL_EXCHANGE_EXPIRY = 3000L;
public SaslServlet()
{
@@ -260,7 +260,17 @@ public class SaslServlet extends AbstractServlet
session.removeAttribute(ATTR_ID);
session.removeAttribute(ATTR_SASL_SERVER);
session.removeAttribute(ATTR_EXPIRY);
+ if(challenge != null && challenge.length != 0)
+ {
+ Map<String, Object> outputObject = new LinkedHashMap<String, Object>();
+ outputObject.put("challenge", new String(Base64.encodeBase64(challenge)));
+
+ final PrintWriter writer = response.getWriter();
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, outputObject);
+ }
response.setStatus(HttpServletResponse.SC_OK);
}
else
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js
index 2d99f886ed..a25375a669 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/sasl.js
@@ -18,8 +18,8 @@
* under the License.
*
*/
-define(["dojo/_base/xhr", "dojox/encoding/base64", "dojox/encoding/digests/_base", "dojox/encoding/digests/MD5"],
- function (xhr, base64, digestsBase, MD5) {
+define(["dojo/_base/xhr", "dojox/encoding/base64", "dojox/encoding/digests/_base", "dojox/encoding/digests/MD5", "dojox/uuid/generateRandomUuid", "dojo/request/script"],
+ function (xhr, base64, digestsBase, MD5, uuid, script) {
var encodeUTF8 = function encodeUTF8(str) {
var byteArray = [];
@@ -83,34 +83,32 @@ var saslPlain = function saslPlain(user, password, callbackFunction)
var saslCramMD5 = function saslCramMD5(user, password, saslMechanism, callbackFunction)
{
-
- // Using dojo.xhrGet, as very little information is being sent
- dojo.xhrPost({
- // The URL of the request
- url: "rest/sasl",
- content: {
- mechanism: saslMechanism
- },
- handleAs: "json",
- failOk: true
- }).then(function(data)
- {
-
- var challengeBytes = base64.decode(data.challenge);
- var wa=[];
- var bitLength = challengeBytes.length*8;
- for(var i=0; i<bitLength; i+=8)
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ mechanism: saslMechanism
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function(data)
{
- wa[i>>5] |= (challengeBytes[i/8] & 0xFF)<<(i%32);
- }
- var challengeStr = digestsBase.wordToString(wa).substring(0,challengeBytes.length);
- var digest = user + " " + MD5._hmac(challengeStr, password, digestsBase.outputTypes.Hex);
- var id = data.id;
+ var challengeBytes = base64.decode(data.challenge);
+ var wa=[];
+ var bitLength = challengeBytes.length*8;
+ for(var i=0; i<bitLength; i+=8)
+ {
+ wa[i>>5] |= (challengeBytes[i/8] & 0xFF)<<(i%32);
+ }
+ var challengeStr = digestsBase.wordToString(wa).substring(0,challengeBytes.length);
+
+ var digest = user + " " + MD5._hmac(challengeStr, password, digestsBase.outputTypes.Hex);
+ var id = data.id;
- var response = base64.encode(encodeUTF8( digest ));
+ var response = base64.encode(encodeUTF8( digest ));
- dojo.xhrPost({
+ dojo.xhrPost({
// The URL of the request
url: "rest/sasl",
content: {
@@ -121,20 +119,163 @@ var saslCramMD5 = function saslCramMD5(user, password, saslMechanism, callbackFu
failOk: true
}).then(callbackFunction, errorHandler);
- },
- function(error)
- {
- if(error.status == 403)
+ },
+ function(error)
{
- alert("Authentication Failed");
- }
- else
- {
- alert(error);
- }
- });
+ if(error.status == 403)
+ {
+ alert("Authentication Failed");
+ }
+ else
+ {
+ alert(error);
+ }
+ });
+
+
+
};
+ var saslScramSha1 = function saslScramSha1(user, password, saslMechanism, callbackFunction)
+ {
+
+ script.get("webjars/cryptojs/3.1.2/rollups/hmac-sha1.js").then( function()
+ {
+ script.get("webjars/cryptojs/3.1.2/components/enc-base64-min.js").then ( function()
+ {
+
+ var toBase64 = function toBase64( input )
+ {
+ var result = [];
+ for(var i = 0; i < input.length; i++)
+ {
+ result[i] = input.charCodeAt(i);
+ }
+ return base64.encode( result )
+ };
+
+ var fromBase64 = function fromBase64( input )
+ {
+ var decoded = base64.decode( input );
+ var result = "";
+ for(var i = 0; i < decoded.length; i++)
+ {
+ result+= String.fromCharCode(decoded[i]);
+ }
+ return result;
+ };
+
+ var xor = function xor(lhs, rhs) {
+ var words = [];
+ for(var i = 0; i < lhs.words.length; i++)
+ {
+ words.push(lhs.words[i]^rhs.words[i]);
+ }
+ return CryptoJS.lib.WordArray.create(words);
+ };
+
+ var hasNonAscii = function hasNonAscii(name) {
+ for(var i = 0; i < name.length; i++) {
+ if(name.charCodeAt(i) > 127) {
+ return true;
+ }
+ }
+ return false;
+ };
+
+ var generateSaltedPassword = function generateSaltedPassword(salt, password, iterationCount)
+ {
+ var hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA1, password);
+
+ hmac.update(salt);
+ hmac.update(CryptoJS.enc.Hex.parse("00000001"));
+
+ var result = hmac.finalize();
+ var previous = null;
+ for(var i = 1 ;i < iterationCount; i++)
+ {
+ hmac = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA1, password);
+ hmac.update( previous != null ? previous : result );
+ previous = hmac.finalize();
+ result = xor(result, previous);
+ }
+ return result;
+
+ };
+
+ GS2_HEADER = "n,,";
+
+ if(!hasNonAscii(user)) {
+
+ user = user.replace(/=/g, "=3D");
+ user = user.replace(/,/g, "=2C");
+
+ clientNonce = uuid();
+ clientFirstMessageBare = "n=" + user + ",r=" + clientNonce;
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ mechanism: saslMechanism,
+ response: toBase64(GS2_HEADER + clientFirstMessageBare)
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function (data) {
+ var serverFirstMessage = fromBase64(data.challenge);
+ var id = data.id;
+
+ var parts = serverFirstMessage.split(",");
+ nonce = parts[0].substring(2);
+ if (!nonce.substr(0, clientNonce.length) == clientNonce) {
+ alert("Authentication error - server nonce does not start with client nonce")
+ }
+ else {
+ var salt = CryptoJS.enc.Base64.parse(parts[1].substring(2));
+ var iterationCount = parts[2].substring(2);
+ var saltedPassword = generateSaltedPassword(salt, password, iterationCount)
+ var clientFinalMessageWithoutProof = "c=" + toBase64(GS2_HEADER) + ",r=" + nonce;
+ var authMessage = clientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof;
+ var clientKey = CryptoJS.HmacSHA1("Client Key", saltedPassword);
+ var storedKey = CryptoJS.SHA1(clientKey);
+ var clientSignature = CryptoJS.HmacSHA1(authMessage, storedKey);
+ var clientProof = xor(clientKey, clientSignature);
+ var serverKey = CryptoJS.HmacSHA1("Server Key", saltedPassword);
+ serverSignature = CryptoJS.HmacSHA1(authMessage, serverKey);
+ dojo.xhrPost({
+ // The URL of the request
+ url: "rest/sasl",
+ content: {
+ id: id,
+ response: toBase64(clientFinalMessageWithoutProof
+ + ",p=" + clientProof.toString(CryptoJS.enc.Base64))
+ },
+ handleAs: "json",
+ failOk: true
+ }).then(function (data) {
+ var serverFinalMessage = fromBase64(data.challenge);
+ if (serverSignature.toString(CryptoJS.enc.Base64) == serverFinalMessage.substring(2)) {
+ callbackFunction();
+ }
+ else {
+ errorHandler("Server signature did not match");
+ }
+
+
+ }, errorHandler);
+ }
+
+ }, errorHandler);
+ }
+ else
+ {
+ alert("Username '"+name+"' is invalid");
+ }
+
+ }, errorHandler);
+ }, errorHandler);
+ };
+
var containsMechanism = function containsMechanism(mechanisms, mech)
{
for (var i = 0; i < mechanisms.length; i++) {
@@ -157,7 +298,11 @@ SaslClient.authenticate = function(username, password, callbackFunction)
}).then(function(data)
{
var mechMap = data.mechanisms;
- if (containsMechanism(mechMap, "CRAM-MD5"))
+ if(containsMechanism(mechMap, "SCRAM-SHA-1"))
+ {
+ saslScramSha1(username, password, "SCRAM-SHA-1", callbackFunction)
+ }
+ else if (containsMechanism(mechMap, "CRAM-MD5"))
{
saslCramMD5(username, password, "CRAM-MD5", callbackFunction);
}
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
index 3d349830ac..6d83a68fb4 100644
--- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
+++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
@@ -140,7 +140,7 @@ define(["dojo/_base/xhr",
util.isProviderManagingUsers = function(type)
{
- return (type === "PlainPasswordFile" || type === "Base64MD5PasswordFile");
+ return (type === "PlainPasswordFile" || type === "Base64MD5PasswordFile" || type === "SCRAM-SHA1");
};
util.showSetAttributesDialog = function(attributeWidgetFactories, data, putURL, dialogTitle, appendNameToUrl)
diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
index 7b0a48cac1..5a7674d4fd 100644
--- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
+++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanInvocationHandlerImpl.java
@@ -60,15 +60,15 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler
private MBeanServer _mbs;
private final boolean _managementRightsInferAllAccess;
- private final Broker _broker;
+ private final Broker<?> _broker;
- MBeanInvocationHandlerImpl(Broker broker)
+ MBeanInvocationHandlerImpl(Broker<?> broker)
{
_managementRightsInferAllAccess = Boolean.valueOf(System.getProperty(BrokerProperties.PROPERTY_MANAGEMENT_RIGHTS_INFER_ALL_ACCESS, "true"));
_broker = broker;
}
- public static MBeanServerForwarder newProxyInstance(Broker broker)
+ public static MBeanServerForwarder newProxyInstance(Broker<?> broker)
{
final InvocationHandler handler = new MBeanInvocationHandlerImpl(broker);
final Class<?>[] interfaces = new Class[] { MBeanServerForwarder.class };
@@ -195,28 +195,23 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler
String methodName;
// Get the component, type and impact, which may be null
String type = getType(method, args);
- String vhost = getVirtualHost(method, args);
+ String virtualHostName = getVirtualHost(method, args);
int impact = getImpact(method, args);
- // Get the security manager for the virtual host (if set)
- SecurityManager security;
- if (vhost == null)
+ if (virtualHostName != null)
{
- security = _broker.getSecurityManager();
- }
- else
- {
- VirtualHost virtualHost = _broker.findVirtualHostByName(vhost);
+ VirtualHost<?> virtualHost = _broker.findVirtualHostByName(virtualHostName);
if (virtualHost == null)
{
- throw new IllegalArgumentException("Virtual host with name '" + vhost + "' is not found.");
+ throw new IllegalArgumentException("Virtual host with name '" + virtualHostName + "' is not found.");
}
- security = virtualHost.getSecurityManager();
}
methodName = getMethodName(method, args);
Operation operation = (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO) ? Operation.ACCESS : Operation.UPDATE;
- security.authoriseMethod(operation, type, methodName);
+
+ SecurityManager security = _broker.getSecurityManager();
+ security.authoriseMethod(operation, type, methodName, virtualHostName);
if (_managementRightsInferAllAccess)
{
diff --git a/qpid/java/build.deps b/qpid/java/build.deps
index f4496ce8ab..a0efbea658 100644
--- a/qpid/java/build.deps
+++ b/qpid/java/build.deps
@@ -57,6 +57,8 @@ jetty-servlet=lib/required/jetty-servlet-8.1.14.v20131031.jar
jetty-websocket=lib/required/jetty-websocket-8.1.14.v20131031.jar
servlet-api=${geronimo-servlet}
+cryptojs=lib/required/cryptojs-3.1.2.jar
+
dojo-version=1.9.1
dojo=lib/required/dojo-${dojo-version}.zip
@@ -80,7 +82,7 @@ broker-core.libs=${commons-cli} ${commons-logging} ${log4j} ${slf4j-log4j} \
#Borrow the broker-core libs, hack for release binary generation
broker.libs=${broker-core.libs}
-broker-plugins-management-http.libs=${dojo}
+broker-plugins-management-http.libs=${dojo} ${cryptojs}
broker-plugins.libs=${log4j} ${commons.libs}
test.libs=${slf4j-log4j} ${log4j} ${junit} ${slf4j-api} ${mockito-all}
diff --git a/qpid/java/client/src/main/java/client.bnd b/qpid/java/client/src/main/java/client.bnd
index 63b1e3b34c..c2abcd55b5 100755
--- a/qpid/java/client/src/main/java/client.bnd
+++ b/qpid/java/client/src/main/java/client.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.27.0
+ver: 0.29.0
Bundle-SymbolicName: qpid-client
Bundle-Version: ${ver}
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties b/qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
index 8855a040ea..109ff9942a 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/security/CallbackHandlerRegistry.properties
@@ -31,3 +31,5 @@ CRAM-MD5.4=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
AMQPLAIN.5=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
PLAIN.6=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
ANONYMOUS.7=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
+SCRAM-SHA1.8=org.apache.qpid.client.security.UsernamePasswordCallbackHandler
+
diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties b/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
index b903208927..c2cd671bdf 100644
--- a/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
+++ b/qpid/java/client/src/main/java/org/apache/qpid/client/security/DynamicSaslRegistrar.properties
@@ -19,3 +19,4 @@
AMQPLAIN=org.apache.qpid.client.security.amqplain.AmqPlainSaslClientFactory
CRAM-MD5-HASHED=org.apache.qpid.client.security.crammd5hashed.CRAMMD5HashedSaslClientFactory
ANONYMOUS=org.apache.qpid.client.security.anonymous.AnonymousSaslClientFactory
+SCRAM-SHA1=org.apache.qpid.client.security.scram.ScramSHA1SaslClientFactory
diff --git a/qpid/java/common.xml b/qpid/java/common.xml
index 889cf3c4d8..87b8f2d175 100644
--- a/qpid/java/common.xml
+++ b/qpid/java/common.xml
@@ -24,9 +24,9 @@
<property name="project.name" value="qpid"/>
<!-- Version used for standard build output -->
- <property name="project.version" value="0.27"/>
+ <property name="project.version" value="0.29"/>
<!-- The release version used for maven output. SNAPSHOT added via maven.version.suffix -->
- <property name="project.version.maven" value="0.28"/>
+ <property name="project.version.maven" value="0.30"/>
<property name="project.url" value="http://qpid.apache.org"/>
<property name="project.groupid" value="org.apache.qpid"/>
<property name="project.namever" value="${project.name}-${project.version}"/>
diff --git a/qpid/java/common/src/main/java/common.bnd b/qpid/java/common/src/main/java/common.bnd
index 76ee9d740f..498562f3c1 100755
--- a/qpid/java/common/src/main/java/common.bnd
+++ b/qpid/java/common/src/main/java/common.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.27.0
+ver: 0.29.0
Bundle-SymbolicName: qpid-common
Bundle-Version: ${ver}
diff --git a/qpid/java/ivy.retrieve.xml b/qpid/java/ivy.retrieve.xml
index dcb97fcf9f..e604023940 100644
--- a/qpid/java/ivy.retrieve.xml
+++ b/qpid/java/ivy.retrieve.xml
@@ -70,6 +70,7 @@
<dependency org="xalan" name="xalan" rev="2.7.0" transitive="false"/>
<dependency org="velocity" name="velocity" rev="1.4" transitive="false"/>
<dependency org="velocity" name="velocity-dep" rev="1.4" transitive="false"/>
+ <dependency org="org.webjars" name="cryptojs" rev="3.1.2" transitive="false"/>
<dependency org="org.dojotoolkit" name="dojo" rev="1.9.1" transitive="false">
<artifact name="dojo" type="zip"/>
</dependency>
diff --git a/qpid/java/management/common/src/main/java/management-common.bnd b/qpid/java/management/common/src/main/java/management-common.bnd
index 459c3e60a8..cb080c9680 100644
--- a/qpid/java/management/common/src/main/java/management-common.bnd
+++ b/qpid/java/management/common/src/main/java/management-common.bnd
@@ -17,7 +17,7 @@
# under the License.
#
-ver: 0.27.0
+ver: 0.29.0
Bundle-SymbolicName: qpid-management-common
Bundle-Version: ${ver}
diff --git a/qpid/java/maven/qpid-enforcer-plugin-rules/pom.xml b/qpid/java/maven/qpid-enforcer-plugin-rules/pom.xml
new file mode 100644
index 0000000000..47a393b888
--- /dev/null
+++ b/qpid/java/maven/qpid-enforcer-plugin-rules/pom.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.apache.qpid.enforcer</groupId>
+ <artifactId>qpid-enforcer-plugin-rules</artifactId>
+ <version>1.0-SNAPSHOT</version>
+ <name>Qpid Maven Enforcer Plugin Rules</name>
+ <description>Custom maven enforcer plugin rules for the Qpid maven build.</description>
+
+ <properties>
+ <api.version>1.3.1</api.version>
+ <maven.version>2.2.1</maven.version>
+ <plexus.container.version>1.5.5</plexus.container.version>
+ <junit.version>4.11</junit.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven.enforcer</groupId>
+ <artifactId>enforcer-rules</artifactId>
+ <version>${api.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>1.3.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.enforcer</groupId>
+ <artifactId>enforcer-api</artifactId>
+ <version>${api.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-project</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-plugin-api</artifactId>
+ <version>${maven.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-container-default</artifactId>
+ <version>${plexus.container.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven.enforcer</groupId>
+ <artifactId>enforcer-rules</artifactId>
+ <version>${api.version}</version>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ </build>
+
+</project>
diff --git a/qpid/java/maven/qpid-enforcer-plugin-rules/src/main/java/org/apache/qpid/maven/enforcer/rule/RequireFileContentsAreEquivalent.java b/qpid/java/maven/qpid-enforcer-plugin-rules/src/main/java/org/apache/qpid/maven/enforcer/rule/RequireFileContentsAreEquivalent.java
new file mode 100644
index 0000000000..11186a5c7f
--- /dev/null
+++ b/qpid/java/maven/qpid-enforcer-plugin-rules/src/main/java/org/apache/qpid/maven/enforcer/rule/RequireFileContentsAreEquivalent.java
@@ -0,0 +1,104 @@
+/**
+ 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.maven.enforcer.rule;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.enforcer.rule.api.EnforcerRule;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleHelper;
+import org.apache.maven.plugins.enforcer.AbstractStandardEnforcerRule;
+
+public class RequireFileContentsAreEquivalent extends AbstractStandardEnforcerRule
+{
+
+ final static String WHITESPACE_REGEX = "\\s+";
+ final static String EMPTY_STRING = "";
+
+ File[] files;
+
+ @Override
+ public void execute(final EnforcerRuleHelper enforcerRuleHelper) throws EnforcerRuleException
+ {
+ if (files.length < 2)
+ {
+ throw new EnforcerRuleException("The file list must contain at least two files for comparison.");
+ }
+
+ boolean success = true;
+ boolean firstTime = true;
+ String referenceContent = null;
+
+ for (final File file : files)
+ {
+ try
+ {
+ final String fileContent = FileUtils.readFileToString(file);
+ if (firstTime)
+ {
+ referenceContent = fileContent;
+ firstTime = false;
+ }
+ else if (referenceContent != null && fileContent != null)
+ {
+ final String strippedReferenceContent = referenceContent.replaceAll(WHITESPACE_REGEX, EMPTY_STRING);
+ final String strippedFileContent = fileContent.replaceAll(WHITESPACE_REGEX, EMPTY_STRING);
+ if (!strippedReferenceContent.equalsIgnoreCase(strippedFileContent))
+ {
+ success = false;
+ break;
+ }
+ }
+ else
+ {
+ throw new EnforcerRuleException("Unable to read file contents");
+ }
+ }
+ catch (final IOException ioe)
+ {
+ throw new EnforcerRuleException("Cannot process file : " + file.getName(), ioe);
+ }
+ }
+
+ if (!success)
+ {
+ throw new EnforcerRuleException("Files specified are not equal in content");
+ }
+ }
+
+ @Override
+ public String getCacheId()
+ {
+ return Integer.toString(Arrays.hashCode(files));
+ }
+
+ @Override
+ public boolean isCacheable()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isResultValid(EnforcerRule arg0)
+ {
+ return true;
+ }
+
+}
diff --git a/qpid/java/maven/qpid-enforcer-plugin-rules/src/test/java/org/apache/qpid/maven/enforcer/rule/TestRequireFileContentsAreEquivalent.java b/qpid/java/maven/qpid-enforcer-plugin-rules/src/test/java/org/apache/qpid/maven/enforcer/rule/TestRequireFileContentsAreEquivalent.java
new file mode 100644
index 0000000000..7a5d214972
--- /dev/null
+++ b/qpid/java/maven/qpid-enforcer-plugin-rules/src/test/java/org/apache/qpid/maven/enforcer/rule/TestRequireFileContentsAreEquivalent.java
@@ -0,0 +1,149 @@
+/**
+ 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.maven.enforcer.rule;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
+import org.apache.maven.plugins.enforcer.EnforcerTestUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestRequireFileContentsAreEquivalent
+{
+ final RequireFileContentsAreEquivalent rule = new RequireFileContentsAreEquivalent();
+
+ final static String TEST_TEXT = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
+ final static String TEST_TEXT_WHITESPACE = "Lorem ipsum dolor sit amet,\n consectetur adipiscing \t elit. ";
+ final static String ALTERNATE_TEST_TEXT_WHITESPACE = " Lorem \t ip sum dolor \n sit amet,\n consectetur adipiscing \t elit.";
+ final static String DIFFERENT_TEST_TEXT = "Donec velit felis, semper dapibus mattis vitae";
+
+ @Test
+ public void testDifferentContentFiles() throws Exception
+ {
+ final File f1 = createTestFile(1, TEST_TEXT);
+ final File f2 = createTestFile(2, DIFFERENT_TEST_TEXT);
+
+ rule.files = new File[]
+ { f1, f2 };
+
+ try
+ {
+ rule.execute(EnforcerTestUtils.getHelper());
+ Assert.fail("Files with different content should have failed enforcer rule");
+ }
+ catch (final EnforcerRuleException ere)
+ {
+ // do nothing
+ }
+ }
+
+ @Test
+ public void testIdenticalContentFiles() throws Exception
+ {
+ final File f1 = createTestFile(1, TEST_TEXT);
+ final File f2 = createTestFile(2, TEST_TEXT);
+
+ rule.files = new File[]
+ { f1, f2 };
+
+ rule.execute(EnforcerTestUtils.getHelper());
+ }
+
+ @Test
+ public void testUsingOneFileTwice() throws Exception
+ {
+ final File f1 = createTestFile(1, TEST_TEXT);
+
+ rule.files = new File[]
+ { f1, f1 };
+
+ rule.execute(EnforcerTestUtils.getHelper());
+ }
+
+ @Test
+ public void testSimilarFiles() throws Exception
+ {
+ final File f1 = createTestFile(1, TEST_TEXT);
+ final File f2 = createTestFile(2, TEST_TEXT_WHITESPACE);
+
+ rule.files = new File[]
+ { f1, f2 };
+
+ rule.execute(EnforcerTestUtils.getHelper());
+ }
+
+ @Test
+ public void testMultipleFilesOneDifferent() throws Exception
+ {
+ final File f1 = createTestFile(1, TEST_TEXT);
+ final File f2 = createTestFile(2, TEST_TEXT_WHITESPACE);
+ final File f3 = createTestFile(3, ALTERNATE_TEST_TEXT_WHITESPACE);
+ final File f4 = createTestFile(4, DIFFERENT_TEST_TEXT);
+
+ rule.files = new File[]
+ { f1, f2, f3, f4 };
+
+ try
+ {
+ rule.execute(EnforcerTestUtils.getHelper());
+ Assert.fail("Files with different content should have failed enforcer rule");
+ }
+ catch (final EnforcerRuleException ere)
+ {
+ // do nothing
+ }
+ }
+
+ @Test
+ public void testMultipleFilesAllSimilar() throws Exception
+ {
+ final File f1 = createTestFile(1, TEST_TEXT);
+ final File f2 = createTestFile(2, TEST_TEXT);
+ final File f3 = createTestFile(3, TEST_TEXT_WHITESPACE);
+ final File f4 = createTestFile(4, ALTERNATE_TEST_TEXT_WHITESPACE);
+
+ rule.files = new File[]
+ { f1, f2, f3, f4 };
+
+ rule.execute(EnforcerTestUtils.getHelper());
+ }
+
+ @After
+ public void deleteTestFiles() throws Exception
+ {
+ for (File file : rule.files)
+ {
+ if (file.exists())
+ {
+ file.delete();
+ }
+ }
+ }
+
+ private File createTestFile(final int id, final String content) throws IOException
+ {
+ final File file = File.createTempFile(TestRequireFileContentsAreEquivalent.class.getName() +
+ "-testfile" + id, "tmp");
+ file.deleteOnExit();
+ FileUtils.writeStringToFile(file, content);
+ return file;
+ }
+}
diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml
index f5fe52e5e1..7c99ea6c85 100644
--- a/qpid/java/pom.xml
+++ b/qpid/java/pom.xml
@@ -54,7 +54,7 @@
<notice.text>Apache Qpid${line.separator}Copyright ${project.inceptionYear}-2014${line.separator}Apache Software Foundation${line.separator}This product includes software developed at Apache Software Foundation (http://www.apache.org/)</notice.text>
<!-- enforcer plugin config properties -->
- <supported-test-profiles-regex>(java-mms.0-9|java-mms.0-9-1|java-mms.0-10|java-bdb.0-9|java-bdb.0-9-1|java-bdb.0-10|java-dby-mem.0-9|java-dby-mem.0-9-1|java-dby-mem.0-10)</supported-test-profiles-regex>
+ <supported-test-profiles-regex>(java-mms.0-9|java-mms.0-9-1|java-mms.0-10|java-bdb.0-9|java-bdb.0-9-1|java-bdb.0-10|java-dby.0-9|java-dby.0-9-1|java-dby.0-10|java-dby-mem.0-9|java-dby-mem.0-9-1|java-dby-mem.0-10)</supported-test-profiles-regex>
<!-- plugin properties-->
<license-maven-plugin-output-dir>${project.build.directory}/generated-licenses</license-maven-plugin-output-dir>
@@ -64,12 +64,21 @@
<qpid.home>${basedir}</qpid.home> <!-- override for broker tests -->
<qpid.home.qbtc.output>${qpid.home}${file.separator}target${file.separator}qbtc-output</qpid.home.qbtc.output> <!-- override for broker tests -->
<qpid.work>${project.build.directory}${file.separator}QPID_WORK</qpid.work>
+
<profile>java-mms.0-10</profile>
- <profile.excludes>JavaTransientExcludes Java010Excludes</profile.excludes>
+ <profile.broker.language>java</profile.broker.language>
+ <profile.broker.type>internal</profile.broker.type>
+ <profile.broker.stopped>Exception</profile.broker.stopped>
+ <profile.broker.ready>BRK-1004</profile.broker.ready>
+ <profile.broker.command>${qpid.home}${file.separator}bin${file.separator}qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE</profile.broker.command>
+ <profile.broker.command.windows>${qpid.home}${file.separator}bin${file.separator}qpid-server.bat -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE</profile.broker.command.windows>
+ <profile.test.excludes>Excludes JavaExcludes ${profile}.excludes ${profile.specific.excludes}</profile.test.excludes>
+ <profile.specific.excludes>JavaTransientExcludes Java010Excludes</profile.specific.excludes>
<profile.broker.version>v0_10</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>false</profile.broker.persistent>
<profile.messagestore.type>Memory</profile.messagestore.type>
+ <profile.broker.clean.between.tests>true</profile.broker.clean.between.tests>
</properties>
<modules>
@@ -146,7 +155,11 @@
<tasks>
<echo>Qpid Test Profile Properties</echo>
<echo>[profile] ${profile}</echo>
- <echo>[profile.excludes] ${profile.excludes}</echo>
+ <echo>[profile.broker.language] ${profile.broker.language}</echo>
+ <echo>[profile.broker.type] ${profile.broker.type}</echo>
+ <echo>[profile.broker.command] ${profile.broker.command}</echo>
+ <echo>[profile.specific.excludes] ${profile.specific.excludes}</echo>
+ <echo>[profile.test.excludes] ${profile.test.excludes}</echo>
<echo>[profile.broker.version] ${profile.broker.version}</echo>
<echo>[profile.qpid.broker_default_amqp_protocol_excludes] ${profile.qpid.broker_default_amqp_protocol_excludes}</echo>
<echo>[profile.broker.persistent] ${profile.broker.persistent}</echo>
@@ -216,20 +229,21 @@
<test.exclude>true</test.exclude>
<test.mem>512M</test.mem>
<profile.clustered>false</profile.clustered>
- <broker.language>java</broker.language>
- <broker.type>internal</broker.type>
- <broker.stopped>Exception</broker.stopped>
- <broker.ready>BRK-1004</broker.ready>
- <broker.command>${qpid.home}${file.separator}bin${file.separator}qpid-server -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE</broker.command>
- <broker.command.windows>${qpid.home}${file.separator}bin${file.separator}qpid-server.bat -sp @STORE_PATH -st @STORE_TYPE -l @LOG_CONFIG_FILE</broker.command.windows>
<!-- Profile Based Values -->
- <test.excludes>Excludes JavaExcludes ${profile}.excludes ${profile.excludes}</test.excludes>
+ <profile>${profile}</profile>
+ <broker.language>${profile.broker.language}</broker.language>
+ <broker.type>${profile.broker.type}</broker.type>
+ <broker.stopped>${profile.broker.stopped}</broker.stopped>
+ <broker.ready>${profile.broker.ready}</broker.ready>
+ <broker.command>${profile.broker.command}</broker.command>
+ <broker.command.windows>${profile.broker.command.windows}</broker.command.windows>
+ <test.excludes>${profile.test.excludes}</test.excludes>
<broker.version>${profile.broker.version}</broker.version>
<qpid.broker_default_amqp_protocol_excludes>${profile.qpid.broker_default_amqp_protocol_excludes}</qpid.broker_default_amqp_protocol_excludes>
<broker.persistent>${profile.broker.persistent}</broker.persistent>
<messagestore.type>${profile.messagestore.type}</messagestore.type>
- <profile>${profile}</profile>
+ <broker.clean.between.tests>${profile.broker.clean.between.tests}</broker.clean.between.tests>
<!-- This must be a child of qpid home currently due to the horrible mechanics of QBTC -->
<test.output>${qpid.home.qbtc.output}</test.output>
@@ -417,7 +431,7 @@
</activation>
<properties>
<profile>java-mms.0-10</profile>
- <profile.excludes>JavaTransientExcludes Java010Excludes</profile.excludes>
+ <profile.specific.excludes>JavaTransientExcludes Java010Excludes</profile.specific.excludes>
<profile.broker.version>v0_10</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>false</profile.broker.persistent>
@@ -435,7 +449,7 @@
</activation>
<properties>
<profile>java-mms.0-9-1</profile>
- <profile.excludes>JavaTransientExcludes XAExcludes JavaPre010Excludes</profile.excludes>
+ <profile.specific.excludes>JavaTransientExcludes XAExcludes JavaPre010Excludes</profile.specific.excludes>
<profile.broker.version>v0_9_1</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>false</profile.broker.persistent>
@@ -453,7 +467,7 @@
</activation>
<properties>
<profile>java-mms.0-9</profile>
- <profile.excludes>JavaTransientExcludes XAExcludes JavaPre010Excludes</profile.excludes>
+ <profile.specific.excludes>JavaTransientExcludes XAExcludes JavaPre010Excludes</profile.specific.excludes>
<profile.broker.version>v0_9</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10,AMQP_0_9_1</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>false</profile.broker.persistent>
@@ -471,7 +485,7 @@
</activation>
<properties>
<profile>java-bdb.0-10</profile>
- <profile.excludes>JavaPersistentExcludes Java010Excludes JavaBDBExcludes</profile.excludes>
+ <profile.specific.excludes>JavaPersistentExcludes Java010Excludes JavaBDBExcludes</profile.specific.excludes>
<profile.broker.version>v0_10</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>true</profile.broker.persistent>
@@ -489,7 +503,7 @@
</activation>
<properties>
<profile>java-bdb.0-9-1</profile>
- <profile.excludes>JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes</profile.excludes>
+ <profile.specific.excludes>JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes</profile.specific.excludes>
<profile.broker.version>v0_9_1</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>true</profile.broker.persistent>
@@ -507,7 +521,7 @@
</activation>
<properties>
<profile>java-bdb.0-9</profile>
- <profile.excludes>JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes</profile.excludes>
+ <profile.specific.excludes>JavaPersistentExcludes XAExcludes JavaPre010Excludes JavaBDBExcludes</profile.specific.excludes>
<profile.broker.version>v0_9</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10,AMQP_0_9_1</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>true</profile.broker.persistent>
@@ -525,7 +539,7 @@
</activation>
<properties>
<profile>java-dby-mem.0-10</profile>
- <profile.excludes>JavaPersistentExcludes JavaDerbyExcludes Java010Excludes</profile.excludes>
+ <profile.specific.excludes>JavaPersistentExcludes JavaDerbyExcludes Java010Excludes</profile.specific.excludes>
<profile.broker.version>v0_10</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>true</profile.broker.persistent>
@@ -543,7 +557,7 @@
</activation>
<properties>
<profile>java-dby-mem.0-9-1</profile>
- <profile.excludes>JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes</profile.excludes>
+ <profile.specific.excludes>JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes</profile.specific.excludes>
<profile.broker.version>v0_9_1</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>true</profile.broker.persistent>
@@ -561,7 +575,7 @@
</activation>
<properties>
<profile>java-dby-mem.0-9</profile>
- <profile.excludes>JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes</profile.excludes>
+ <profile.specific.excludes>JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes</profile.specific.excludes>
<profile.broker.version>v0_9</profile.broker.version>
<profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10,AMQP_0_9_1</profile.qpid.broker_default_amqp_protocol_excludes>
<profile.broker.persistent>true</profile.broker.persistent>
@@ -569,6 +583,63 @@
</properties>
</profile>
+ <profile>
+ <id>java-dby.0-10</id>
+ <activation>
+ <property>
+ <name>profile</name>
+ <value>java-dby.0-10</value>
+ </property>
+ </activation>
+ <properties>
+ <profile>java-dby.0-10</profile>
+ <profile.specific.excludes>JavaPersistentExcludes JavaDerbyExcludes Java010Excludes</profile.specific.excludes>
+ <profile.broker.version>v0_10</profile.broker.version>
+ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0</profile.qpid.broker_default_amqp_protocol_excludes>
+ <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-derby.xml</profile.broker.virtualhosts-config>
+ <profile.broker.persistent>true</profile.broker.persistent>
+ <profile.messagestore.class.name>org.apache.qpid.server.store.derby.DerbyMessageStore</profile.messagestore.class.name>
+ </properties>
+ </profile>
+
+ <profile>
+ <id>java-dby.0-9-1</id>
+ <activation>
+ <property>
+ <name>profile</name>
+ <value>java-dby.0-9-1</value>
+ </property>
+ </activation>
+ <properties>
+ <profile>java-dby.0-9-1</profile>
+ <profile.specific.excludes>JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes</profile.specific.excludes>
+ <profile.broker.version>v0_9_1</profile.broker.version>
+ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10</profile.qpid.broker_default_amqp_protocol_excludes>
+ <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-derby.xml</profile.broker.virtualhosts-config>
+ <profile.broker.persistent>true</profile.broker.persistent>
+ <profile.messagestore.class.name>org.apache.qpid.server.store.derby.DerbyMessageStore</profile.messagestore.class.name>
+ </properties>
+ </profile>
+
+ <profile>
+ <id>java-dby.0-9</id>
+ <activation>
+ <property>
+ <name>profile</name>
+ <value>java-dby.0-9</value>
+ </property>
+ </activation>
+ <properties>
+ <profile>java-dby.0-9</profile>
+ <profile.specific.excludes>JavaPersistentExcludes JavaDerbyExcludes XAExcludes JavaPre010Excludes</profile.specific.excludes>
+ <profile.broker.version>v0_9</profile.broker.version>
+ <profile.qpid.broker_default_amqp_protocol_excludes>AMQP_1_0,AMQP_0_10,AMQP_0_9_1</profile.qpid.broker_default_amqp_protocol_excludes>
+ <profile.broker.virtualhosts-config>${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests-derby.xml</profile.broker.virtualhosts-config>
+ <profile.broker.persistent>true</profile.broker.persistent>
+ <profile.messagestore.class.name>org.apache.qpid.server.store.derby.DerbyMessageStore</profile.messagestore.class.name>
+ </properties>
+ </profile>
+
</profiles>
</project>
diff --git a/qpid/java/qpid-perftests-systests/pom.xml b/qpid/java/qpid-perftests-systests/pom.xml
index 6856fd9d17..4557e903ff 100644
--- a/qpid/java/qpid-perftests-systests/pom.xml
+++ b/qpid/java/qpid-perftests-systests/pom.xml
@@ -86,6 +86,20 @@
<scope>runtime</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid-bdbstore</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <optional>true</optional>
+ </dependency>
+
+ <dependency>
+ <groupId>com.sleepycat</groupId>
+ <artifactId>je</artifactId>
+ <scope>test</scope>
+ <optional>true</optional>
+ </dependency>
</dependencies>
<build>
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java
index 37f960a65a..a0188626ee 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/AccessControlLoggingTest.java
@@ -49,8 +49,7 @@ public class AccessControlLoggingTest extends AbstractTestLogging
public void setUp() throws Exception
{
// Write out ACL for this test
- AbstractACLTestCase.writeACLFileUtil(this, "test",
- "ACL ALLOW client ACCESS VIRTUALHOST",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW client ACCESS VIRTUALHOST",
"ACL ALLOW client CREATE QUEUE name='allow'",
"ACL ALLOW-LOG client CREATE QUEUE name='allow-log'",
"ACL DENY client CREATE QUEUE name='deny'",
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
index 72626e5089..789ad420d8 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/AbstractACLTestCase.java
@@ -24,9 +24,7 @@ import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQConnectionURL;
import org.apache.qpid.jms.ConnectionListener;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.test.utils.QpidBrokerTestCase;
-import org.apache.qpid.test.utils.TestBrokerConfiguration;
import org.apache.qpid.url.URLSyntaxException;
import javax.jms.Connection;
@@ -45,12 +43,10 @@ import java.util.concurrent.TimeUnit;
/**
* Abstract test case for ACLs.
- *
+ *
* This base class contains convenience methods to manage ACL files and implements a mechanism that allows each
* test method to run its own setup code before the broker starts.
- *
- * TODO move the pre broker-startup setup method invocation code to {@link QpidBrokerTestCase}
- *
+ *
* @see ExternalACLTest
* @see ExternalACLJMXTest
* @see ExhaustiveACLTest
@@ -80,7 +76,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
{
throw (Exception) e.getTargetException();
}
-
+
super.setUp();
}
@@ -97,26 +93,18 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
//that we provoked with authentication failures, where the test passes - we can ignore on con close
}
}
-
- public void writeACLFile(final String vhost, final String...rules) throws IOException
+
+ public void writeACLFile(final String...rules) throws IOException
{
- writeACLFileUtil(this, vhost, rules);
+ writeACLFileUtil(this, rules);
}
- public static void writeACLFileUtil(QpidBrokerTestCase testcase, String vhost, String...rules) throws IOException
+ public static void writeACLFileUtil(QpidBrokerTestCase testcase, String...rules) throws IOException
{
File aclFile = File.createTempFile(testcase.getClass().getSimpleName(), testcase.getName());
aclFile.deleteOnExit();
- TestBrokerConfiguration config = testcase.getBrokerConfiguration();
- if (vhost == null)
- {
- config.addAclFileConfiguration(aclFile.getAbsolutePath());
- }
- else
- {
- config.setObjectAttribute(vhost, VirtualHost.SECURITY_ACL, aclFile.getAbsolutePath());
- }
+ testcase.getBrokerConfiguration().addAclFileConfiguration(aclFile.getAbsolutePath());
PrintWriter out = new PrintWriter(new FileWriter(aclFile));
out.println(String.format("# %s", testcase.getName()));
@@ -128,7 +116,7 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
}
/**
- * Creates a connection to the broker, and sets a connection listener to prevent failover and an exception listener
+ * Creates a connection to the broker, and sets a connection listener to prevent failover and an exception listener
* with a {@link CountDownLatch} to synchronise in the {@link #check403Exception(Throwable)} method and allow the
* {@link #tearDown()} method to complete properly.
*/
@@ -138,8 +126,8 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
//Prevent Failover
connection.setConnectionListener(this);
-
- //QPID-2081: use a latch to sync on exception causing connection close, to work
+
+ //QPID-2081: use a latch to sync on exception causing connection close, to work
//around the connection close race during tearDown() causing sporadic failures
_exceptionReceived = new CountDownLatch(1);
@@ -196,8 +184,8 @@ public abstract class AbstractACLTestCase extends QpidBrokerTestCase implements
assertNotNull("There was no linked exception", t);
assertTrue("Wrong linked exception type : " + t.getClass(), t instanceof AMQException);
assertEquals("Incorrect error code received", 403, ((AMQException) t).getErrorCode().getCode());
-
- //use the latch to ensure the control thread waits long enough for the exception thread
+
+ //use the latch to ensure the control thread waits long enough for the exception thread
//to have done enough to mark the connection closed before teardown commences
assertTrue("Timed out waiting for conneciton to report close", _exceptionReceived.await(2, TimeUnit.SECONDS));
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java
index 50c80692dd..07fe88b38f 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExhaustiveACLTest.java
@@ -39,20 +39,20 @@ public class ExhaustiveACLTest extends AbstractACLTestCase
/**
* Creates a queue.
- *
+ *
* Connects to the broker as a particular user and create the named queue on a virtual host, with the provided
* parameters. Uses a new {@link Connection} and {@link Session} and closes them afterwards.
*/
private void createQueue(String vhost, String user, String name, boolean autoDelete, boolean durable) throws Exception
{
- Connection conn = getConnection(vhost, user, "guest");
+ Connection conn = getConnection(vhost, user, "guest");
Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
conn.start();
((AMQSession<?, ?>) sess).createQueue(new AMQShortString(name), autoDelete, durable, false);
sess.commit();
conn.close();
}
-
+
/**
* Calls {@link #createQueue(String, String, String, boolean, boolean)} with the provided parameters and checks that
* no exceptions were thrown.
@@ -61,7 +61,7 @@ public class ExhaustiveACLTest extends AbstractACLTestCase
{
try
{
- createQueue(vhost, user, name, autoDelete, durable);
+ createQueue(vhost, user, name, autoDelete, durable);
}
catch (AMQException e)
{
@@ -72,7 +72,7 @@ public class ExhaustiveACLTest extends AbstractACLTestCase
/**
* Calls {@link #createQueue(String, String, String, boolean, boolean)} with the provided parameters and checks that
- * the exception thrown was an {@link AMQConstant#ACCESS_REFUSED} or 403 error code.
+ * the exception thrown was an {@link AMQConstant#ACCESS_REFUSED} or 403 error code.
*/
private void createQueueFailure(String vhost, String user, String name, boolean autoDelete, boolean durable) throws Exception
{
@@ -87,67 +87,64 @@ public class ExhaustiveACLTest extends AbstractACLTestCase
assertEquals("Should be an ACCESS_REFUSED error", 403, e.getErrorCode().getCode());
}
}
-
+
public void setUpAuthoriseCreateQueueAutodelete() throws Exception
{
- writeACLFile("test",
- "acl allow client access virtualhost",
+ writeACLFile("acl allow client access virtualhost",
"acl allow server access virtualhost",
"acl allow client create queue name=\"temp.true.*\" autodelete=true",
"acl allow client create queue name=\"temp.false.*\" autodelete=false",
- "acl deny client create queue",
- "acl allow client delete queue",
+ "acl deny client create queue",
+ "acl allow client delete queue",
"acl deny all create queue"
);
}
-
+
/**
* Test creation of temporary queues, with the autodelete property set to true.
*/
public void testAuthoriseCreateQueueAutodelete() throws Exception
{
- createQueueSuccess("test", "client", "temp.true.00", true, false);
+ createQueueSuccess("test", "client", "temp.true.00", true, false);
createQueueSuccess("test", "client", "temp.true.01", true, false);
createQueueSuccess("test", "client", "temp.true.02", true, true);
- createQueueSuccess("test", "client", "temp.false.03", false, false);
+ createQueueSuccess("test", "client", "temp.false.03", false, false);
createQueueSuccess("test", "client", "temp.false.04", false, false);
createQueueSuccess("test", "client", "temp.false.05", false, true);
- createQueueFailure("test", "client", "temp.true.06", false, false);
+ createQueueFailure("test", "client", "temp.true.06", false, false);
createQueueFailure("test", "client", "temp.false.07", true, false);
- createQueueFailure("test", "server", "temp.true.08", true, false);
+ createQueueFailure("test", "server", "temp.true.08", true, false);
createQueueFailure("test", "client", "temp.other.09", false, false);
}
-
+
public void setUpAuthoriseCreateQueue() throws Exception
{
- writeACLFile("test",
- "acl allow client access virtualhost",
+ writeACLFile("acl allow client access virtualhost",
"acl allow server access virtualhost",
"acl allow client create queue name=\"create.*\""
);
}
-
+
/**
* Tests creation of named queues.
*
- * If a named queue is specified
+ * If a named queue is specified
*/
public void testAuthoriseCreateQueue() throws Exception
{
createQueueSuccess("test", "client", "create.00", true, true);
createQueueSuccess("test", "client", "create.01", true, false);
createQueueSuccess("test", "client", "create.02", false, true);
- createQueueSuccess("test", "client", "create.03", true, false);
+ createQueueSuccess("test", "client", "create.03", true, false);
createQueueFailure("test", "server", "create.04", true, true);
createQueueFailure("test", "server", "create.05", true, false);
createQueueFailure("test", "server", "create.06", false, true);
- createQueueFailure("test", "server", "create.07", true, false);
+ createQueueFailure("test", "server", "create.07", true, false);
}
-
+
public void setUpAuthoriseCreateQueueBoth() throws Exception
{
- writeACLFile("test",
- "acl allow all access virtualhost",
+ writeACLFile("acl allow all access virtualhost",
"acl allow client create queue name=\"create.*\"",
"acl allow all create queue temporary=true"
);
@@ -156,16 +153,16 @@ public class ExhaustiveACLTest extends AbstractACLTestCase
/**
* Tests creation of named queues.
*
- * If a named queue is specified
+ * If a named queue is specified
*/
public void testAuthoriseCreateQueueBoth() throws Exception
{
createQueueSuccess("test", "client", "create.00", true, false);
createQueueSuccess("test", "client", "create.01", false, false);
createQueueFailure("test", "server", "create.02", false, false);
- createQueueFailure("test", "guest", "create.03", false, false);
+ createQueueFailure("test", "guest", "create.03", false, false);
createQueueSuccess("test", "client", "tmp.00", true, false);
- createQueueSuccess("test", "server", "tmp.01", true, false);
+ createQueueSuccess("test", "server", "tmp.01", true, false);
createQueueSuccess("test", "guest", "tmp.02", true, false);
}
}
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
index 389ac5ff4d..7a1a6cd639 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java
@@ -56,7 +56,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
super.setUp();
_jmx.open();
}
-
+
@Override
public void tearDown() throws Exception
{
@@ -66,9 +66,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
public void setUpDenyAllIsCatchAllRule() throws Exception
{
- writeACLFile(null,
- "ACL ALLOW admin ACCESS MANAGEMENT",
- "#No more rules, default catch all (deny all) should apply");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "#No more rules, default catch all (deny all) should apply");
}
public void testDenyAllIsCatchAllRule() throws Exception
@@ -107,7 +106,7 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
*/
public void setUpAllowAll() throws Exception
{
- writeACLFile(null, "ACL ALLOW ALL ALL");
+ writeACLFile("ACL ALLOW ALL ALL");
}
public void testAllowAll() throws Exception
@@ -118,24 +117,17 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
// PASS
}
- /**
- * admin user is denied at broker level but allowed at vhost level.
- */
- public void setUpVhostAllowOverridesGlobalDeny() throws Exception
+ public void setUpVhostWithName() throws Exception
{
- writeACLFile(null,
- "ACL ALLOW admin ACCESS MANAGEMENT",
- "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
- writeACLFile(TEST_VHOST,
- "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue' virtualhost_name='"+ TEST_VHOST + "'",
+ "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue' virtualhost_name='"+ TEST2_VHOST + "'");
}
- public void testVhostAllowOverridesGlobalDeny() throws Exception
+ public void testVhostWithName() throws Exception
{
- //try a vhost-level method on the allowed vhost
_jmx.createQueue(TEST_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true);
- //try a vhost-level method on a different vhost
try
{
_jmx.createQueue(TEST2_VHOST, getTestQueueName(), TEST_QUEUE_OWNER, true);
@@ -153,9 +145,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
*/
public void setUpUpdateComponentOnlyAllow() throws Exception
{
- writeACLFile(null,
- "ACL ALLOW admin ACCESS MANAGEMENT",
- "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager'");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager'");
}
public void testUpdateComponentOnlyAllow() throws Exception
@@ -172,9 +163,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
*/
public void setUpUpdateMethodOnlyAllow() throws Exception
{
- writeACLFile(null,
- "ACL ALLOW admin ACCESS MANAGEMENT",
- "ACL ALLOW admin UPDATE METHOD");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL ALLOW admin UPDATE METHOD");
}
public void testUpdateMethodOnlyAllow() throws Exception
@@ -187,12 +177,12 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
/**
- * admin user has JMX right, AMPQ right is irrelevant.
+ * admin user has JMX right, AMQP right is irrelevant.
*/
public void setUpCreateQueueSuccess() throws Exception
{
- writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT");
- writeACLFile(TEST_VHOST, "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
}
public void testCreateQueueSuccess() throws Exception
@@ -202,14 +192,13 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
/**
- * admin user has JMX right, verifies lack of AMPQ rights is irrelevant.
+ * admin user has JMX right, verifies lack of AMQP rights is irrelevant.
*/
public void setUpCreateQueueSuccessNoAMQPRights() throws Exception
{
- writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT");
- writeACLFile(TEST_VHOST,
- "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'",
- "ACL DENY admin CREATE QUEUE");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL ALLOW admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'",
+ "ACL DENY admin CREATE QUEUE");
}
public void testCreateQueueSuccessNoAMQPRights() throws Exception
@@ -219,13 +208,12 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
/**
- * admin user does not have JMX right, AMPQ right is irrelevant.
+ * admin user does not have JMX right, AMQP right is irrelevant.
*/
public void setUpCreateQueueDenied() throws Exception
{
- writeACLFile(null, "ACL ALLOW admin ACCESS MANAGEMENT");
- writeACLFile(TEST_VHOST,
- "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL DENY admin UPDATE METHOD component='VirtualHost.VirtualHostManager' name='createNewQueue'");
}
public void testCreateQueueDenied() throws Exception
@@ -247,9 +235,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
*/
public void setUpServerInformationUpdateDenied() throws Exception
{
- writeACLFile(null,
- "ACL ALLOW admin ACCESS MANAGEMENT",
- "ACL DENY admin UPDATE METHOD component='ServerInformation' name='resetStatistics'");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL DENY admin UPDATE METHOD component='ServerInformation' name='resetStatistics'");
}
public void testServerInformationUpdateDenied() throws Exception
@@ -272,9 +259,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
*/
public void setUpServerInformationAccessGranted() throws Exception
{
- writeACLFile(null,
- "ACL ALLOW admin ACCESS MANAGEMENT",
- "ACL ALLOW-LOG admin ACCESS METHOD component='ServerInformation' name='getManagementApiMajorVersion'");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL ALLOW-LOG admin ACCESS METHOD component='ServerInformation' name='getManagementApiMajorVersion'");
}
public void testServerInformationAccessGranted() throws Exception
@@ -299,9 +285,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
*/
public void setUpServerInformationUpdateMethodPermission() throws Exception
{
- writeACLFile(null,
- "ACL ALLOW admin ACCESS MANAGEMENT",
- "ACL ALLOW admin UPDATE METHOD component='ServerInformation' name='resetStatistics'");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL ALLOW admin UPDATE METHOD component='ServerInformation' name='resetStatistics'");
}
public void testServerInformationUpdateMethodPermission() throws Exception
@@ -317,9 +302,8 @@ public class ExternalACLJMXTest extends AbstractACLTestCase
*/
public void setUpServerInformationAllMethodPermissions() throws Exception
{
- writeACLFile(null,
- "ACL ALLOW admin ACCESS MANAGEMENT",
- "ACL ALLOW admin ALL METHOD component='ServerInformation'");
+ writeACLFile("ACL ALLOW admin ACCESS MANAGEMENT",
+ "ACL ALLOW admin ALL METHOD component='ServerInformation'");
}
public void testServerInformationAllMethodPermissions() throws Exception
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
index 00c85e80c8..0e8f3cb7d8 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java
@@ -18,12 +18,6 @@
*/
package org.apache.qpid.server.security.acl;
-import org.apache.qpid.AMQException;
-import org.apache.qpid.client.AMQDestination;
-import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.url.URLSyntaxException;
-
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
@@ -37,8 +31,14 @@ import javax.jms.Topic;
import javax.jms.TopicSubscriber;
import javax.naming.NamingException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.AMQDestination;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.url.URLSyntaxException;
+
/**
- * Tests the V2 ACLs. The tests perform basic AMQP operations like creating queues or excahnges and publishing and consuming messages, using
+ * Tests the V2 ACLs. The tests perform basic AMQP operations like creating queues or exchanges and publishing and consuming messages, using
* JMS to contact the broker.
*/
public class ExternalACLTest extends AbstractACLTestCase
@@ -46,65 +46,113 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpAccessAuthorizedSuccess() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST");
}
public void testAccessAuthorizedSuccess() throws Exception
{
+ Connection conn = getConnection("test", "client", "guest");
+ conn.close();
+ }
+
+ public void setUpAccessNoRightsFailure() throws Exception
+ {
+ writeACLFile("ACL DENY-LOG client ACCESS VIRTUALHOST");
+ }
+
+ public void testAccessNoRightsFailure() throws Exception
+ {
try
{
- Connection conn = getConnection("test", "client", "guest");
- Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
- conn.start();
+ getConnection("test", "client", "guest");
+ fail("Connection was created.");
+ }
+ catch (JMSException e)
+ {
+ assertAccessDeniedException(e);
+ }
+ }
- //Do something to show connection is active.
- sess.rollback();
+ private void assertAccessDeniedException(JMSException e)
+ {
+ assertEquals("Unexpected exception message", "Error creating connection: Permission denied: test", e.getMessage());
+
+ // JMSException -> linkedException -> cause = AMQException (403 or 320)
+ Exception linkedException = e.getLinkedException();
+ assertNotNull("There was no linked exception", linkedException);
+ Throwable cause = linkedException.getCause();
+ assertNotNull("Cause was null", cause);
+ assertTrue("Wrong linked exception type", cause instanceof AMQException);
+ AMQConstant errorCode = isBroker010() ? AMQConstant.CONNECTION_FORCED : AMQConstant.ACCESS_REFUSED;
+ assertEquals("Incorrect error code received", errorCode, ((AMQException) cause).getErrorCode());
+ }
+
+ public void setUpAccessVirtualHostWithName() throws Exception
+ {
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST name='test'", "ACL DENY-LOG guest ACCESS VIRTUALHOST name='test'",
+ "ACL ALLOW-LOG server ACCESS VIRTUALHOST name='*'");
+ }
- conn.close();
+ public void testAccessVirtualHostWithName() throws Exception
+ {
+ Connection conn = getConnection("test", "client", "guest");
+ conn.close();
+
+ try
+ {
+ getConnection("test", "guest", "guest");
+ fail("Access should be denied");
}
- catch (Exception e)
+ catch (JMSException e)
{
- fail("Connection was not created due to:" + e);
+ assertAccessDeniedException(e);
}
+
+ Connection conn2 = getConnection("test", "server", "guest");
+ conn2.close();
}
- public void setUpAccessNoRightsFailure() throws Exception
+ public void setUpClientCreateVirtualHostQueue() throws Exception
{
- writeACLFile("test", "ACL DENY-LOG client ACCESS VIRTUALHOST");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client CREATE QUEUE virtualhost_name='test'",
+ "ACL ALLOW-LOG client CONSUME QUEUE",
+ "ACL ALLOW-LOG client BIND EXCHANGE",
+ "ACL ALLOW-LOG guest ACCESS VIRTUALHOST",
+ "ACL DENY-LOG guest CREATE QUEUE virtualhost_name='test'");
}
- public void testAccessNoRightsFailure() throws Exception
+ public void testClientCreateVirtualHostQueue() throws NamingException, JMSException, AMQException, Exception
{
+ Connection conn = getConnection("test", "client", "guest");
+ Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ Destination dest = sess.createQueue(getTestQueueName());
+ sess.createConsumer(dest);
+ conn.close();
+
try
{
- Connection conn = getConnection("test", "guest", "guest");
- Session sess = conn.createSession(true, Session.SESSION_TRANSACTED);
- conn.start();
- sess.rollback();
+ conn = getConnection("test", "guest", "guest");
+ sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ sess.createConsumer(dest);
- fail("Connection was created.");
+ fail("Queue creation for user 'guest' is denied");
}
catch (JMSException e)
{
- // JMSException -> linkedException -> cause = AMQException (403 or 320)
- Exception linkedException = e.getLinkedException();
- assertNotNull("There was no linked exception", linkedException);
- Throwable cause = linkedException.getCause();
- assertNotNull("Cause was null", cause);
- assertTrue("Wrong linked exception type", cause instanceof AMQException);
- AMQConstant errorCode = isBroker010() ? AMQConstant.CONNECTION_FORCED : AMQConstant.ACCESS_REFUSED;
- assertEquals("Incorrect error code received", errorCode, ((AMQException) cause).getErrorCode());
+ check403Exception(e.getLinkedException());
}
}
+
public void setUpClientDeleteQueueSuccess() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL ALLOW-LOG client CREATE QUEUE durable=\"true\"" ,
- "ACL ALLOW-LOG client CONSUME QUEUE name=\"clientid:kipper\"",
- "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper",
- "ACL ALLOW-LOG client DELETE QUEUE durable=\"true\"",
- "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client CREATE QUEUE durable=\"true\"",
+ "ACL ALLOW-LOG client CONSUME QUEUE name=\"clientid:kipper\"" ,
+ "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper",
+ "ACL ALLOW-LOG client DELETE QUEUE durable=\"true\"",
+ "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper");
}
public void testClientDeleteQueueSuccess() throws Exception
@@ -128,12 +176,12 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpClientDeleteQueueFailure() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL ALLOW-LOG client CREATE QUEUE durable=\"true\"" ,
- "ACL ALLOW-LOG client CONSUME QUEUE name=\"clientid:kipper\"",
- "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper",
- "ACL DENY-LOG client DELETE QUEUE durable=\"true\"",
- "ACL DENY-LOG client UNBIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client CREATE QUEUE durable=\"true\"",
+ "ACL ALLOW-LOG client CONSUME QUEUE name=\"clientid:kipper\"" ,
+ "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper",
+ "ACL DENY-LOG client DELETE QUEUE durable=\"true\"",
+ "ACL DENY-LOG client UNBIND EXCHANGE name=\"amq.topic\" durable=true routingKey=kipper");
}
public void testClientDeleteQueueFailure() throws Exception
@@ -177,10 +225,10 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpClientConsumeFromNamedQueueValid() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL ALLOW-LOG client CREATE QUEUE name=\"example.RequestQueue\"" ,
- "ACL ALLOW-LOG client CONSUME QUEUE name=\"example.RequestQueue\"",
- "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\"");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client CREATE QUEUE name=\"example.RequestQueue\"",
+ "ACL ALLOW-LOG client CONSUME QUEUE name=\"example.RequestQueue\"" ,
+ "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\"");
}
@@ -197,10 +245,10 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpClientConsumeFromNamedQueueFailure() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL ALLOW-LOG client CREATE QUEUE" ,
- "ACL ALLOW-LOG client BIND EXCHANGE",
- "ACL DENY-LOG client CONSUME QUEUE name=\"IllegalQueue\"");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client CREATE QUEUE",
+ "ACL ALLOW-LOG client BIND EXCHANGE" ,
+ "ACL DENY-LOG client CONSUME QUEUE name=\"IllegalQueue\"");
}
public void testClientConsumeFromNamedQueueFailure() throws NamingException, Exception
@@ -224,11 +272,11 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpClientCreateTemporaryQueueSuccess() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL ALLOW-LOG client CREATE QUEUE temporary=\"true\"" ,
- "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" temporary=true",
- "ACL ALLOW-LOG client DELETE QUEUE temporary=\"true\"",
- "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.direct\" temporary=true");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client CREATE QUEUE temporary=\"true\"",
+ "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" temporary=true" ,
+ "ACL ALLOW-LOG client DELETE QUEUE temporary=\"true\"",
+ "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.direct\" temporary=true");
}
public void testClientCreateTemporaryQueueSuccess() throws JMSException, URLSyntaxException, Exception
@@ -243,8 +291,8 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpClientCreateTemporaryQueueFailed() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL DENY-LOG client CREATE QUEUE temporary=\"true\"");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL DENY-LOG client CREATE QUEUE temporary=\"true\"");
}
public void testClientCreateTemporaryQueueFailed() throws NamingException, Exception
@@ -268,9 +316,8 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpClientCreateNamedQueueFailure() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL ALLOW-LOG client CREATE QUEUE name=\"ValidQueue\"",
- "ACL ALLOW-LOG client CONSUME QUEUE");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client CREATE QUEUE name=\"ValidQueue\"");
}
public void testClientCreateNamedQueueFailure() throws NamingException, JMSException, AMQException, Exception
@@ -294,10 +341,10 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpClientPublishUsingTransactionSuccess() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL ALLOW-LOG client CREATE QUEUE" ,
- "ACL ALLOW-LOG client BIND EXCHANGE",
- "ACL ALLOW-LOG client PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\"");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client CREATE QUEUE",
+ "ACL ALLOW-LOG client BIND EXCHANGE" ,
+ "ACL ALLOW-LOG client PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\"");
}
public void testClientPublishUsingTransactionSuccess() throws Exception
@@ -329,19 +376,18 @@ public class ExternalACLTest extends AbstractACLTestCase
// We tolerate a dependency from this test to that file because its
// contents are expected to change rarely.
- writeACLFile("test", "ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST",
- "# Server side",
- "ACL ALLOW-LOG server CREATE QUEUE name=\"example.RequestQueue\"" ,
- "ACL ALLOW-LOG server BIND EXCHANGE",
- "ACL ALLOW-LOG server PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"TempQueue*\"",
- "ACL ALLOW-LOG server CONSUME QUEUE name=\"example.RequestQueue\"",
- "# Client side",
- "ACL ALLOW-LOG client PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\"",
- "ACL ALLOW-LOG client CONSUME QUEUE temporary=true",
- "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" temporary=true",
- "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.direct\" temporary=true",
- "ACL ALLOW-LOG client CREATE QUEUE temporary=true",
- "ACL ALLOW-LOG client DELETE QUEUE temporary=true");
+ writeACLFile("ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST", "# Server side",
+ "ACL ALLOW-LOG server CREATE QUEUE name=\"example.RequestQueue\"",
+ "ACL ALLOW-LOG server BIND EXCHANGE" ,
+ "ACL ALLOW-LOG server PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"TempQueue*\"",
+ "ACL ALLOW-LOG server CONSUME QUEUE name=\"example.RequestQueue\"",
+ "# Client side",
+ "ACL ALLOW-LOG client PUBLISH EXCHANGE name=\"amq.direct\" routingKey=\"example.RequestQueue\"",
+ "ACL ALLOW-LOG client CONSUME QUEUE temporary=true",
+ "ACL ALLOW-LOG client BIND EXCHANGE name=\"amq.direct\" temporary=true",
+ "ACL ALLOW-LOG client UNBIND EXCHANGE name=\"amq.direct\" temporary=true",
+ "ACL ALLOW-LOG client CREATE QUEUE temporary=true",
+ "ACL ALLOW-LOG client DELETE QUEUE temporary=true");
}
@@ -386,9 +432,9 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpClientDeleteQueueSuccessWithOnlyAllPermissions() throws Exception
{
- writeACLFile("test", "ACL ALLOW-LOG client ACCESS VIRTUALHOST",
- "ACL ALLOW-LOG client ALL QUEUE",
- "ACL ALLOW-LOG client ALL EXCHANGE");
+ writeACLFile("ACL ALLOW-LOG client ACCESS VIRTUALHOST",
+ "ACL ALLOW-LOG client ALL QUEUE",
+ "ACL ALLOW-LOG client ALL EXCHANGE");
}
public void testClientDeleteQueueSuccessWithOnlyAllPermissions() throws Exception
@@ -412,7 +458,7 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpFirewallAllow() throws Exception
{
- writeACLFile("test", "ACL ALLOW client ACCESS VIRTUALHOST from_network=\"127.0.0.1\"");
+ writeACLFile("ACL ALLOW client ACCESS VIRTUALHOST from_network=\"127.0.0.1\"");
}
public void testFirewallAllow() throws Exception
@@ -423,7 +469,7 @@ public class ExternalACLTest extends AbstractACLTestCase
public void setUpFirewallDeny() throws Exception
{
- writeACLFile("test", "ACL DENY client ACCESS VIRTUALHOST from_network=\"127.0.0.1\"");
+ writeACLFile("ACL DENY client ACCESS VIRTUALHOST from_network=\"127.0.0.1\"");
}
public void testFirewallDeny() throws Exception
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java
index 36e86fbe7b..d89f5cc66e 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java
@@ -185,6 +185,12 @@ public class MessageStoreTest extends QpidTestCase
try
{
_virtualHost = BrokerTestHelper.createVirtualHost(new VirtualHostRegistry(new EventLogger()), getVirtualHostModel());
+ when(_virtualHostModel.getId()).thenReturn(_virtualHost.getId());
+
+ ConfiguredObjectRecord objectRecord = mock(ConfiguredObjectRecord.class);
+ when(objectRecord.getId()).thenReturn(_virtualHost.getId());
+ when(objectRecord.getType()).thenReturn(org.apache.qpid.server.model.VirtualHost.class.getSimpleName());
+ when(_virtualHostModel.asObjectRecord()).thenReturn(objectRecord);
}
catch (Exception e)
{
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java
index 06b7091a47..cae6e29b96 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java
@@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicLong;
import org.apache.qpid.server.message.EnqueueableMessage;
import org.apache.qpid.server.message.MessageContentSource;
+import org.apache.qpid.server.model.ConfiguredObject;
public class
QuotaMessageStore extends NullMessageStore
@@ -81,7 +82,7 @@ public class
}
@Override
- public void recoverMessageStore(MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
+ public void recoverMessageStore(ConfiguredObject<?> parent, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
{
_stateManager.attainState(State.ACTIVATING);
_stateManager.attainState(State.ACTIVE);
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
index 44a5252355..8ec576c7ca 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java
@@ -29,7 +29,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.log4j.Logger;
import org.apache.qpid.server.message.EnqueueableMessage;
-import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.plugin.MessageStoreFactory;
public class SlowMessageStore implements MessageStore, DurableConfigurationStore
@@ -64,9 +64,9 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore
}
@Override
- public void recoverConfigurationStore(ConfigurationRecoveryHandler recoveryHandler)
+ public void recoverConfigurationStore(ConfiguredObject<?> parent, ConfigurationRecoveryHandler recoveryHandler)
{
- _realDurableConfigurationStore.recoverConfigurationStore(recoveryHandler);
+ _realDurableConfigurationStore.recoverConfigurationStore(parent, recoveryHandler);
}
private void configureDelays(Map<String, Object> delays)
@@ -183,7 +183,6 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore
_realDurableConfigurationStore.closeConfigurationStore();
}
-
@Override
public <M extends StorableMessageMetaData> StoredMessage<M> addMessage(M metaData)
{
@@ -191,39 +190,24 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore
}
@Override
- public void create(UUID id, String type, Map<String, Object> attributes) throws StoreException
+ public void create(ConfiguredObjectRecord record) throws StoreException
{
doPreDelay("create");
- _realDurableConfigurationStore.create(id, type, attributes);
+ _realDurableConfigurationStore.create(record);
doPostDelay("create");
}
- @Override
- public void remove(UUID id, String type) throws StoreException
- {
- doPreDelay("remove");
- _realDurableConfigurationStore.remove(id, type);
- doPostDelay("remove");
- }
@Override
- public UUID[] removeConfiguredObjects(final UUID... objects) throws StoreException
+ public UUID[] remove(final ConfiguredObjectRecord... objects) throws StoreException
{
doPreDelay("remove");
- UUID[] removed = _realDurableConfigurationStore.removeConfiguredObjects(objects);
+ UUID[] removed = _realDurableConfigurationStore.remove(objects);
doPostDelay("remove");
return removed;
}
@Override
- public void update(UUID id, String type, Map<String, Object> attributes) throws StoreException
- {
- doPreDelay("update");
- _realDurableConfigurationStore.update(id, type, attributes);
- doPostDelay("update");
- }
-
- @Override
public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws StoreException
{
doPreDelay("update");
@@ -310,9 +294,9 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore
}
@Override
- public void recoverMessageStore(MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
+ public void recoverMessageStore(ConfiguredObject<?> parent, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler transactionLogRecoveryHandler)
{
- _realMessageStore.recoverMessageStore(messageRecoveryHandler, transactionLogRecoveryHandler);
+ _realMessageStore.recoverMessageStore(parent, messageRecoveryHandler, transactionLogRecoveryHandler);
}
@Override
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
index ec389e55f1..da9466e9a9 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
@@ -63,8 +63,7 @@ public class BrokerACLTest extends QpidRestTestCase
super.customizeConfiguration();
getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER);
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_USER + " CONFIGURE BROKER",
"ACL DENY-LOG " + DENIED_USER + " CONFIGURE BROKER",
"ACL DENY-LOG ALL ALL");
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java
index b63df34b98..f20d9dfa47 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java
@@ -47,8 +47,7 @@ public class ExchangeRestACLTest extends QpidRestTestCase
super.customizeConfiguration();
getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER);
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_USER + " CREATE QUEUE",
"ACL ALLOW-LOG " + ALLOWED_USER + " CREATE EXCHANGE",
"ACL DENY-LOG " + DENIED_USER + " CREATE EXCHANGE",
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java
index aff1eac9cf..e6d5f8b1e0 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/GroupRestACLTest.java
@@ -94,8 +94,7 @@ public class GroupRestACLTest extends QpidRestTestCase
public void testCreateGroup() throws Exception
{
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE GROUP",
"ACL DENY-LOG " + DENIED_GROUP + " CREATE GROUP");
@@ -121,8 +120,7 @@ public class GroupRestACLTest extends QpidRestTestCase
public void testDeleteGroup() throws Exception
{
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE GROUP",
"ACL DENY-LOG " + DENIED_GROUP + " DELETE GROUP");
@@ -148,8 +146,7 @@ public class GroupRestACLTest extends QpidRestTestCase
public void testUpdateGroupAddMember() throws Exception
{
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP",
"ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP");
@@ -169,8 +166,7 @@ public class GroupRestACLTest extends QpidRestTestCase
public void testUpdateGroupDeleteMember() throws Exception
{
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE GROUP",
"ACL DENY-LOG " + DENIED_GROUP + " UPDATE GROUP");
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java
index 7d94ee27ad..dd6c7d6a28 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java
@@ -38,8 +38,7 @@ public class LogViewerACLTest extends QpidRestTestCase
super.customizeConfiguration();
getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER);
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_USER + " ACCESS_LOGS BROKER",
"ACL DENY-LOG " + DENIED_USER + " ACCESS_LOGS BROKER",
"ACL DENY-LOG ALL ALL");
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java
index 52f70a5dd2..b712327329 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java
@@ -42,8 +42,7 @@ public class QueueRestACLTest extends QpidRestTestCase
super.customizeConfiguration();
getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER);
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_USER + " CREATE QUEUE",
"ACL DENY-LOG " + DENIED_USER + " CREATE QUEUE",
"ACL ALLOW-LOG " + ALLOWED_USER + " UPDATE QUEUE",
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java
index b23e44a4d3..4b4854e4b3 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java
@@ -76,7 +76,7 @@ public class UserPreferencesRestACLTest extends QpidRestTestCase
super.customizeConfiguration();
getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER);
- AbstractACLTestCase.writeACLFileUtil(this, null, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", "ACL ALLOW-LOG " + ALLOWED_USER
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", "ACL ALLOW-LOG " + ALLOWED_USER
+ " UPDATE USER", "ACL DENY-LOG " + DENIED_USER + " UPDATE USER", "ACL DENY-LOG ALL ALL");
TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration();
diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java
index d2f0401db5..7c5042c750 100644
--- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java
+++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserRestACLTest.java
@@ -96,8 +96,7 @@ public class UserRestACLTest extends QpidRestTestCase
public void testAddUser() throws Exception
{
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_GROUP + " CREATE USER",
"ACL DENY-LOG " + DENIED_GROUP + " CREATE USER");
@@ -121,8 +120,7 @@ public class UserRestACLTest extends QpidRestTestCase
public void testDeleteUser() throws Exception
{
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_GROUP + " DELETE USER",
"ACL DENY-LOG " + DENIED_GROUP + " DELETE USER");
@@ -142,8 +140,7 @@ public class UserRestACLTest extends QpidRestTestCase
public void testUpdateUser() throws Exception
{
- AbstractACLTestCase.writeACLFileUtil(this, null,
- "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
+ AbstractACLTestCase.writeACLFileUtil(this, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT",
"ACL ALLOW-LOG " + ALLOWED_GROUP + " UPDATE USER",
"ACL DENY-LOG " + DENIED_GROUP + " UPDATE USER");