diff options
131 files changed, 4504 insertions, 3661 deletions
diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java index f36c1ecc6f..3a21bc70d7 100644 --- a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java +++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBean.java @@ -38,6 +38,7 @@ import javax.management.openmbean.TabularType; import org.apache.log4j.Logger; import org.apache.qpid.server.jmx.AMQManagedObject; import org.apache.qpid.server.jmx.ManagedObject; +import org.apache.qpid.server.jmx.ManagedObjectRegistry; import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; /** @@ -75,9 +76,9 @@ public class BDBHAMessageStoreManagerMBean extends AMQManagedObject implements M private final ReplicatedEnvironmentFacade _replicatedEnvironmentFacade; private final String _objectName; - protected BDBHAMessageStoreManagerMBean(String virtualHostName, ReplicatedEnvironmentFacade replicatedEnvironmentFacade, ManagedObject parent) throws JMException + protected BDBHAMessageStoreManagerMBean(String virtualHostName, ReplicatedEnvironmentFacade replicatedEnvironmentFacade, ManagedObjectRegistry registry) throws JMException { - super(ManagedBDBHAMessageStore.class, ManagedBDBHAMessageStore.TYPE, ((AMQManagedObject)parent).getRegistry()); + super(ManagedBDBHAMessageStore.class, ManagedBDBHAMessageStore.TYPE, registry); LOGGER.debug("Creating BDBHAMessageStoreManagerMBean for " + virtualHostName); _replicatedEnvironmentFacade = replicatedEnvironmentFacade; _objectName = ObjectName.quote(virtualHostName); diff --git a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java index 410ef941cd..558cc7e8a9 100644 --- a/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java +++ b/java/bdbstore/jmx/src/main/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanProvider.java @@ -26,11 +26,14 @@ import javax.management.StandardMBean; import org.apache.log4j.Logger; import org.apache.qpid.server.jmx.MBeanProvider; import org.apache.qpid.server.jmx.ManagedObject; +import org.apache.qpid.server.jmx.ManagedObjectRegistry; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.store.berkeleydb.BDBHAVirtualHost; import org.apache.qpid.server.store.berkeleydb.BDBMessageStore; import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; +import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode; /** * This provide will create a {@link BDBHAMessageStoreManagerMBean} if the child is a virtual @@ -49,15 +52,15 @@ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider @Override public boolean isChildManageableByMBean(ConfiguredObject child) { - return (child instanceof VirtualHost && BDBHAVirtualHost.TYPE.equals(child.getType())); + return child instanceof BDBHAVirtualHostNode; } @Override - public StandardMBean createMBean(ConfiguredObject child, StandardMBean parent) throws JMException + public ManagedObject createMBean(ConfiguredObject child, ManagedObjectRegistry registry) throws JMException { - VirtualHost virtualHostChild = (VirtualHost) child; + BDBHAVirtualHostNode<?> virtualHostNode = (BDBHAVirtualHostNode<?>) child; - BDBMessageStore messageStore = (BDBMessageStore) virtualHostChild.getMessageStore(); + BDBMessageStore messageStore = (BDBMessageStore) virtualHostNode.getConfigurationStore(); if (LOGGER.isDebugEnabled()) { @@ -65,7 +68,7 @@ public class BDBHAMessageStoreManagerMBeanProvider implements MBeanProvider } ReplicatedEnvironmentFacade replicatedEnvironmentFacade = (ReplicatedEnvironmentFacade)messageStore.getEnvironmentFacade(); - return new BDBHAMessageStoreManagerMBean(virtualHostChild.getName(), replicatedEnvironmentFacade, (ManagedObject) parent); + return new BDBHAMessageStoreManagerMBean(virtualHostNode.getGroupName(), replicatedEnvironmentFacade, registry); } @Override diff --git a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java index fa16d1061a..6aeadde0f8 100644 --- a/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java +++ b/java/bdbstore/jmx/src/test/java/org/apache/qpid/server/store/berkeleydb/jmx/BDBHAMessageStoreManagerMBeanTest.java @@ -54,7 +54,6 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase private ReplicatedEnvironmentFacade _replicatedEnvironmentFacade; private BDBHAMessageStoreManagerMBean _mBean; - private AMQManagedObject _mBeanParent; @Override protected void setUp() throws Exception @@ -62,9 +61,8 @@ public class BDBHAMessageStoreManagerMBeanTest extends TestCase super.setUp(); _replicatedEnvironmentFacade = mock(ReplicatedEnvironmentFacade.class); - _mBeanParent = mock(AMQManagedObject.class); - when(_mBeanParent.getRegistry()).thenReturn(mock(ManagedObjectRegistry.class)); - _mBean = new BDBHAMessageStoreManagerMBean(TEST_STORE_NAME, _replicatedEnvironmentFacade, _mBeanParent); + ManagedObjectRegistry registry = mock(ManagedObjectRegistry.class); + _mBean = new BDBHAMessageStoreManagerMBean(TEST_STORE_NAME, _replicatedEnvironmentFacade, registry); } @Override diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java index 97d6355fa4..40781a6349 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java @@ -20,93 +20,34 @@ */ package org.apache.qpid.server.store.berkeleydb; -import java.util.HashMap; import java.util.Map; -import com.sleepycat.je.rep.StateChangeEvent; -import com.sleepycat.je.rep.StateChangeListener; -import org.apache.log4j.Logger; - -import org.apache.qpid.server.connection.IConnectionRegistry; -import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.ConfiguredObjectRecordRecoveverAndUpgrader; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; -import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; import org.apache.qpid.server.virtualhost.AbstractVirtualHost; -import org.apache.qpid.server.virtualhost.MessageStoreRecoverer; -import org.apache.qpid.server.virtualhost.VirtualHostState; @ManagedObject( category = false, type = "BDB_HA" ) public class BDBHAVirtualHost extends AbstractVirtualHost<BDBHAVirtualHost> { public static final String TYPE = "BDB_HA"; - private static final Logger LOGGER = Logger.getLogger(BDBHAVirtualHost.class); - private BDBMessageStore _messageStore; + private final BDBMessageStore _messageStore; private MessageStoreLogSubject _messageStoreLogSubject; - BDBHAVirtualHost(final Map<String, Object> attributes, Broker<?> broker) + protected BDBHAVirtualHost(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode) { - super(attributes, broker); - } - + super(attributes, virtualHostNode); - @Override - public void validate() - { - super.validate(); - Map<String, Object> attributes = getActualAttributes(); - @SuppressWarnings("unchecked") - Map<String, Object> messageStoreSettings = (Map<String, Object>)attributes.get(org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS); - if (messageStoreSettings == null) - { - throw new IllegalArgumentException("Attribute '"+ org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS + "' is required."); - } - - validateAttribute(MessageStore.STORE_PATH, String.class, messageStoreSettings); - validateAttribute(ReplicatedEnvironmentFacadeFactory.GROUP_NAME, String.class, messageStoreSettings); - validateAttribute(ReplicatedEnvironmentFacadeFactory.NODE_NAME, String.class, messageStoreSettings); - validateAttribute(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS, String.class, messageStoreSettings); - validateAttribute(ReplicatedEnvironmentFacadeFactory.HELPER_ADDRESS, String.class, messageStoreSettings); - } - - private void validateAttribute(String attrName, Class<?> clazz, Map<String, Object> attributes) - { - Object attr = attributes.get(attrName); - if(!clazz.isInstance(attr)) - { - throw new IllegalArgumentException("Attribute '"+ attrName - +"' is required and must be of type "+clazz.getSimpleName()+"."); - } + _messageStore = (BDBMessageStore) virtualHostNode.getConfigurationStore(); + _messageStoreLogSubject = new MessageStoreLogSubject(getName(), _messageStore.getClass().getSimpleName()); } - protected void initialiseStorage(VirtualHost virtualHost) + @Override + protected void initialiseStorage() { - setState(VirtualHostState.PASSIVE); - - _messageStoreLogSubject = new MessageStoreLogSubject(getName(), BDBMessageStore.class.getSimpleName()); - _messageStore = new BDBMessageStore(new ReplicatedEnvironmentFacadeFactory()); - getEventLogger().message(_messageStoreLogSubject, MessageStoreMessages.CREATED()); - - Map<String, Object> messageStoreSettings = new HashMap<String, Object>(virtualHost.getMessageStoreSettings()); - messageStoreSettings.put(DurableConfigurationStore.IS_MESSAGE_STORE_TOO, true); - - _messageStore.openConfigurationStore(virtualHost, messageStoreSettings); - _messageStore.openMessageStore(virtualHost, messageStoreSettings); - - getEventLogger().message(_messageStoreLogSubject, MessageStoreMessages.STORE_LOCATION(_messageStore.getStoreLocation())); - - // Make the virtualhost model object a replication group listener - ReplicatedEnvironmentFacade environmentFacade = (ReplicatedEnvironmentFacade) _messageStore.getEnvironmentFacade(); - environmentFacade.setStateChangeListener(new BDBHAMessageStoreStateChangeListener()); - } @Override @@ -121,98 +62,10 @@ public class BDBHAVirtualHost extends AbstractVirtualHost<BDBHAVirtualHost> return _messageStore; } - private void onMaster() - { - try - { - _messageStore.getEnvironmentFacade().getEnvironment().flushLog(true); - - if(isStoreEmpty()) - { - createDefaultExchanges(); - } - else - { - ConfiguredObjectRecordHandler upgraderRecoverer = - new ConfiguredObjectRecordRecoveverAndUpgrader(this, getDurableConfigurationRecoverers()); - _messageStore.visitConfiguredObjectRecords(upgraderRecoverer); - } - - new MessageStoreRecoverer(this, getMessageStoreLogSubject()).recover(); - - attainActivation(); - } - catch (Exception e) - { - LOGGER.error("Failed to activate on hearing MASTER change event", e); - } - } - - private void passivate() - { - VirtualHostState finalState = VirtualHostState.ERRORED; - - try - { - /* the approach here is not ideal as there is a race condition where a - * queue etc could be created while the virtual host is on the way to - * the passivated state. However the store state change from MASTER to UNKNOWN - * is documented as exceptionally rare. - */ - - getConnectionRegistry().close(IConnectionRegistry.VHOST_PASSIVATE_REPLY_TEXT); - removeHouseKeepingTasks(); - - getDtxRegistry().close(); - - finalState = VirtualHostState.PASSIVE; - } - finally - { - setState(finalState); - reportIfError(getVirtualHostState()); - } - } - @Override protected MessageStoreLogSubject getMessageStoreLogSubject() { return _messageStoreLogSubject; } - private class BDBHAMessageStoreStateChangeListener implements StateChangeListener - { - - @Override - public void stateChange(StateChangeEvent stateChangeEvent) throws RuntimeException - { - com.sleepycat.je.rep.ReplicatedEnvironment.State state = stateChangeEvent.getState(); - - if (LOGGER.isInfoEnabled()) - { - LOGGER.info("Received BDB event indicating transition to state " + state); - } - - switch (state) - { - case MASTER: - onMaster(); - break; - case REPLICA: - passivate(); - break; - case DETACHED: - LOGGER.error("BDB replicated node in detached state, therefore passivating."); - passivate(); - break; - case UNKNOWN: - LOGGER.warn("BDB replicated node in unknown state (hopefully temporarily)"); - break; - default: - LOGGER.error("Unexpected state change: " + state); - throw new IllegalStateException("Unexpected state change: " + state); - } - } - } - } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostFactory.java index 2a28a61eca..cf011d06c1 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostFactory.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostFactory.java @@ -20,13 +20,11 @@ */ package org.apache.qpid.server.store.berkeleydb; +import java.util.Map; + import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; - -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; +import org.apache.qpid.server.model.VirtualHostNode; public class BDBHAVirtualHostFactory extends AbstractConfiguredObjectTypeFactory<BDBHAVirtualHost> { @@ -40,9 +38,8 @@ public class BDBHAVirtualHostFactory extends AbstractConfiguredObjectTypeFactory public BDBHAVirtualHost createInstance(final Map<String, Object> attributes, final ConfiguredObject<?>... parents) { - final Broker broker = getParent(Broker.class, parents); - return new BDBHAVirtualHost(attributes, broker); + final VirtualHostNode<?> virtualHostNode = getParent(VirtualHostNode.class, parents); + return new BDBHAVirtualHost(attributes, virtualHostNode); } - } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java index 722a3a090d..5d9c2012a9 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Random; import java.util.UUID; @@ -36,6 +37,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.model.VirtualHostNode; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.Event; @@ -128,6 +130,9 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore private volatile Committer _committer; + private boolean _isMessageStoreProvider; + + private String _storeLocation; public BDBMessageStore() { @@ -153,7 +158,8 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore if (_environmentFacade == null) { EnvironmentFacadeTask[] initialisationTasks = null; - if (MapValueConverter.getBooleanAttribute(IS_MESSAGE_STORE_TOO, storeSettings, false)) + _isMessageStoreProvider = MapValueConverter.getBooleanAttribute(VirtualHostNode.IS_MESSAGE_STORE_PROVIDER, storeSettings, false); + if (_isMessageStoreProvider) { String[] databaseNames = new String[CONFIGURATION_STORE_DATABASE_NAMES.length + MESSAGE_STORE_DATABASE_NAMES.length]; System.arraycopy(CONFIGURATION_STORE_DATABASE_NAMES, 0, databaseNames, 0, CONFIGURATION_STORE_DATABASE_NAMES.length); @@ -165,6 +171,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore initialisationTasks = new EnvironmentFacadeTask[]{new UpgradeTask(parent), new OpenDatabasesTask(CONFIGURATION_STORE_DATABASE_NAMES)}; } _environmentFacade = _environmentFacadeFactory.createEnvironmentFacade(storeSettings, initialisationTasks); + _storeLocation = _environmentFacade.getStoreLocation(); } else { @@ -274,6 +281,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore { _environmentFacade = _environmentFacadeFactory.createEnvironmentFacade(messageStoreSettings, new UpgradeTask(parent), new OpenDatabasesTask(MESSAGE_STORE_DATABASE_NAMES), new DiskSpaceTask(), new MaxMessageIdTask()); + _storeLocation = _environmentFacade.getStoreLocation(); } _committer = _environmentFacade.createCommitter(parent.getName()); @@ -292,11 +300,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore @Override public String getStoreLocation() { - if (_environmentFacade == null) - { - return null; - } - return _environmentFacade.getStoreLocation(); + return _storeLocation; } public EnvironmentFacade getEnvironmentFacade() @@ -355,6 +359,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore try { _environmentFacade.close(); + _environmentFacade = null; } catch(DatabaseException e) { @@ -1514,21 +1519,22 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore @Override public void onDelete() { - String storeLocation = getStoreLocation(); - - if (storeLocation != null) + if (!_configurationStoreOpen.get() && !_messageStoreOpen.get()) { - if (LOGGER.isDebugEnabled()) + if (_storeLocation != null) { - LOGGER.debug("Deleting store " + storeLocation); - } + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Deleting store " + _storeLocation); + } - File location = new File(storeLocation); - if (location.exists()) - { - if (!FileUtils.delete(location, true)) + File location = new File(_storeLocation); + if (location.exists()) { - LOGGER.error("Cannot delete " + storeLocation); + if (!FileUtils.delete(location, true)) + { + LOGGER.error("Cannot delete " + _storeLocation); + } } } } @@ -1711,6 +1717,7 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore checkMessageStoreOpen(); Cursor cursor = null; + List<QueueEntryKey> entries = new ArrayList<QueueEntryKey>(); try { cursor = getDeliveryDb().openCursor(null, null); @@ -1718,15 +1725,10 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore QueueEntryBinding keyBinding = QueueEntryBinding.getInstance(); DatabaseEntry value = new DatabaseEntry(); - while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) + while (cursor.getNext(key, value, LockMode.DEFAULT) == OperationStatus.SUCCESS) { QueueEntryKey entry = keyBinding.entryToObject(key); - UUID queueId = entry.getQueueId(); - long messageId = entry.getMessageId(); - if (!handler.handle(queueId, messageId)) - { - break; - } + entries.add(entry); } } catch (DatabaseException e) @@ -1737,6 +1739,17 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore { closeCursorSafely(cursor); } + + for(QueueEntryKey entry : entries) + { + UUID queueId = entry.getQueueId(); + long messageId = entry.getMessageId(); + if (!handler.handle(queueId, messageId)) + { + break; + } + } + } @Override diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java index ef749f2472..5c4633fe04 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java @@ -64,16 +64,18 @@ public class BDBMessageStoreFactory implements MessageStoreFactory, DurableConfi } } + } - @SuppressWarnings("unchecked") - Map<String, Object> configurationStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.CONFIGURATION_STORE_SETTINGS); + @Override + public void validateConfigurationStoreSettings(Map<String, Object> configurationStoreSettings) + { if(configurationStoreSettings != null && getType().equals(configurationStoreSettings.get(DurableConfigurationStore.STORE_TYPE))) { Object storePath = configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); if(!(storePath instanceof String)) { - throw new IllegalArgumentException("Setting '"+ DurableConfigurationStore.STORE_PATH - +"' is required and must be of type String."); + throw new IllegalArgumentException("Durable configuration store setting '" + DurableConfigurationStore.STORE_PATH + + "' is required and must be of type String."); } } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java index 2e02a6cfed..83584e306f 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/EnvironmentFacadeFactory.java @@ -24,7 +24,7 @@ import java.util.Map; public interface EnvironmentFacadeFactory { - public static final String ENVIRONMENT_CONFIGURATION = "bdbEnvironmentConfig"; + public static final String ENVIRONMENT_CONFIGURATION = "environmentConfiguration"; EnvironmentFacade createEnvironmentFacade(Map<String, Object> storeSettings, EnvironmentFacadeTask... initialisationTasks); diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java index 6065be5fa9..b11fb6e873 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/StandardEnvironmentFacade.java @@ -232,5 +232,4 @@ public class StandardEnvironmentFacade implements EnvironmentFacade { return _storePath; } - } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java index b8192ea741..0b00800b04 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacade.java @@ -1103,4 +1103,5 @@ public class ReplicatedEnvironmentFacade implements EnvironmentFacade, StateChan } } + } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeFactory.java index 05944632b0..62035bb65f 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeFactory.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/replication/ReplicatedEnvironmentFacadeFactory.java @@ -20,31 +20,14 @@ */ package org.apache.qpid.server.store.berkeleydb.replication; -import com.sleepycat.je.Durability; -import com.sleepycat.je.Durability.ReplicaAckPolicy; -import com.sleepycat.je.Durability.SyncPolicy; -import org.apache.qpid.server.store.MessageStore; +import java.util.Map; + import org.apache.qpid.server.store.berkeleydb.EnvironmentFacade; import org.apache.qpid.server.store.berkeleydb.EnvironmentFacadeFactory; - -import java.util.Map; +import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeImpl; public class ReplicatedEnvironmentFacadeFactory implements EnvironmentFacadeFactory { - public static final String DURABILITY = "haDurability"; - public static final String GROUP_NAME = "haGroupName"; - public static final String HELPER_ADDRESS = "haHelperAddress"; - public static final String NODE_ADDRESS = "haNodeAddress"; - public static final String NODE_NAME = "haNodeName"; - public static final String REPLICATION_CONFIG = "haReplicationConfig"; - public static final String COALESCING_SYNC = "haCoalescingSync"; - public static final String DESIGNATED_PRIMARY = "haDesignatedPrimary"; - - private static final int DEFAULT_NODE_PRIORITY = 1; - private static final Durability DEFAULT_DURABILITY = new Durability(SyncPolicy.NO_SYNC, SyncPolicy.NO_SYNC, - ReplicaAckPolicy.SIMPLE_MAJORITY); - private static final boolean DEFAULT_COALESCING_SYNC = true; - @Override public EnvironmentFacade createEnvironmentFacade(final Map<String, Object> messageStoreSettings, EnvironmentFacadeTask... initialisationTasks) { @@ -53,77 +36,76 @@ public class ReplicatedEnvironmentFacadeFactory implements EnvironmentFacadeFact @Override public boolean isDesignatedPrimary() { - return convertBoolean(messageStoreSettings.get(DESIGNATED_PRIMARY), false); + return (Boolean)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.DESIGNATED_PRIMARY); } @Override public boolean isCoalescingSync() { - return convertBoolean(messageStoreSettings.get(COALESCING_SYNC), DEFAULT_COALESCING_SYNC); + return (Boolean)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.COALESCING_SYNC); } @Override public String getStorePath() { - return (String) messageStoreSettings.get(MessageStore.STORE_PATH); + return (String) messageStoreSettings.get(BDBHAVirtualHostNodeImpl.STORE_PATH); } @SuppressWarnings("unchecked") @Override public Map<String, String> getParameters() { - return (Map<String, String>) messageStoreSettings.get(EnvironmentFacadeFactory.ENVIRONMENT_CONFIGURATION); + return (Map<String, String>) messageStoreSettings.get(BDBHAVirtualHostNodeImpl.ENVIRONMENT_CONFIGURATION); } @SuppressWarnings("unchecked") @Override public Map<String, String> getReplicationParameters() { - return (Map<String, String>) messageStoreSettings.get(REPLICATION_CONFIG); + return (Map<String, String>) messageStoreSettings.get(BDBHAVirtualHostNodeImpl.REPLICATED_ENVIRONMENT_CONFIGURATION); } @Override public int getQuorumOverride() { - return 0; + return (Integer)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.QUORUM_OVERRIDE); } @Override public int getPriority() { - return DEFAULT_NODE_PRIORITY; + return (Integer)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.PRIORITY); } @Override public String getName() { - return (String)messageStoreSettings.get(NODE_NAME); + return (String)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.NAME); } @Override public String getHostPort() { - return (String)messageStoreSettings.get(NODE_ADDRESS); + return (String)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.ADDRESS); } @Override public String getHelperHostPort() { - return (String)messageStoreSettings.get(HELPER_ADDRESS); + return (String)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.HELPER_ADDRESS); } @Override public String getGroupName() { - return (String)messageStoreSettings.get(GROUP_NAME); + return (String)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.GROUP_NAME); } @Override public String getDurability() { - String durability = (String)messageStoreSettings.get(DURABILITY); - return durability == null ? DEFAULT_DURABILITY.toString() : durability; - } + return (String)messageStoreSettings.get(BDBHAVirtualHostNodeImpl.DURABILITY); + } }; return new ReplicatedEnvironmentFacade(configuration, initialisationTasks); @@ -135,24 +117,4 @@ public class ReplicatedEnvironmentFacadeFactory implements EnvironmentFacadeFact return ReplicatedEnvironmentFacade.TYPE; } - private boolean convertBoolean(final Object value, boolean defaultValue) - { - if(value instanceof Boolean) - { - return (Boolean) value; - } - else if(value instanceof String) - { - return Boolean.valueOf((String) value); - } - else if(value == null) - { - return defaultValue; - } - else - { - throw new IllegalArgumentException("Cannot convert type " + value.getClass() + " to a Boolean"); - } - } - } diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java index 0d4e40fdcb..faccd2fdf4 100644 --- a/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8.java @@ -78,7 +78,7 @@ public class UpgradeFrom7To8 extends AbstractStoreUpgrade Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); virtualHostAttributes.put("modelVersion", stringifiedConfigVersion); - + virtualHostAttributes.put("name", parent.getName()); String virtualHostName = parent.getName(); UUID virtualHostId = UUIDGenerator.generateVhostUUID(virtualHostName); ConfiguredObjectRecord virtualHostRecord = new org.apache.qpid.server.store.ConfiguredObjectRecordImpl(virtualHostId, "VirtualHost", virtualHostAttributes); diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java new file mode 100644 index 0000000000..f0325b24f8 --- /dev/null +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNode.java @@ -0,0 +1,65 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode.berkeleydb; + +import java.util.Map; + +import org.apache.qpid.server.model.ManagedAttribute; + +public interface BDBHAVirtualHostNode<X extends BDBHAVirtualHostNode<X>> extends BDBVirtualHostNode<X> +{ + public static final String GROUP_NAME = "groupName"; + public static final String ADDRESS = "address"; + public static final String HELPER_ADDRESS = "helperAddress"; + public static final String DURABILITY = "durability"; + public static final String COALESCING_SYNC = "coalescingSync"; + public static final String DESIGNATED_PRIMARY = "designatedPrimary"; + public static final String PRIORITY = "priority"; + public static final String QUORUM_OVERRIDE = "quorumOverride"; + public static final String REPLICATED_ENVIRONMENT_CONFIGURATION = "replicatedEnvironmentConfiguration"; + + @ManagedAttribute(automate = true, mandatory=true) + String getGroupName(); + + @ManagedAttribute(automate = true, mandatory=true) + String getAddress(); + + @ManagedAttribute(automate = true, mandatory=true) + String getHelperAddress(); + + @ManagedAttribute(automate = true, defaultValue = "NO_SYNC,NO_SYNC,SIMPLE_MAJORITY") + String getDurability(); + + @ManagedAttribute(automate = true, defaultValue = "true") + boolean isCoalescingSync(); + + @ManagedAttribute(automate = true, defaultValue = "false") + boolean isDesignatedPrimary(); + + @ManagedAttribute(automate = true, defaultValue = "1") + int getPriority(); + + @ManagedAttribute(automate = true, defaultValue = "0") + int getQuorumOverride(); + + @ManagedAttribute(automate = true) + Map<String, String> getReplicatedEnvironmentConfiguration(); +} diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeFactory.java new file mode 100644 index 0000000000..5f988559e8 --- /dev/null +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeFactory.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.virtualhostnode.berkeleydb; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; + +public class BDBHAVirtualHostNodeFactory extends AbstractConfiguredObjectTypeFactory<BDBHAVirtualHostNodeImpl> +{ + public BDBHAVirtualHostNodeFactory() + { + super(BDBHAVirtualHostNodeImpl.class); + } + + @Override + public BDBHAVirtualHostNodeImpl createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents) + { + Broker<?> broker = getParent(Broker.class, parents); + return new BDBHAVirtualHostNodeImpl(broker, attributes, broker.getTaskExecutor()); + } + +} diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java new file mode 100644 index 0000000000..fff5c63337 --- /dev/null +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java @@ -0,0 +1,537 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode.berkeleydb; + +import java.security.PrivilegedAction; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import javax.security.auth.Subject; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.logging.EventLogger; +import org.apache.qpid.server.logging.messages.ConfigStoreMessages; +import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; +import org.apache.qpid.server.model.AbstractConfiguredObject; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.BrokerModel; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.ConfiguredObjectFactory; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.SystemContext; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer; +import org.apache.qpid.server.store.berkeleydb.BDBHAVirtualHost; +import org.apache.qpid.server.store.berkeleydb.BDBHAVirtualHostFactory; +import org.apache.qpid.server.store.berkeleydb.BDBMessageStore; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacade; +import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; +import org.apache.qpid.server.virtualhost.VirtualHostState; + +import com.sleepycat.je.rep.StateChangeEvent; +import com.sleepycat.je.rep.StateChangeListener; + +@ManagedObject( category = false, type = "BDB_HA" ) +public class BDBHAVirtualHostNodeImpl extends AbstractConfiguredObject<BDBHAVirtualHostNodeImpl> implements BDBHAVirtualHostNode<BDBHAVirtualHostNodeImpl> +{ + private static final Logger LOGGER = Logger.getLogger(BDBHAVirtualHostNodeImpl.class); + + @ManagedAttributeField + private Map<String, String> _environmentConfiguration; + + @ManagedAttributeField + private String _storePath; + + @ManagedAttributeField + private String _groupName; + + @ManagedAttributeField + private String _helperAddress; + + @ManagedAttributeField + private String _address; + + @ManagedAttributeField + private String _durability; + + @ManagedAttributeField + private boolean _coalescingSync; + + @ManagedAttributeField + private boolean _designatedPrimary; + + @ManagedAttributeField + private int _priority; + + @ManagedAttributeField + private int _quorumOverride; + + @ManagedAttributeField + private Map<String, String> _replicatedEnvironmentConfiguration; + + //TODO: remove this field + @ManagedAttributeField + private boolean _messageStoreProvider; + + private final AtomicReference<State> _state = new AtomicReference<State>(State.INITIALISING); + private final Broker<?> _broker; + private final ConfiguredObjectFactory _objectFactory; + private final EventLogger _eventLogger; + + private MessageStoreLogSubject _configurationStoreLogSubject; + private BDBMessageStore _durableConfigurationStore; + + @SuppressWarnings("rawtypes") + protected BDBHAVirtualHostNodeImpl(Broker<?> broker, Map<String, Object> attributes, TaskExecutor taskExecutor) + { + super(Collections.<Class<? extends ConfiguredObject>,ConfiguredObject<?>>singletonMap(Broker.class, broker), attributes, taskExecutor); + _broker = broker; + _objectFactory = _broker.getParent(SystemContext.class).getObjectFactory(); + SystemContext systemContext = _broker.getParent(SystemContext.class); + _eventLogger = systemContext.getEventLogger(); + + } + + @Override + public Map<String, String> getEnvironmentConfiguration() + { + return _environmentConfiguration; + } + + @Override + public String getStorePath() + { + return _storePath; + } + + @Override + public boolean isMessageStoreProvider() + { + return true; + } + + @Override + public VirtualHost<?,?,?> getVirtualHost() + { + @SuppressWarnings("rawtypes") + Collection<VirtualHost> children = getChildren(VirtualHost.class); + if (children.size() == 0) + { + return null; + } + else if (children.size() == 1) + { + return children.iterator().next(); + } + else + { + throw new IllegalStateException(this + " has an unexpected number of virtualhost children, size " + children.size()); + } + } + + + @Override + public DurableConfigurationStore getConfigurationStore() + { + return _durableConfigurationStore; + } + + @Override + public State getState() + { + return _state.get(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public String getGroupName() + { + return _groupName; + } + + @Override + public String getHelperAddress() + { + return _helperAddress; + } + + @Override + public String getAddress() + { + return _address; + } + + @Override + public String getDurability() + { + return _durability; + } + + @Override + public boolean isCoalescingSync() + { + return _coalescingSync; + } + + @Override + public boolean isDesignatedPrimary() + { + return _designatedPrimary; + } + + @Override + public int getPriority() + { + return _priority; + } + + @Override + public int getQuorumOverride() + { + return _quorumOverride; + } + + @Override + public Map<String, String> getReplicatedEnvironmentConfiguration() + { + return _replicatedEnvironmentConfiguration; + } + + @Override + protected boolean setState(State currentState, State desiredState) + { + State state = getState(); + + if (desiredState == State.DELETED) + { + if (state == State.ACTIVE) + { + setDesiredState(state, State.STOPPED); + } + if (state == State.INITIALISING || state == State.STOPPED || state == State.ERRORED) + { + if( _state.compareAndSet(state, State.DELETED)) + { + delete(); + return true; + } + } + else + { + throw new IllegalStateException("Cannot delete virtual host node in " + state + " state"); + } + } + else if (desiredState == State.ACTIVE) + { + if ((state == State.INITIALISING || state == State.STOPPED) && _state.compareAndSet(state, State.ACTIVE)) + { + try + { + activate(); + } + catch(RuntimeException e) + { + _state.compareAndSet(State.ACTIVE, State.ERRORED); + if (_broker.isManagementMode()) + { + LOGGER.warn("Failed to make " + this + " active.", e); + } + else + { + throw e; + } + } + return true; + } + else + { + throw new IllegalStateException("Cannot activate virtual host node in " + state + " state"); + } + } + else if (desiredState == State.STOPPED) + { + if (_state.compareAndSet(state, State.STOPPED)) + { + stop(); + return true; + } + else + { + throw new IllegalStateException("Cannot stop virtual host node in " + state + " state"); + } + } + return false; + } + + @Override + public String toString() + { + return "BDBHAVirtualHostNodeImpl [name=" + getName() + ", storePath=" + _storePath + ", groupName=" + _groupName + ", address=" + _address + + ", state=" + _state.get() + "]"; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + protected <C extends ConfiguredObject> C addChild(Class<C> childClass, Map<String, Object> attributes, + ConfiguredObject... otherParents) + { + if(childClass == VirtualHost.class) + { + if ("MASTER".equals(((ReplicatedEnvironmentFacade)_durableConfigurationStore.getEnvironmentFacade()).getNodeState())) + { + BDBHAVirtualHostFactory virtualHostFactory = new BDBHAVirtualHostFactory(); + return (C) virtualHostFactory.create(getObjectFactory(), attributes,this); + } + else + { + ReplicaVirtualHost host = new ReplicaVirtualHost(attributes, this); + host.create(); + return (C) host; + } + } + return super.addChild(childClass, attributes, otherParents); + } + + private void activate() + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Activating virtualhost node " + this); + } + + _durableConfigurationStore = new BDBMessageStore(new ReplicatedEnvironmentFacadeFactory()); + _configurationStoreLogSubject = new MessageStoreLogSubject(getName(), BDBMessageStore.class.getSimpleName()); + + Map<String, Object> attributes = buildAttributesForStore(); + + _durableConfigurationStore.openConfigurationStore(this, attributes); + + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.CREATED()); + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.STORE_LOCATION(getStorePath())); + + + ReplicatedEnvironmentFacade environmentFacade = (ReplicatedEnvironmentFacade) _durableConfigurationStore.getEnvironmentFacade(); + environmentFacade.setStateChangeListener(new BDBHAMessageStoreStateChangeListener()); + } + + private void stop() + { + destroyVirtualHostIfExist(); + _durableConfigurationStore.closeConfigurationStore(); + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.CLOSE()); + } + + private void delete() + { + VirtualHost<?, ?, ?> virtualHost = getVirtualHost(); + if (virtualHost != null) + { + virtualHost.setDesiredState(virtualHost.getState(), State.DELETED); + } + + //TODO: this needs to be called from parent + deleted(); + + _durableConfigurationStore.onDelete(); + + } + + private Map<String, Object> buildAttributesForStore() + { + final Map<String, Object> attributes = new HashMap<String, Object>(); + Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>() + { + @Override + public Object run() + { + for (String attributeName : getAttributeNames()) + { + Object value = getAttribute(attributeName); + attributes.put(attributeName, value); + } + return null; + } + }); + + attributes.put(IS_MESSAGE_STORE_PROVIDER, true); + return attributes; + } + + private void onMaster() + { + try + { + destroyVirtualHostIfExist(); + _durableConfigurationStore.getEnvironmentFacade().getEnvironment().flushLog(true); + + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.RECOVERY_START()); + VirtualHostStoreUpgraderAndRecoverer upgraderAndRecoverer = new VirtualHostStoreUpgraderAndRecoverer(this, _objectFactory); + upgraderAndRecoverer.perform(_durableConfigurationStore); + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.RECOVERY_COMPLETE()); + + VirtualHost<?,?,?> host = getVirtualHost(); + + if (host == null) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Creating new virtualhost with name : " + getGroupName()); + } + + Map<String, Object> hostAttributes = new HashMap<String, Object>(); + hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION); + hostAttributes.put(VirtualHost.NAME, getGroupName()); + hostAttributes.put(VirtualHost.TYPE, "BDB_HA"); + host = createChild(VirtualHost.class, hostAttributes); + } + else + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Recovered virtualhost with name : " + getGroupName()); + } + + final VirtualHost<?,?,?> recoveredHost = host; + Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>() + { + @Override + public Object run() + { + recoveredHost.open(); + return null; + } + }); + } + host.setDesiredState(host.getState(), State.ACTIVE); + + } + catch (Exception e) + { + LOGGER.error("Failed to activate on hearing MASTER change event", e); + } + } + + private void onReplica() + { + try + { + destroyVirtualHostIfExist(); + + Map<String, Object> hostAttributes = new HashMap<String, Object>(); + hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION); + hostAttributes.put(VirtualHost.NAME, getGroupName()); + hostAttributes.put(VirtualHost.TYPE, "BDB_HA"); + createChild(VirtualHost.class, hostAttributes); + } + catch (Exception e) + { + LOGGER.error("Failed to create a replica host", e); + } + } + + private void onDetached() + { + destroyVirtualHostIfExist(); + } + + protected void destroyVirtualHostIfExist() + { + VirtualHost<?,?,?> virtualHost = getVirtualHost(); + if (virtualHost!= null) + { + virtualHost.setDesiredState(virtualHost.getState(), State.STOPPED); + } + } + + private class BDBHAMessageStoreStateChangeListener implements StateChangeListener + { + @Override + public void stateChange(StateChangeEvent stateChangeEvent) throws RuntimeException + { + com.sleepycat.je.rep.ReplicatedEnvironment.State state = stateChangeEvent.getState(); + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Received BDB event indicating transition to state " + state); + } + + switch (state) + { + case MASTER: + onMaster(); + break; + case REPLICA: + onReplica(); + break; + case DETACHED: + LOGGER.error("BDB replicated node in detached state, therefore passivating."); + onDetached(); + break; + case UNKNOWN: + LOGGER.warn("BDB replicated node in unknown state (hopefully temporarily)"); + break; + default: + LOGGER.error("Unexpected state change: " + state); + throw new IllegalStateException("Unexpected state change: " + state); + } + } + } + + private class ReplicaVirtualHost extends BDBHAVirtualHost + { + + ReplicaVirtualHost(Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode) + { + super(attributes, virtualHostNode); + setState(VirtualHostState.PASSIVE); + } + + @Override + public void onCreate() + { + } + + @Override + public boolean setState(State currentState, State desiredState) + { + if (desiredState != State.STOPPED) + { + throw new IllegalArgumentException("Unsupported state " + desiredState); + } + return super.setState(currentState, desiredState); + } + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/UpgraderProvider.java b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNode.java index 9785be78a6..4785d47447 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/UpgraderProvider.java +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNode.java @@ -18,9 +18,17 @@ * under the License. * */ -package org.apache.qpid.server.store; +package org.apache.qpid.server.virtualhostnode.berkeleydb; -public interface UpgraderProvider +import java.util.Map; + +import org.apache.qpid.server.model.ManagedAttribute; +import org.apache.qpid.server.virtualhostnode.FileBasedVirtualHostNode; + +public interface BDBVirtualHostNode<X extends BDBVirtualHostNode<X>> extends FileBasedVirtualHostNode<X> { - DurableConfigurationStoreUpgrader getUpgrader(String configVersion, DurableConfigurationRecoverer recoverer); -} + public static final String ENVIRONMENT_CONFIGURATION = "environmentConfiguration"; + + @ManagedAttribute(mandatory=false, automate=true) + Map<String, String> getEnvironmentConfiguration(); +}
\ No newline at end of file diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeFactory.java b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeFactory.java new file mode 100644 index 0000000000..80bf9d9520 --- /dev/null +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeFactory.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.virtualhostnode.berkeleydb; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; + +public class BDBVirtualHostNodeFactory extends AbstractConfiguredObjectTypeFactory<BDBVirtualHostNodeImpl> +{ + public BDBVirtualHostNodeFactory() + { + super(BDBVirtualHostNodeImpl.class); + } + + @Override + public BDBVirtualHostNodeImpl createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents) + { + Broker<?> broker = getParent(Broker.class, parents); + return new BDBVirtualHostNodeImpl(broker, attributes, broker.getTaskExecutor()); + } + +} diff --git a/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java new file mode 100644 index 0000000000..806dd49256 --- /dev/null +++ b/java/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java @@ -0,0 +1,71 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode.berkeleydb; + +import java.util.Map; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.store.berkeleydb.BDBMessageStoreFactory; +import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode; + +@ManagedObject( category = false, type = "BDB" ) +public class BDBVirtualHostNodeImpl extends AbstractStandardVirtualHostNode<BDBVirtualHostNodeImpl> implements BDBVirtualHostNode<BDBVirtualHostNodeImpl> +{ + @ManagedAttributeField + private String _storePath; + + @ManagedAttributeField + private Map<String, String> _environmentConfiguration; + + public BDBVirtualHostNodeImpl(Broker<?> parent, Map<String, Object> attributes, TaskExecutor taskExecutor) + { + super(parent, attributes, taskExecutor); + } + + @Override + protected DurableConfigurationStoreFactory getDurableConfigurationStoreFactory() + { + return new BDBMessageStoreFactory(); + } + + @Override + public Map<String, String> getEnvironmentConfiguration() + { + return _environmentConfiguration; + } + + @Override + public String getStorePath() + { + return _storePath; + } + + @Override + public String toString() + { + return getClass().getSimpleName() + " [id=" + getId() + ", name=" + getName() + ", storePath=" + getStorePath() + "]"; + } + +} diff --git a/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory b/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory index 0f8848cb74..a8855df6b7 100644 --- a/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory +++ b/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory @@ -17,3 +17,5 @@ # under the License. # org.apache.qpid.server.store.berkeleydb.BDBHAVirtualHostFactory +org.apache.qpid.server.virtualhostnode.berkeleydb.BDBVirtualHostNodeFactory +org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeFactory diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java new file mode 100644 index 0000000000..d54ed354f0 --- /dev/null +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHostNodeTest.java @@ -0,0 +1,193 @@ +/* + * + * 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 static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfigurationChangeListener; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode; +import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNodeFactory; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.util.FileUtils; + +import com.sleepycat.je.rep.ReplicatedEnvironment; +import com.sleepycat.je.rep.ReplicationConfig; + +public class BDBHAVirtualHostNodeTest extends QpidTestCase +{ + + private Broker<?> _broker; + private File _bdbStorePath; + private VirtualHostNode<?> _virtualHostNode; + private TaskExecutor _taskExecutor; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _broker = BrokerTestHelper.createBrokerMock(); + + _taskExecutor = new TaskExecutor(); + _taskExecutor.start(); + when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); + + _bdbStorePath = new File(TMP_FOLDER, getTestName() + "." + System.currentTimeMillis()); + _bdbStorePath.deleteOnExit(); + } + + @Override + protected void tearDown() throws Exception + { + try + { + if (_virtualHostNode != null) + { + _virtualHostNode.setDesiredState(_virtualHostNode.getState(), State.STOPPED); + } + } + finally + { + if (_taskExecutor != null) + { + _taskExecutor.stopImmediately(); + } + if (_bdbStorePath != null) + { + FileUtils.delete(_bdbStorePath, true); + } + super.tearDown(); + } + } + + public void testCreateAndActivateVirtualHostNode() throws Exception + { + String repStreamTimeout = "2 h"; + String nodeName = "node"; + String groupName = "group"; + String nodeHostPort = "localhost:" + findFreePort(); + String helperHostPort = nodeHostPort; + String durability = "NO_SYNC,SYNC,NONE"; + UUID id = UUID.randomUUID(); + + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(BDBHAVirtualHostNode.TYPE, "BDB_HA"); + attributes.put(BDBHAVirtualHostNode.ID, id); + attributes.put(BDBHAVirtualHostNode.NAME, nodeName); + attributes.put(BDBHAVirtualHostNode.GROUP_NAME, groupName); + attributes.put(BDBHAVirtualHostNode.ADDRESS, nodeHostPort); + attributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, helperHostPort); + attributes.put(BDBHAVirtualHostNode.DURABILITY, durability); + attributes.put(BDBHAVirtualHostNode.STORE_PATH, _bdbStorePath); + attributes.put(BDBHAVirtualHostNode.REPLICATED_ENVIRONMENT_CONFIGURATION, + Collections.singletonMap(ReplicationConfig.REP_STREAM_TIMEOUT, repStreamTimeout)); + + ConfiguredObjectTypeFactory<?> factory = new BDBHAVirtualHostNodeFactory(); + + BDBHAVirtualHostNode<?> node = (BDBHAVirtualHostNode<?>) factory.create(null, attributes, _broker); + + final CountDownLatch virtualHostAddedLatch = new CountDownLatch(1); + final CountDownLatch virtualHostStateChangeLatch = new CountDownLatch(1); + node.addChangeListener(new ConfigurationChangeListener() + { + @Override + public void stateChanged(ConfiguredObject object, State oldState, State newState) + { + if (object instanceof VirtualHost) + { + virtualHostStateChangeLatch.countDown(); + } + } + + @Override + public void childRemoved(ConfiguredObject object, ConfiguredObject child) + { + } + + @Override + public void childAdded(ConfiguredObject object, ConfiguredObject child) + { + child.addChangeListener(this); + virtualHostAddedLatch.countDown(); + } + + @Override + public void attributeSet(ConfiguredObject object, String attributeName, Object oldAttributeValue, Object newAttributeValue) + { + } + }); + assertEquals(State.ACTIVE, node.setDesiredState(node.getState(), State.ACTIVE)); + + DurableConfigurationStore store = node.getConfigurationStore(); + assertNotNull(store); + + BDBMessageStore bdbMessageStore = (BDBMessageStore) store; + ReplicatedEnvironment environment = (ReplicatedEnvironment) bdbMessageStore.getEnvironmentFacade().getEnvironment(); + ReplicationConfig replicationConfig = environment.getRepConfig(); + + assertEquals(nodeName, environment.getNodeName()); + assertEquals(groupName, environment.getGroup().getName()); + assertEquals(nodeHostPort, replicationConfig.getNodeHostPort()); + assertEquals(helperHostPort, replicationConfig.getHelperHosts()); + assertEquals(durability, environment.getConfig().getDurability().toString()); + assertEquals("Unexpected JE replication stream timeout", repStreamTimeout, replicationConfig.getConfigParam(ReplicationConfig.REP_STREAM_TIMEOUT)); + + assertTrue("Virtual host child has not been added", virtualHostAddedLatch.await(30, TimeUnit.SECONDS)); + assertTrue("Virtual host child has not had a state change", virtualHostStateChangeLatch.await(30, TimeUnit.SECONDS)); + VirtualHost<?, ?, ?> virtualHost = node.getVirtualHost(); + assertNotNull("Virtual host child was not added", virtualHost); + assertEquals("Unexpected virtual host name", groupName, virtualHost.getName()); + assertEquals("Unexpected virtual host store", store, virtualHost.getMessageStore()); + assertEquals("Unexpected virtual host state", State.ACTIVE, virtualHost.getState()); + + State currentState = node.setDesiredState(State.ACTIVE, State.STOPPED); + assertEquals("Unexpected state returned after stop", State.STOPPED, currentState); + assertEquals("Unexpected state", State.STOPPED, node.getState()); + + assertNull("Virtual host is not destroyed", node.getVirtualHost()); + + currentState = node.setDesiredState(State.STOPPED, State.DELETED); + assertEquals("Unexpected state returned after delete", State.DELETED, currentState); + assertEquals("Unexpected state", State.DELETED, node.getState()); + assertFalse("Store still exists", _bdbStorePath.exists()); + } + +} + + diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/VirtualHostTest.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/VirtualHostTest.java deleted file mode 100644 index abaaaa6d72..0000000000 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/VirtualHostTest.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.store.berkeleydb; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - -import com.sleepycat.je.rep.ReplicatedEnvironment; -import com.sleepycat.je.rep.ReplicationConfig; - -import org.apache.qpid.server.configuration.ConfigurationEntryStore; -import org.apache.qpid.server.configuration.RecovererProvider; -import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.ConfiguredObjectFactory; -import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl; -import org.apache.qpid.server.model.State; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; -import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.util.FileUtils; - -public class VirtualHostTest extends QpidTestCase -{ - - private Broker<?> _broker; - private StatisticsGatherer _statisticsGatherer; - private RecovererProvider _recovererProvider; - private File _bdbStorePath; - private VirtualHost<?,?,?> _host; - private ConfigurationEntryStore _store; - private TaskExecutor _taskExecutor; - - @Override - protected void setUp() throws Exception - { - super.setUp(); - - _store = mock(ConfigurationEntryStore.class); - _broker = BrokerTestHelper.createBrokerMock(); - _taskExecutor = new TaskExecutor(); - _taskExecutor.start(); - when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); - - _statisticsGatherer = mock(StatisticsGatherer.class); - - _bdbStorePath = new File(TMP_FOLDER, getTestName() + "." + System.currentTimeMillis()); - _bdbStorePath.deleteOnExit(); - } - - @Override - protected void tearDown() throws Exception - { - try - { - if (_host != null) - { - _host.setDesiredState(_host.getState(), State.STOPPED); - } - } - finally - { - _taskExecutor.stopImmediately(); - - if (_bdbStorePath != null) - { - FileUtils.delete(_bdbStorePath, true); - } - super.tearDown(); - } - } - - public void testCreateBdbHaVirtualHostFromConfigurationEntry() - { - String repStreamTimeout = "2 h"; - String nodeName = "node"; - String groupName = "group"; - String nodeHostPort = "localhost:" + findFreePort(); - String helperHostPort = nodeHostPort; - String durability = "NO_SYNC,SYNC,NONE"; - String virtualHostName = getName(); - - Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.NODE_NAME, nodeName); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.GROUP_NAME, groupName); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS, nodeHostPort); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.HELPER_ADDRESS, helperHostPort); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.DURABILITY, durability); - - messageStoreSettings.put(MessageStore.STORE_PATH, _bdbStorePath.getAbsolutePath()); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.REPLICATION_CONFIG, - Collections.singletonMap(ReplicationConfig.REP_STREAM_TIMEOUT, repStreamTimeout)); - - Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); - virtualHostAttributes.put(VirtualHost.NAME, virtualHostName); - virtualHostAttributes.put(VirtualHost.TYPE, BDBHAVirtualHost.TYPE); - virtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); - - _host = createHost(virtualHostAttributes); - _host.setDesiredState(State.INITIALISING, State.ACTIVE); - - assertEquals("Unexpected virtual host name", virtualHostName, _host.getName()); - assertEquals("Unexpected host type", BDBHAVirtualHost.TYPE, _host.getType()); - - assertEquals(messageStoreSettings, _host.getMessageStoreSettings()); - - BDBMessageStore messageStore = (BDBMessageStore) _host.getMessageStore(); - ReplicatedEnvironment environment = (ReplicatedEnvironment) messageStore.getEnvironmentFacade().getEnvironment(); - ReplicationConfig replicationConfig = environment.getRepConfig(); - - assertEquals(nodeName, environment.getNodeName()); - assertEquals(groupName, environment.getGroup().getName()); - assertEquals(nodeHostPort, replicationConfig.getNodeHostPort()); - assertEquals(helperHostPort, replicationConfig.getHelperHosts()); - assertEquals(durability, environment.getConfig().getDurability().toString()); - assertEquals("Unexpected JE replication stream timeout", repStreamTimeout, replicationConfig.getConfigParam(ReplicationConfig.REP_STREAM_TIMEOUT)); - } - - - private VirtualHost<?,?,?> createHost(Map<String, Object> attributes) - { - ConfiguredObjectFactory factory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); - attributes = new HashMap<String, Object>(attributes); - attributes.put(ConfiguredObject.ID, UUID.randomUUID()); - return (VirtualHost<?,?,?>) factory.create(VirtualHost.class, attributes,_broker); - } - -} - - diff --git a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8Test.java b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8Test.java index 57adc5afe4..9bd5c96fe6 100644 --- a/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8Test.java +++ b/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom7To8Test.java @@ -160,6 +160,7 @@ public class UpgradeFrom7To8Test extends AbstractUpgradeTestCase { Map<String, Object> expectedVirtualHostEntry = new HashMap<String, Object>(); expectedVirtualHostEntry.put("modelVersion", modelVersion); + expectedVirtualHostEntry.put(VirtualHost.NAME, getVirtualHost().getName()); UUID expectedUUID = UUIDGenerator.generateVhostUUID(getVirtualHost().getName()); return Collections.singletonMap(expectedUUID, expectedVirtualHostEntry); diff --git a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java index c682f44d60..fab889a49f 100644 --- a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java +++ b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBBackupTest.java @@ -31,9 +31,8 @@ import javax.jms.MessageConsumer; import javax.jms.Session; import org.apache.log4j.Logger; - -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBVirtualHostNode; import org.apache.qpid.test.utils.Piper; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.util.FileUtils; @@ -63,9 +62,9 @@ public class BDBBackupTest extends QpidBrokerTestCase super.setUp(); _backupToDir = new File(SYSTEM_TMP_DIR + File.separator + getTestName()); _backupToDir.mkdirs(); - Map<String, Object> virtualHostAttributes = getBrokerConfiguration().getObjectAttributes(VirtualHost.class,TEST_VHOST); - Map<String, Object> messageStoreSettings = (Map<String, Object>) virtualHostAttributes.get(VirtualHost.MESSAGE_STORE_SETTINGS); - _backupFromDir = new File(Strings.expand((String) messageStoreSettings.get(MessageStore.STORE_PATH))); + + Map<String, Object> virtualHostNodeAttributes = getBrokerConfiguration().getObjectAttributes(VirtualHostNode.class, TEST_VHOST); + _backupFromDir = new File(Strings.expand((String) virtualHostNodeAttributes.get(BDBVirtualHostNode.STORE_PATH))); boolean fromDirExistsAndIsDir = _backupFromDir.isDirectory(); assertTrue("backupFromDir " + _backupFromDir + " should already exist", fromDirExistsAndIsDir); } diff --git a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java index 55d4c78ccb..491856d953 100644 --- a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java +++ b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBUpgradeTest.java @@ -42,18 +42,17 @@ import javax.jms.TopicSubscriber; import javax.management.openmbean.CompositeData; import javax.management.openmbean.TabularDataSupport; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBVirtualHostNode; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.util.FileUtils; import org.apache.qpid.util.Strings; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Tests upgrading a BDB store on broker startup. @@ -86,10 +85,8 @@ public class BDBUpgradeTest extends QpidBrokerTestCase public void setUp() throws Exception { assertNotNull("QPID_WORK must be set", QPID_WORK_ORIG); - Map<String, Object> virtualHostAttributes = getBrokerConfiguration().getObjectAttributes(VirtualHost.class,TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); - @SuppressWarnings("unchecked") - Map<String, Object> messageStoreSettings = (Map<String, Object>) virtualHostAttributes.get(VirtualHost.MESSAGE_STORE_SETTINGS); - _storeLocation = Strings.expand((String)messageStoreSettings.get(MessageStore.STORE_PATH)); + Map<String, Object> virtualHostNodeAttributes = getBrokerConfiguration().getObjectAttributes(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + _storeLocation = Strings.expand((String)virtualHostNodeAttributes.get(BDBVirtualHostNode.STORE_PATH)); //Clear the two target directories if they exist. File directory = new File(_storeLocation); diff --git a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java index 0464269efc..0de61d68cd 100644 --- a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java +++ b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterBlackboxTest.java @@ -146,7 +146,6 @@ public class HAClusterBlackboxTest extends QpidBrokerTestCase assertEquals("Failover occurred unexpectedly", 1L, _failoverLatch.getCount()); } - @Override public void failoverComplete() { diff --git a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java index 248cd7dc3d..b414905ddc 100644 --- a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java +++ b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterTwoNodeTest.java @@ -169,8 +169,8 @@ public class HAClusterTwoNodeTest extends QpidBrokerTestCase public void testSecondaryDesignatedAsPrimaryAfterOrginalPrimaryStopped() throws Exception { startCluster(true); - _clusterCreator.stopNode(_clusterCreator.getBrokerPortNumberOfPrimary()); final ManagedBDBHAMessageStore storeBean = getStoreBeanForNodeAtBrokerPort(_clusterCreator.getBrokerPortNumberOfSecondaryNode()); + _clusterCreator.stopNode(_clusterCreator.getBrokerPortNumberOfPrimary()); assertFalse("Expected node to NOT be set as designated primary", storeBean.getDesignatedPrimary()); storeBean.setDesignatedPrimary(true); diff --git a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java index 78d58224f9..96a75db2cc 100644 --- a/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java +++ b/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HATestClusterCreator.java @@ -38,19 +38,18 @@ import java.util.concurrent.TimeUnit; import javax.jms.Connection; -import com.sleepycat.je.rep.ReplicationConfig; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; - import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQConnectionURL; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.berkeleydb.replication.ReplicatedEnvironmentFacadeFactory; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.virtualhostnode.berkeleydb.BDBHAVirtualHostNode; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.url.URLSyntaxException; +import com.sleepycat.je.rep.ReplicationConfig; + public class HATestClusterCreator { protected static final Logger LOGGER = Logger.getLogger(HATestClusterCreator.class); @@ -82,7 +81,7 @@ public class HATestClusterCreator { _testcase = testcase; _virtualHostName = virtualHostName; - _groupName = "group" + _testcase.getName(); + _groupName = virtualHostName; _ipAddressOfBroker = getIpAddressOfBrokerHost(); _numberOfNodes = numberOfNodes; _bdbHelperPort = 0; @@ -104,21 +103,23 @@ public class HATestClusterCreator } String nodeName = getNodeNameForNodeAt(bdbPort); - Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); - messageStoreSettings.put(MessageStore.STORE_PATH, System.getProperty("QPID_WORK") + File.separator + brokerPort); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.GROUP_NAME, _groupName); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.NODE_NAME, nodeName); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS, getNodeHostPortForNodeAt(bdbPort)); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.HELPER_ADDRESS, getHelperHostPort()); + + Map<String, Object> virtualHostNodeAttributes = new HashMap<String, Object>(); + virtualHostNodeAttributes.put(BDBHAVirtualHostNode.STORE_PATH, System.getProperty("QPID_WORK") + File.separator + brokerPort); + virtualHostNodeAttributes.put(BDBHAVirtualHostNode.GROUP_NAME, _groupName); + virtualHostNodeAttributes.put(BDBHAVirtualHostNode.NAME, nodeName); + virtualHostNodeAttributes.put(BDBHAVirtualHostNode.ADDRESS, getNodeHostPortForNodeAt(bdbPort)); + virtualHostNodeAttributes.put(BDBHAVirtualHostNode.HELPER_ADDRESS, getHelperHostPort()); + virtualHostNodeAttributes.put(BDBHAVirtualHostNode.TYPE, "BDB_HA"); + Map<String, String> repSettings = new HashMap<String, String>(); repSettings.put(ReplicationConfig.INSUFFICIENT_REPLICAS_TIMEOUT, "2 s"); repSettings.put(ReplicationConfig.ELECTIONS_PRIMARY_RETRIES, "0"); - messageStoreSettings.put(ReplicatedEnvironmentFacadeFactory.REPLICATION_CONFIG, repSettings ); + virtualHostNodeAttributes.put(BDBHAVirtualHostNode.REPLICATED_ENVIRONMENT_CONFIGURATION, repSettings); TestBrokerConfiguration brokerConfiguration = _testcase.getBrokerConfiguration(brokerPort); brokerConfiguration.addJmxManagementConfiguration(); - brokerConfiguration.setObjectAttribute(VirtualHost.class, _virtualHostName, VirtualHost.TYPE, BDBHAVirtualHost.TYPE); - brokerConfiguration.setObjectAttribute(VirtualHost.class, _virtualHostName, VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); + brokerConfiguration.setObjectAttributes(VirtualHostNode.class, _virtualHostName, virtualHostNodeAttributes); brokerPort = _testcase.getNextAvailable(bdbPort + 1); } @@ -132,10 +133,8 @@ public class HATestClusterCreator throw new IllegalArgumentException("Only two nodes groups have the concept of primary"); } TestBrokerConfiguration config = _testcase.getBrokerConfiguration(_primaryBrokerPort); - @SuppressWarnings("unchecked") - Map<String, Object> storeSetting = (Map<String, Object>) config.getObjectAttributes(VirtualHost.class, _virtualHostName).get(VirtualHost.MESSAGE_STORE_SETTINGS); - storeSetting.put(ReplicatedEnvironmentFacadeFactory.DESIGNATED_PRIMARY, designatedPrimary); - config.setObjectAttribute(VirtualHost.class, _virtualHostName, VirtualHost.MESSAGE_STORE_SETTINGS, storeSetting); + String nodeName = getNodeNameForNodeAt(_brokerPortToBdbPortMap.get(_primaryBrokerPort)); + config.setObjectAttribute(VirtualHostNode.class, nodeName, BDBHAVirtualHostNode.DESIGNATED_PRIMARY, designatedPrimary); config.setSaved(false); } @@ -369,15 +368,15 @@ public class HATestClusterCreator public void modifyClusterNodeBdbAddress(int brokerPortNumberToBeMoved, int newBdbPort) { TestBrokerConfiguration config = _testcase.getBrokerConfiguration(brokerPortNumberToBeMoved); + String nodeName = getNodeNameForNodeAt(_brokerPortToBdbPortMap.get(brokerPortNumberToBeMoved)); + + Map<String, Object> objectAttributes = config.getObjectAttributes(VirtualHostNode.class, nodeName); - @SuppressWarnings("unchecked") - Map<String, Object> storeSetting = (Map<String, Object>) config.getObjectAttributes(VirtualHost.class, _virtualHostName).get(VirtualHost.MESSAGE_STORE_SETTINGS); - String oldBdbHostPort = (String) storeSetting.get(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS); + String oldBdbHostPort = (String)objectAttributes.get(BDBHAVirtualHostNode.ADDRESS); String[] oldHostAndPort = StringUtils.split(oldBdbHostPort, ":"); String oldHost = oldHostAndPort[0]; String newBdbHostPort = oldHost + ":" + newBdbPort; - storeSetting.put(ReplicatedEnvironmentFacadeFactory.NODE_ADDRESS, newBdbHostPort); - config.setObjectAttribute(VirtualHost.class, _virtualHostName, VirtualHost.MESSAGE_STORE_SETTINGS, storeSetting); + config.setObjectAttribute(VirtualHostNode.class, nodeName, BDBHAVirtualHostNode.ADDRESS, newBdbHostPort); config.setSaved(false); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/BrokerStoreUpgrader.java b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/BrokerStoreUpgrader.java index 79d1595b27..1a942a2e4a 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/BrokerStoreUpgrader.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/BrokerStoreUpgrader.java @@ -1,4 +1,4 @@ -package org.apache.qpid.server.configuration.startup;/* +/* * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -18,7 +18,7 @@ package org.apache.qpid.server.configuration.startup;/* * under the License. * */ - +package org.apache.qpid.server.configuration.startup; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -30,7 +30,6 @@ import java.util.Set; import java.util.UUID; import org.apache.log4j.Logger; - import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.model.Broker; @@ -41,82 +40,58 @@ import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.DurableConfigurationStoreUpgrader; -import org.apache.qpid.server.store.NonNullUpgrader; +import org.apache.qpid.server.store.NullUpgrader; import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; import org.apache.qpid.server.util.Action; public class BrokerStoreUpgrader { - private static Logger LOGGER = Logger.getLogger(BrokerStoreUpgrader.class); - - private static Map<String, UpgraderPhaseFactory> _upgraders = new HashMap<String, UpgraderPhaseFactory>(); private final SystemContext _systemContext; + private Map<String, UpgraderPhaseFactory> _upgraders = new HashMap<String, UpgraderPhaseFactory>(); + + + // Note: don't use externally defined constants in upgraders in case they change, the values here MUST stay the same + // no matter what changes are made to the code in the future public BrokerStoreUpgrader(SystemContext systemContext) { _systemContext = systemContext; + + register(new Upgrader_1_0_to_1_1()); + register(new Upgrader_1_1_to_1_2()); + register(new Upgrader_1_2_to_1_3()); + register(new Upgrader_1_3_to_1_4()); } - private static abstract class UpgraderPhaseFactory + private void register(UpgraderPhaseFactory factory) { - private final String _toVersion; - - protected UpgraderPhaseFactory(String fromVersion, String toVersion) - { - _upgraders.put(fromVersion, this); - _toVersion = toVersion; - } - - public String getToVersion() - { - return _toVersion; - } - - public abstract BrokerStoreUpgraderPhase newInstance(); + _upgraders.put(factory.getFromVersion(), factory); } - private static abstract class BrokerStoreUpgraderPhase extends NonNullUpgrader + private final class Upgrader_1_0_to_1_1 extends UpgraderPhaseFactory { - private final String _toVersion; - - protected BrokerStoreUpgraderPhase(String toVersion) + private Upgrader_1_0_to_1_1() { - _toVersion = toVersion; + super("1.0", "1.1"); } - - protected ConfiguredObjectRecord upgradeBrokerRecord(ConfiguredObjectRecord record) - { - Map<String, Object> updatedAttributes = new HashMap<String, Object>(record.getAttributes()); - updatedAttributes.put(Broker.MODEL_VERSION, _toVersion); - record = createModifiedRecord(record, updatedAttributes); - getUpdateMap().put(record.getId(), record); - return record; - } - } - - // Note: don't use externally defined constants in upgraders in case they change, the values here MUST stay the same - // no matter what changes are made to the code in the future - - private final static UpgraderPhaseFactory UPGRADE_1_0 = new UpgraderPhaseFactory("1.0", "1.1") - { @Override - public BrokerStoreUpgraderPhase newInstance() + public StoreUpgraderPhase newInstance() { - return new BrokerStoreUpgraderPhase(getToVersion()) + return new StoreUpgraderPhase(Broker.MODEL_VERSION, getToVersion()) { @Override public void configuredObject(ConfiguredObjectRecord record) { if (record.getType().equals("Broker")) { - record = upgradeBrokerRecord(record); + record = upgradeRootRecord(record); } else if (record.getType().equals("VirtualHost") && record.getAttributes().containsKey("storeType")) { Map<String, Object> updatedAttributes = new HashMap<String, Object>(record.getAttributes()); updatedAttributes.put("type", "STANDARD"); - record = createModifiedRecord(record, updatedAttributes); + record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), updatedAttributes, record.getParents()); getUpdateMap().put(record.getId(), record); } @@ -131,24 +106,19 @@ public class BrokerStoreUpgrader } }; } - - - }; - - - protected static ConfiguredObjectRecordImpl createModifiedRecord(final ConfiguredObjectRecord record, - final Map<String, Object> updatedAttributes) - { - - return new ConfiguredObjectRecordImpl(record.getId(), record.getType(), updatedAttributes, record.getParents()); } - private final static UpgraderPhaseFactory UPGRADE_1_1 = new UpgraderPhaseFactory("1.1", "1.2") + private static final class Upgrader_1_1_to_1_2 extends UpgraderPhaseFactory { + private Upgrader_1_1_to_1_2() + { + super("1.1", "1.2"); + } + @Override - public BrokerStoreUpgraderPhase newInstance() + public StoreUpgraderPhase newInstance() { - return new BrokerStoreUpgraderPhase(getToVersion()) + return new StoreUpgraderPhase(Broker.MODEL_VERSION, getToVersion()) { @Override @@ -156,7 +126,7 @@ public class BrokerStoreUpgrader { if (record.getType().equals("Broker")) { - record = upgradeBrokerRecord(record); + record = upgradeRootRecord(record); } getNextUpgrader().configuredObject(record); @@ -170,15 +140,19 @@ public class BrokerStoreUpgrader } }; } - }; - + } - private final static UpgraderPhaseFactory UPGRADE_1_2 = new UpgraderPhaseFactory("1.2", "1.3") + private static final class Upgrader_1_2_to_1_3 extends UpgraderPhaseFactory { + private Upgrader_1_2_to_1_3() + { + super("1.2", "1.3"); + } + @Override - public BrokerStoreUpgraderPhase newInstance() + public StoreUpgraderPhase newInstance() { - return new BrokerStoreUpgraderPhase(getToVersion()) + return new StoreUpgraderPhase(Broker.MODEL_VERSION, getToVersion()) { @Override @@ -188,7 +162,7 @@ public class BrokerStoreUpgrader { Map<String, Object> updatedAttributes = new HashMap<String, Object>(record.getAttributes()); updatedAttributes.put("trustStoreType", updatedAttributes.remove("type")); - record = createModifiedRecord(record, updatedAttributes); + record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), updatedAttributes, record.getParents()); getUpdateMap().put(record.getId(), record); } @@ -196,13 +170,13 @@ public class BrokerStoreUpgrader { Map<String, Object> updatedAttributes = new HashMap<String, Object>(record.getAttributes()); updatedAttributes.put("keyStoreType", updatedAttributes.remove("type")); - record = createModifiedRecord(record, updatedAttributes); + record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), updatedAttributes, record.getParents()); getUpdateMap().put(record.getId(), record); } else if (record.getType().equals("Broker")) { - record = upgradeBrokerRecord(record); + record = upgradeRootRecord(record); } getNextUpgrader().configuredObject(record); @@ -216,17 +190,22 @@ public class BrokerStoreUpgrader } }; } - }; - + } - private final static UpgraderPhaseFactory UPGRADE_1_3 = new UpgraderPhaseFactory("1.3", "1.4") + private static final class Upgrader_1_3_to_1_4 extends UpgraderPhaseFactory { + private Upgrader_1_3_to_1_4() + { + super("1.3", "1.4"); + } + @Override - public BrokerStoreUpgraderPhase newInstance() + public StoreUpgraderPhase newInstance() { - return new BrokerStoreUpgraderPhase(getToVersion()) + return new StoreUpgraderPhase(Broker.MODEL_VERSION, getToVersion()) { + @SuppressWarnings("serial") private Map<String, VirtualHostEntryUpgrader> _vhostUpgraderMap = new HashMap<String, VirtualHostEntryUpgrader>() {{ put("BDB_HA", new BdbHaVirtualHostUpgrader()); @@ -257,13 +236,13 @@ public class BrokerStoreUpgrader { Map<String, Object> updatedAttributes = new HashMap<String, Object>(record.getAttributes()); updatedAttributes.put("type", updatedAttributes.remove("pluginType")); - record = createModifiedRecord(record, updatedAttributes); + record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), updatedAttributes, record.getParents()); getUpdateMap().put(record.getId(), record); } else if (record.getType().equals("Broker")) { - record = upgradeBrokerRecord(record); + record = upgradeRootRecord(record); } getNextUpgrader().configuredObject(record); @@ -277,9 +256,7 @@ public class BrokerStoreUpgrader } }; } - - - }; + } private static interface VirtualHostEntryUpgrader { @@ -288,6 +265,7 @@ public class BrokerStoreUpgrader private static class StandardVirtualHostUpgrader implements VirtualHostEntryUpgrader { + @SuppressWarnings("serial") Map<String, AttributesTransformer> _messageStoreAttributeTransformers = new HashMap<String, AttributesTransformer>() {{ put("DERBY", new AttributesTransformer(). @@ -317,6 +295,7 @@ public class BrokerStoreUpgrader addAttributeTransformer("storeType", mutateAttributeValue("JDBC"))); }}; + @SuppressWarnings("serial") Map<String, AttributesTransformer> _configurationStoreAttributeTransformers = new HashMap<String, AttributesTransformer>() {{ put("DERBY", new AttributesTransformer(). @@ -581,12 +560,9 @@ public class BrokerStoreUpgrader } } - - - - public Broker upgrade(DurableConfigurationStore store) + public Broker<?> upgrade(DurableConfigurationStore store) { - final BrokerStoreRecoveryHandler recoveryHandler = new BrokerStoreRecoveryHandler(_systemContext, store); + final BrokerStoreRecoveryHandler recoveryHandler = new BrokerStoreRecoveryHandler(_systemContext, store, _upgraders); store.openConfigurationStore(_systemContext, Collections.<String,Object>emptyMap()); store.visitConfiguredObjectRecords(recoveryHandler); @@ -602,11 +578,13 @@ public class BrokerStoreUpgrader private DurableConfigurationStore _store; private final Map<UUID, ConfiguredObjectRecord> _records = new HashMap<UUID, ConfiguredObjectRecord>(); private final SystemContext _systemContext; + private Map<String, UpgraderPhaseFactory> _upgraders; - private BrokerStoreRecoveryHandler(final SystemContext systemContext, DurableConfigurationStore store) + private BrokerStoreRecoveryHandler(final SystemContext systemContext, DurableConfigurationStore store, Map<String, UpgraderPhaseFactory> upgraders) { _systemContext = systemContext; _store = store; + _upgraders = upgraders; } @@ -631,7 +609,7 @@ public class BrokerStoreUpgrader { LOGGER.debug("Adding broker store upgrader from model version: " + version); final UpgraderPhaseFactory upgraderPhaseFactory = _upgraders.get(version); - BrokerStoreUpgraderPhase upgrader = upgraderPhaseFactory.newInstance(); + StoreUpgraderPhase upgrader = upgraderPhaseFactory.newInstance(); if(_upgrader == null) { _upgrader = upgrader; @@ -645,69 +623,11 @@ public class BrokerStoreUpgrader if(_upgrader == null) { - _upgrader = new DurableConfigurationStoreUpgrader() - { - - @Override - public void configuredObject(final ConfiguredObjectRecord record) - { - } - - @Override - public void complete() - { - } - - @Override - public void setNextUpgrader(final DurableConfigurationStoreUpgrader upgrader) - { - } - - @Override - public Map<UUID, ConfiguredObjectRecord> getUpdatedRecords() - { - return Collections.emptyMap(); - } - - @Override - public Map<UUID, ConfiguredObjectRecord> getDeletedRecords() - { - return Collections.emptyMap(); - } - }; + _upgrader = new NullUpgrader(); } else { - _upgrader.setNextUpgrader(new DurableConfigurationStoreUpgrader() - { - @Override - public void configuredObject(final ConfiguredObjectRecord record) - { - } - - @Override - public void complete() - { - - } - - @Override - public void setNextUpgrader(final DurableConfigurationStoreUpgrader upgrader) - { - } - - @Override - public Map<UUID, ConfiguredObjectRecord> getUpdatedRecords() - { - return Collections.emptyMap(); - } - - @Override - public Map<UUID, ConfiguredObjectRecord> getDeletedRecords() - { - return Collections.emptyMap(); - } - }); + _upgrader.setNextUpgrader(new NullUpgrader()); } for(ConfiguredObjectRecord record : _records.values()) diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgraderPhase.java b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgraderPhase.java new file mode 100644 index 0000000000..5762a8f8e6 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/StoreUpgraderPhase.java @@ -0,0 +1,49 @@ +/* + * + * 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.configuration.startup; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.server.store.ConfiguredObjectRecord; +import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; +import org.apache.qpid.server.store.NonNullUpgrader; + +public abstract class StoreUpgraderPhase extends NonNullUpgrader +{ + private final String _toVersion; + private final String _versionAttributeName; + + protected StoreUpgraderPhase(String versionAttributeName, String toVersion) + { + _toVersion = toVersion; + _versionAttributeName = versionAttributeName; + } + + protected ConfiguredObjectRecord upgradeRootRecord(ConfiguredObjectRecord record) + { + Map<String, Object> updatedAttributes = new HashMap<String, Object>(record.getAttributes()); + updatedAttributes.put(_versionAttributeName, _toVersion); + record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), updatedAttributes, record.getParents()); + getUpdateMap().put(record.getId(), record); + return record; + } +}
\ No newline at end of file diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/UpgraderPhaseFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/UpgraderPhaseFactory.java new file mode 100644 index 0000000000..26686c67cd --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/startup/UpgraderPhaseFactory.java @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.configuration.startup; + +public abstract class UpgraderPhaseFactory +{ + private final String _toVersion; + private final String _fromVersion; + + protected UpgraderPhaseFactory(String fromVersion, String toVersion) + { + _toVersion = toVersion; + _fromVersion = fromVersion; + } + + public String getToVersion() + { + return _toVersion; + } + + public String getFromVersion() + { + return _fromVersion; + } + + public abstract StoreUpgraderPhase newInstance(); +}
\ No newline at end of file diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java index b76041dcce..94f496d89e 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListener.java @@ -34,6 +34,7 @@ import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Model; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.store.DurableConfigurationStore; public class StoreConfigurationChangeListener implements ConfigurationChangeListener @@ -59,8 +60,8 @@ public class StoreConfigurationChangeListener implements ConfigurationChangeList @Override public void childAdded(ConfiguredObject object, ConfiguredObject child) { - // exclude VirtualHost children from storing in broker store - if (!(object instanceof VirtualHost)) + // exclude VirtualHostNode children from storing in broker store + if (!(object instanceof VirtualHostNode)) { child.addChangeListener(this); _store.update(true,child.asObjectRecord()); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java index d69d6e3076..f159f70d20 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java @@ -61,7 +61,7 @@ abstract public class AbstractConfiguredObjectTypeFactory<X extends AbstractConf protected abstract X createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents); - public final <C extends ConfiguredObject<C>> C getParent(Class<C> parentClass, ConfiguredObject<?>... parents) + public final <C extends ConfiguredObject<?>> C getParent(Class<C> parentClass, ConfiguredObject<?>... parents) { if(!parents[0].getModel().getParentTypes((Class<? extends ConfiguredObject>) getCategoryClass()).contains( diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java index 16aa3e8916..024a7b0bfb 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java @@ -136,7 +136,7 @@ public interface Broker<X extends Broker<X>> extends ConfiguredObject<X>, EventL //children - Collection < VirtualHost<?,?,?> > getVirtualHosts(); + Collection<VirtualHostNode<?>> getVirtualHostNodes(); Collection<Port<?>> getPorts(); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java index 7a6fd2a501..bcfb413451 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java @@ -38,9 +38,10 @@ public final class BrokerModel extends Model * 1.1 Addition of mandatory virtual host type / different types of virtual host * 1.3 Truststore/Keystore type => trustStoreType / type => keyStoreType * 1.4 Separate messageStoreSettings from virtualhost + * 2.0 Introduce VirtualHostNode as a child of a Broker instead of VirtualHost */ - public static final int MODEL_MAJOR_VERSION = 1; - public static final int MODEL_MINOR_VERSION = 4; + public static final int MODEL_MAJOR_VERSION = 2; + public static final int MODEL_MINOR_VERSION = 0; public static final String MODEL_VERSION = MODEL_MAJOR_VERSION + "." + MODEL_MINOR_VERSION; private static final Model MODEL_INSTANCE = new BrokerModel(); private final Map<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>> _parents = @@ -60,7 +61,7 @@ public final class BrokerModel extends Model addRelationship(SystemContext.class, Broker.class); - addRelationship(Broker.class, VirtualHost.class); + addRelationship(Broker.class, VirtualHostNode.class); addRelationship(Broker.class, Port.class); addRelationship(Broker.class, AccessControlProvider.class); addRelationship(Broker.class, AuthenticationProvider.class); @@ -69,6 +70,8 @@ public final class BrokerModel extends Model addRelationship(Broker.class, KeyStore.class); addRelationship(Broker.class, Plugin.class); + addRelationship(VirtualHostNode.class, VirtualHost.class); + addRelationship(VirtualHost.class, Exchange.class); addRelationship(VirtualHost.class, Queue.class); addRelationship(VirtualHost.class, Connection.class); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java index d5ccd6a69f..48206ccdf4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java @@ -44,8 +44,8 @@ public interface VirtualHost<X extends VirtualHost<X, Q, E>, Q extends Queue<?>, String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes"; String SECURITY_ACL = "securityAcl"; String HOUSE_KEEPING_THREAD_COUNT = "houseKeepingThreadCount"; - String CONFIGURATION_STORE_SETTINGS = "configurationStoreSettings"; String MESSAGE_STORE_SETTINGS = "messageStoreSettings"; + String MODEL_VERSION = "modelVersion"; // TODO - this isn't really an attribute @ManagedAttribute( derived = true ) @@ -111,8 +111,8 @@ public interface VirtualHost<X extends VirtualHost<X, Q, E>, Q extends Queue<?>, @ManagedAttribute( automate = true ) Map<String, Object> getMessageStoreSettings(); - @ManagedAttribute( automate = true ) - Map<String, Object> getConfigurationStoreSettings(); + @ManagedAttribute( derived = true ) + String getModelVersion(); @ManagedStatistic long getQueueCount(); @@ -135,7 +135,6 @@ public interface VirtualHost<X extends VirtualHost<X, Q, E>, Q extends Queue<?>, @ManagedStatistic long getMessagesOut(); - //children Collection<VirtualHostAlias> getAliases(); Collection<Connection> getConnections(); diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java new file mode 100644 index 0000000000..8d80ad19d7 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java @@ -0,0 +1,36 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model; + +import org.apache.qpid.server.store.DurableConfigurationStore; + +@ManagedObject(category=true, managesChildren=false) +public interface VirtualHostNode<X extends VirtualHostNode<X>> extends ConfiguredObject<X> +{ + public static final String IS_MESSAGE_STORE_PROVIDER = "messageStoreProvider"; + + @ManagedAttribute (automate = true, defaultValue = "false") + boolean isMessageStoreProvider(); + + VirtualHost<?,?,?> getVirtualHost(); + + DurableConfigurationStore getConfigurationStore(); +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index 3dd261e9a9..0a3ffe4595 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -36,7 +36,6 @@ import java.util.regex.Pattern; import javax.security.auth.Subject; import org.apache.log4j.Logger; - import org.apache.qpid.common.QpidProperties; import org.apache.qpid.server.BrokerOptions; import org.apache.qpid.server.configuration.IllegalConfigurationException; @@ -108,8 +107,6 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple attributes, parent.getTaskExecutor()); - //_virtualHostRegistry = new VirtualHostRegistry(parent.getEventLogger()); - _logRecorder = parent.getLogRecorder(); _eventLogger = parent.getEventLogger(); _brokerOptions = parent.getBrokerOptions(); @@ -235,9 +232,9 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple { addAccessControlProvider(accessControlProvider); } - for(VirtualHost<?,?,?> virtualHost : getChildren(VirtualHost.class)) + for(VirtualHostNode<?> virtualHostNode : getChildren(VirtualHostNode.class)) { - addVirtualHost(virtualHost); + addVirtualHostNode(virtualHostNode); } @@ -358,9 +355,10 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple return BrokerModel.MODEL_VERSION; } - public Collection<VirtualHost<?,?,?>> getVirtualHosts() + @Override + public Collection<VirtualHostNode<?>> getVirtualHostNodes() { - Collection children = getChildren(VirtualHost.class); + Collection children = getChildren(VirtualHostNode.class); return children; } @@ -402,11 +400,11 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple return children; } - private VirtualHost createVirtualHost(final Map<String, Object> attributes) + private VirtualHostNode<?> createVirtualHostNode(Map<String, Object> attributes) throws AccessControlException, IllegalArgumentException { - final VirtualHost virtualHost = getObjectFactory().create(VirtualHost.class,attributes,this); + final VirtualHostNode virtualHostNode = getObjectFactory().create(VirtualHostNode.class,attributes, this); // permission has already been granted to create the virtual host // disable further access check on other operations, e.g. create exchange @@ -415,20 +413,13 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple @Override public Object run() { - virtualHost.setDesiredState(State.INITIALISING, State.ACTIVE); + virtualHostNode.setDesiredState(State.INITIALISING, State.ACTIVE); return null; } }); - return virtualHost; + return virtualHostNode; } - private boolean deleteVirtualHost(final VirtualHost vhost) throws AccessControlException, IllegalStateException - { - vhost.removeChangeListener(this); - return true; - } - - public State getState() { return null; //TODO @@ -467,9 +458,9 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple @Override public C execute() { - if (childClass == VirtualHost.class) + if (childClass == VirtualHostNode.class) { - return (C) createVirtualHost(attributes); + return (C) createVirtualHostNode(attributes); } else if (childClass == Port.class) { @@ -720,10 +711,16 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple return true; } - private void addVirtualHost(VirtualHost<?,?,?> virtualHost) + private void addVirtualHostNode(VirtualHostNode<?> virtualHostNode) { + virtualHostNode.addChangeListener(this); + } - virtualHost.addChangeListener(this); + + private boolean deleteVirtualHostNode(final VirtualHostNode virtualHostNode) throws AccessControlException, IllegalStateException + { + virtualHostNode.removeChangeListener(this); + return true; } @Override @@ -815,9 +812,9 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple { childDeleted = deletePort(oldState, (Port)object); } - else if(object instanceof VirtualHost) + else if(object instanceof VirtualHostNode) { - childDeleted = deleteVirtualHost((VirtualHost)object); + childDeleted = deleteVirtualHostNode((VirtualHostNode)object); } else if(object instanceof GroupProvider) { @@ -890,9 +887,17 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple } @Override - public VirtualHost findVirtualHostByName(String name) + public VirtualHost<?,?,?> findVirtualHostByName(String name) { - return getChildByName(VirtualHost.class, name); + for (VirtualHostNode<?> virtualHostNode : getChildren(VirtualHostNode.class)) + { + VirtualHost<?, ?, ?> virtualHost = virtualHostNode.getVirtualHost(); + if (virtualHost != null && virtualHost.getName().equals(name)) + { + return virtualHost; + } + } + return null; } @Override @@ -1042,11 +1047,12 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple _messagesReceived.reset(); _dataReceived.reset(); - for (VirtualHost vhost : getVirtualHosts()) + for (VirtualHostNode<?> virtualHostNode : getChildren(VirtualHostNode.class)) { - if(vhost instanceof VirtualHostImpl) + VirtualHost<?, ?, ?> virtualHost = virtualHostNode.getVirtualHost(); + if (virtualHost instanceof VirtualHostImpl) { - ((VirtualHostImpl) vhost).resetStatistics(); + ((VirtualHostImpl) virtualHost).resetStatistics(); } } } @@ -1098,37 +1104,38 @@ public class BrokerAdapter extends AbstractConfiguredObject<BrokerAdapter> imple _eventLogger.message(BrokerMessages.STATS_MSGS(RECEIVED, _messagesReceived.getPeak(), _messagesReceived.getTotal())); - Collection<VirtualHost<?,?,?>> hosts = getVirtualHosts(); - for (VirtualHost vhost : hosts) + for (VirtualHostNode<?> virtualHostNode : getChildren(VirtualHostNode.class)) + { + VirtualHost<?, ?, ?> virtualHost = virtualHostNode.getVirtualHost(); + if (virtualHost instanceof VirtualHostImpl) { - if(vhost instanceof VirtualHostImpl) - { - VirtualHostImpl vhostImpl = (VirtualHostImpl) vhost; - String name = vhost.getName(); - StatisticsCounter dataDelivered = vhostImpl.getDataDeliveryStatistics(); - StatisticsCounter messagesDelivered = vhostImpl.getMessageDeliveryStatistics(); - StatisticsCounter dataReceived = vhostImpl.getDataReceiptStatistics(); - StatisticsCounter messagesReceived = vhostImpl.getMessageReceiptStatistics(); - EventLogger logger = vhostImpl.getEventLogger(); - logger.message(VirtualHostMessages.STATS_DATA(name, - DELIVERED, - dataDelivered.getPeak() / 1024.0, - dataDelivered.getTotal())); - logger.message(VirtualHostMessages.STATS_MSGS(name, - DELIVERED, - messagesDelivered.getPeak(), - messagesDelivered.getTotal())); - logger.message(VirtualHostMessages.STATS_DATA(name, - RECEIVED, - dataReceived.getPeak() / 1024.0, - dataReceived.getTotal())); - logger.message(VirtualHostMessages.STATS_MSGS(name, - RECEIVED, - messagesReceived.getPeak(), - messagesReceived.getTotal())); - } + VirtualHostImpl vhostImpl = (VirtualHostImpl) virtualHost; + String name = virtualHost.getName(); + StatisticsCounter dataDelivered = vhostImpl.getDataDeliveryStatistics(); + StatisticsCounter messagesDelivered = vhostImpl.getMessageDeliveryStatistics(); + StatisticsCounter dataReceived = vhostImpl.getDataReceiptStatistics(); + StatisticsCounter messagesReceived = vhostImpl.getMessageReceiptStatistics(); + EventLogger logger = vhostImpl.getEventLogger(); + logger.message(VirtualHostMessages.STATS_DATA(name, + DELIVERED, + dataDelivered.getPeak() / 1024.0, + dataDelivered.getTotal())); + logger.message(VirtualHostMessages.STATS_MSGS(name, + DELIVERED, + messagesDelivered.getPeak(), + messagesDelivered.getTotal())); + logger.message(VirtualHostMessages.STATS_DATA(name, + RECEIVED, + dataReceived.getPeak() / 1024.0, + dataReceived.getTotal())); + logger.message(VirtualHostMessages.STATS_MSGS(name, + RECEIVED, + messagesReceived.getPeak(), + messagesReceived.getTotal())); + } + } if (_reset) { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/StandardVirtualHostFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/StandardVirtualHostFactory.java index 64845e94f3..51f8897d67 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/StandardVirtualHostFactory.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/StandardVirtualHostFactory.java @@ -23,8 +23,8 @@ package org.apache.qpid.server.model.adapter; import java.util.Map; import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.virtualhost.StandardVirtualHost; public class StandardVirtualHostFactory extends AbstractConfiguredObjectTypeFactory<StandardVirtualHost> @@ -39,8 +39,8 @@ public class StandardVirtualHostFactory extends AbstractConfiguredObjectTypeFact public StandardVirtualHost createInstance(final Map<String, Object> attributes, final ConfiguredObject<?>... parents) { - final Broker broker = getParent(Broker.class, parents); - return new StandardVirtualHost(attributes, broker); + final VirtualHostNode<?> virtualHostNode = getParent(VirtualHostNode.class, parents); + return new StandardVirtualHost(attributes, virtualHostNode); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java index 4121e24368..436122d2e1 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java @@ -47,6 +47,7 @@ import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.MapValueConverter; import org.apache.qpid.server.util.ParameterizedTypeImpl; @@ -238,13 +239,17 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo public Collection<VirtualHostAlias> getVirtualHostBindings() { List<VirtualHostAlias> aliases = new ArrayList<VirtualHostAlias>(); - for(VirtualHost<?,?,?> vh : _broker.getVirtualHosts()) + for(VirtualHostNode<?> vhn : _broker.getVirtualHostNodes()) { - for(VirtualHostAlias<?> alias : vh.getAliases()) + VirtualHost<?, ?, ?> vh = vhn.getVirtualHost(); + if (vh != null) { - if(alias.getPort().equals(this)) + for(VirtualHostAlias<?> alias : vh.getAliases()) { - aliases.add(alias); + if(alias.getPort().equals(this)) + { + aliases.add(alias); + } } } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java index ad52f420b6..3952ea3871 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java @@ -99,7 +99,8 @@ public class AmqpPortImpl extends AbstractPortWithAuthProvider<AmqpPortImpl> imp { name = _broker.getDefaultVirtualHost(); } - return (VirtualHostImpl) _broker.getChildByName(VirtualHost.class, name); + + return (VirtualHostImpl) _broker.findVirtualHostByName(name); } protected Set<Protocol> getDefaultProtocols() diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java index b83222f798..ba398f129d 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java @@ -21,13 +21,16 @@ package org.apache.qpid.server.plugin; import java.util.Map; + import org.apache.qpid.server.store.DurableConfigurationStore; public interface DurableConfigurationStoreFactory extends Pluggable { + PluggableFactoryLoader<DurableConfigurationStoreFactory> FACTORY_LOADER = new PluggableFactoryLoader<DurableConfigurationStoreFactory>(DurableConfigurationStoreFactory.class); + String getType(); DurableConfigurationStore createDurableConfigurationStore(); - void validateAttributes(Map<String, Object> attributes); + void validateConfigurationStoreSettings(Map<String, Object> attributes); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java deleted file mode 100644 index 75fe2a6642..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.store; - -import java.util.UUID; - -import org.apache.qpid.server.model.ConfiguredObject; - -public abstract class AbstractDurableConfiguredObjectRecoverer<T extends ConfiguredObject> implements DurableConfiguredObjectRecoverer -{ - @Override - public void load(final DurableConfigurationRecoverer durableConfigurationRecoverer, - final ConfiguredObjectRecord record) - { - final UnresolvedObject<T> obj = createUnresolvedObject(record); - UnresolvedDependency[] dependencies = obj.getUnresolvedDependencies(); - for(final UnresolvedDependency dependency : dependencies) - { - if(dependency.getId() != null) - { - Object dep; - if ((dep = durableConfigurationRecoverer.getResolvedObject(dependency.getType(), dependency.getId())) - != null) - { - dependency.resolve(dep); - } - else - { - durableConfigurationRecoverer.addResolutionListener(dependency.getType(), dependency.getId(), - null, new DependencyListener() - { - - @Override - public void dependencyResolved(final String depType, - final UUID depId, - final ConfiguredObject o) - { - dependency.resolve(o); - if (obj.getUnresolvedDependencies().length - == 0) - { - durableConfigurationRecoverer.resolve( - getType(), - record.getId(), - obj.resolve()); - } - } - } - ); - } - } - else - { - Object dep; - - if ((dep = durableConfigurationRecoverer.getResolvedObject(dependency.getType(), dependency.getName())) - != null) - { - dependency.resolve(dep); - } - else - { - durableConfigurationRecoverer.addResolutionListener(dependency.getType(), dependency.getId(), - dependency.getName(), new DependencyListener() - { - - @Override - public void dependencyResolved(final String depType, - final UUID depId, - final ConfiguredObject o) - { - dependency.resolve(o); - if (obj.getUnresolvedDependencies().length - == 0) - { - durableConfigurationRecoverer.resolve( - getType(), - record.getId(), - obj.resolve()); - } - } - } - ); - } - } - } - if(obj.getUnresolvedDependencies().length == 0) - { - durableConfigurationRecoverer.resolve(getType(), record.getId(), obj.resolve()); - } - else - { - durableConfigurationRecoverer.addUnresolvedObject(getType(), record.getId(), obj); - } - - } - - public abstract UnresolvedObject<T> createUnresolvedObject(final ConfiguredObjectRecord record); - -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java index 0e61ec9b47..2f83b34692 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java @@ -2495,5 +2495,12 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC { return Collections.unmodifiableMap(_parents); } + + @Override + public String toString() + { + return "ConfiguredObjectRecordImpl [_id=" + _id + ", _type=" + _type + ", _attributes=" + _attributes + ", _parents=" + + _parents + "]"; + } } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java index 63413fc0de..e2c43f5012 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java @@ -32,7 +32,6 @@ import java.util.concurrent.atomic.AtomicLong; 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.Transaction.Record; import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; import org.apache.qpid.server.store.handler.DistributedTransactionHandler; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordRecoveverAndUpgrader.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordRecoveverAndUpgrader.java deleted file mode 100644 index e9e6d88f36..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordRecoveverAndUpgrader.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.store; - -import java.util.Map; - -import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; -import org.apache.qpid.server.virtualhost.DefaultUpgraderProvider; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; - -public class ConfiguredObjectRecordRecoveverAndUpgrader implements ConfiguredObjectRecordHandler -{ - private DurableConfigurationRecoverer _configRecoverer; - private DurableConfigurationStore _store; - - public ConfiguredObjectRecordRecoveverAndUpgrader(VirtualHostImpl virtualHost, Map<String, DurableConfiguredObjectRecoverer> recoverers) - { - DefaultUpgraderProvider upgraderProvider = new DefaultUpgraderProvider(virtualHost); - _configRecoverer = new DurableConfigurationRecoverer(virtualHost.getName(), recoverers, upgraderProvider, virtualHost.getEventLogger()); - _store = virtualHost.getDurableConfigurationStore(); - } - - @Override - public void begin() - { - _configRecoverer.beginConfigurationRecovery(_store); - } - - @Override - public boolean handle(ConfiguredObjectRecord record) - { - _configRecoverer.configuredObject(record); - return true; - } - - @Override - public void end() - { - _configRecoverer.completeConfigurationRecovery(); - } - -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java deleted file mode 100644 index 52d690df53..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.store; - -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; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.logging.messages.ConfigStoreMessages; -import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.ConfiguredObject; - -public class DurableConfigurationRecoverer implements ConfigurationRecoveryHandler -{ - private static final Logger _logger = Logger.getLogger(DurableConfigurationRecoverer.class); - - private final Map<String, Map<UUID, ConfiguredObject>> _resolvedObjects = new HashMap<String, Map<UUID, ConfiguredObject>>(); - - private final Map<String, Map<UUID, UnresolvedObject>> _unresolvedObjects = - new HashMap<String, Map<UUID, UnresolvedObject>>(); - private final List<ConfiguredObjectRecord> _records = new ArrayList<ConfiguredObjectRecord>(); - - private final Map<String, Map<UUID, List<DependencyListener>>> _dependencyListeners = - new HashMap<String, Map<UUID, List<DependencyListener>>>(); - private final Map<String, Map<String, List<DependencyListener>>> _dependencyNameListeners = - new HashMap<String, Map<String, List<DependencyListener>>>(); - - private final Map<String, DurableConfiguredObjectRecoverer> _recoverers; - private final UpgraderProvider _upgraderProvider; - private final EventLogger _eventLogger; - - private DurableConfigurationStoreUpgrader _upgrader; - - private DurableConfigurationStore _store; - private final String _name; - - private MessageStoreLogSubject _logSubject; - - public DurableConfigurationRecoverer(final String name, - Map<String, DurableConfiguredObjectRecoverer> recoverers, - UpgraderProvider upgraderProvider, EventLogger eventLogger) - { - _recoverers = recoverers; - _name = name; - _upgraderProvider = upgraderProvider; - _eventLogger = eventLogger; - } - - @Override - public void beginConfigurationRecovery(final DurableConfigurationStore store) - { - _logSubject = new MessageStoreLogSubject(_name, store.getClass().getSimpleName()); - - _store = store; - _eventLogger.message(_logSubject, ConfigStoreMessages.RECOVERY_START()); - } - - @Override - public void configuredObject(ConfiguredObjectRecord record) - { - _records.add(record); - } - - @Override - public String completeConfigurationRecovery() - { - String configVersion = getConfigVersionFromRecords(); - - _upgrader = _upgraderProvider.getUpgrader(configVersion, this); - - for (ConfiguredObjectRecord record : _records) - { - // We don't yet recover the VirtualHost record. - if (!"VirtualHost".equals(record.getType())) - { - _upgrader.configuredObject(record); - } - } - _upgrader.complete(); - checkUnresolvedDependencies(); - applyUpgrade(); - - _eventLogger.message(_logSubject, ConfigStoreMessages.RECOVERY_COMPLETE()); - return BrokerModel.MODEL_VERSION; - } - - private String getConfigVersionFromRecords() - { - String configVersion = BrokerModel.MODEL_VERSION; - for (ConfiguredObjectRecord record : _records) - { - if ("VirtualHost".equals(record.getType())) - { - configVersion = (String) record.getAttributes().get("modelVersion"); - _logger.debug("Confifuration has config version : " + configVersion); - break; - } - } - return configVersion; - } - - void onConfiguredObject(ConfiguredObjectRecord record) - { - DurableConfiguredObjectRecoverer recoverer = getRecoverer(record.getType()); - if(recoverer == null) - { - throw new IllegalConfigurationException("Unknown type for configured object: " + record.getType()); - } - recoverer.load(this, record); - } - - - private DurableConfiguredObjectRecoverer getRecoverer(final String type) - { - DurableConfiguredObjectRecoverer recoverer = _recoverers.get(type); - return recoverer; - } - - private void applyUpgrade() - { - - 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()) - { - _store.update(true,updates.toArray(new ConfiguredObjectRecord[updates.size()])); - } - if(!deletes.isEmpty()) - { - _store.remove(deletes.toArray(new ConfiguredObjectRecord[deletes.size()])); - } - - } - - private void checkUnresolvedDependencies() - { - if(_unresolvedObjects != null && !_unresolvedObjects.isEmpty()) - { - boolean unresolvedObjectsExist = false; - for(Map.Entry<String, Map<UUID, UnresolvedObject>>entry : _unresolvedObjects.entrySet()) - { - for(Map.Entry<UUID,UnresolvedObject> obj : entry.getValue().entrySet()) - { - unresolvedObjectsExist = true; - StringBuilder errorMessage = new StringBuilder("Durable configured object of type "); - errorMessage.append(entry.getKey()).append(" with id ").append(obj.getKey()) - .append(" has unresolved dependencies: "); - for(UnresolvedDependency dep : obj.getValue().getUnresolvedDependencies()) - { - errorMessage.append(dep.getType()).append(" with id ").append(dep.getId()).append("; "); - } - _logger.error(errorMessage); - } - } - if(unresolvedObjectsExist) - { - throw new IllegalConfigurationException("Durable configuration has unresolved dependencies"); - } - } - } - - void addResolutionListener(final String type, - final UUID id, - final String name, - final DependencyListener dependencyListener) - { - if(id != null) - { - Map<UUID, List<DependencyListener>> typeListeners = _dependencyListeners.get(type); - if (typeListeners == null) - { - typeListeners = new HashMap<UUID, List<DependencyListener>>(); - _dependencyListeners.put(type, typeListeners); - } - List<DependencyListener> objectListeners = typeListeners.get(id); - if (objectListeners == null) - { - objectListeners = new ArrayList<DependencyListener>(); - typeListeners.put(id, objectListeners); - } - objectListeners.add(dependencyListener); - } - else - { - Map<String, List<DependencyListener>> typeListeners = _dependencyNameListeners.get(type); - if (typeListeners == null) - { - typeListeners = new HashMap<String, List<DependencyListener>>(); - _dependencyNameListeners.put(type, typeListeners); - } - List<DependencyListener> objectListeners = typeListeners.get(name); - if (objectListeners == null) - { - objectListeners = new ArrayList<DependencyListener>(); - typeListeners.put(name, objectListeners); - } - objectListeners.add(dependencyListener); - } - } - - Object getResolvedObject(final String type, final UUID id) - { - Map<UUID, ConfiguredObject> objects = _resolvedObjects.get(type); - return objects == null ? null : objects.get(id); - } - - Object getResolvedObject(final String type, final String name) - { - Map<UUID, ConfiguredObject> objects = _resolvedObjects.get(type); - if(objects != null) - { - for (ConfiguredObject object : objects.values()) - { - if(object.getName().equals(name)) - { - return object; - } - } - } - return null; - - } - - void resolve(final String type, final UUID id, final ConfiguredObject object) - { - Map<UUID, ConfiguredObject> typeObjects = _resolvedObjects.get(type); - if(typeObjects == null) - { - typeObjects = new HashMap<UUID, ConfiguredObject>(); - _resolvedObjects.put(type, typeObjects); - } - typeObjects.put(id, object); - Map<UUID, UnresolvedObject> unresolved = _unresolvedObjects.get(type); - if(unresolved != null) - { - unresolved.remove(id); - } - - Map<UUID, List<DependencyListener>> typeListeners = _dependencyListeners.get(type); - if(typeListeners != null) - { - List<DependencyListener> listeners = typeListeners.remove(id); - if(listeners != null) - { - for(DependencyListener listener : listeners) - { - listener.dependencyResolved(type, id, object); - } - } - } - - Map<String, List<DependencyListener>> typeNameListeners = _dependencyNameListeners.get(type); - if(typeNameListeners != null) - { - List<DependencyListener> listeners = typeNameListeners.remove(object.getName()); - if(listeners != null) - { - for(DependencyListener listener : listeners) - { - listener.dependencyResolved(type, id, object); - } - } - } - } - - void addUnresolvedObject(final String type, - final UUID id, - final UnresolvedObject obj) - { - Map<UUID, UnresolvedObject> typeObjects = _unresolvedObjects.get(type); - if(typeObjects == null) - { - typeObjects = new HashMap<UUID, UnresolvedObject>(); - _unresolvedObjects.put(type, typeObjects); - } - typeObjects.put(id, obj); - } - - -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java index 7d93f18906..7d1abb020e 100755 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java @@ -30,8 +30,6 @@ public interface DurableConfigurationStore { String STORE_TYPE = "storeType"; String STORE_PATH = "storePath"; - String IS_MESSAGE_STORE_TOO = "isMessageStoreToo"; - public static interface Source { diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java index 23ecc6f243..dcacb1ae7f 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java @@ -48,7 +48,6 @@ import org.codehaus.jackson.map.SerializationConfig; import org.codehaus.jackson.map.SerializerProvider; import org.codehaus.jackson.map.module.SimpleModule; -import org.apache.qpid.server.model.BrokerModel; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Model; import org.apache.qpid.server.model.VirtualHost; @@ -57,19 +56,19 @@ import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; public class JsonFileConfigStore implements DurableConfigurationStore { - private Map<String,Class<? extends ConfiguredObject>> _classNameMapping; public static final String TYPE = "JSON"; private final Map<UUID, ConfiguredObjectRecord> _objectsById = new HashMap<UUID, ConfiguredObjectRecord>(); private final Map<String, List<UUID>> _idsByType = new HashMap<String, List<UUID>>(); private final ObjectMapper _objectMapper = new ObjectMapper(); + private final Class<? extends ConfiguredObject> _rootClass; + private Map<String,Class<? extends ConfiguredObject>> _classNameMapping; private String _directoryName; private String _name; private FileLock _fileLock; private String _configFileName; private String _backupFileName; - private int _configVersion; private static final Module _module; static @@ -96,8 +95,14 @@ public class JsonFileConfigStore implements DurableConfigurationStore public JsonFileConfigStore() { + this(VirtualHost.class); + } + + public JsonFileConfigStore(Class<? extends ConfiguredObject> rootClass) + { _objectMapper.registerModule(_module); _objectMapper.enable(SerializationConfig.Feature.INDENT_OUTPUT); + _rootClass = rootClass; } @Override @@ -105,7 +110,7 @@ public class JsonFileConfigStore implements DurableConfigurationStore { _parent = parent; _name = parent.getName(); - _classNameMapping = generateClassNameMap(_parent.getModel(), VirtualHost.class); + _classNameMapping = generateClassNameMap(_parent.getModel(), _rootClass); setup(storeSettings); load(); } @@ -260,48 +265,26 @@ public class JsonFileConfigStore implements DurableConfigurationStore } - protected void loadFromMap(final Map data) + protected void loadFromMap(final Map<String,Object> data) { - Collection<Class<? extends ConfiguredObject>> childClasses = - _parent.getModel().getChildTypes(VirtualHost.class); - data.remove("modelVersion"); - Object configVersion; - if((configVersion = data.remove("configVersion")) instanceof Integer) + if (!data.isEmpty()) { - _configVersion = (Integer) configVersion; - } - for(Class<? extends ConfiguredObject> childClass : childClasses) - { - final String type = childClass.getSimpleName(); - String attrName = type.toLowerCase() + "s"; - Object children = data.remove(attrName); - if(children != null) - { - if(children instanceof Collection) - { - for(Object child : (Collection)children) - { - if(child instanceof Map) - { - loadChild(childClass, (Map)child, VirtualHost.class, null); - } - } - } - } + loadChild(_rootClass, data, null, null); } } + private void loadChild(final Class<? extends ConfiguredObject> clazz, final Map<String,Object> data, final Class<? extends ConfiguredObject> parentClass, final UUID parentId) { - Collection<Class<? extends ConfiguredObject>> childClasses = - _parent.getModel().getChildTypes(clazz); String idStr = (String) data.remove("id"); final UUID id = UUID.fromString(idStr); final String type = clazz.getSimpleName(); + Map<String,UUID> parentMap = new HashMap<String, UUID>(); + Collection<Class<? extends ConfiguredObject>> childClasses = _parent.getModel().getChildTypes(clazz); for(Class<? extends ConfiguredObject> childClass : childClasses) { final String childType = childClass.getSimpleName(); @@ -322,7 +305,6 @@ public class JsonFileConfigStore implements DurableConfigurationStore } } - Map<String,UUID> parentMap = new HashMap<String, UUID>(); if(parentId != null) { parentMap.put(parentClass.getSimpleName(),parentId); @@ -356,7 +338,6 @@ public class JsonFileConfigStore implements DurableConfigurationStore _idsByType.put(type, idsForType); } idsForType.add(id); - } @Override @@ -380,42 +361,38 @@ public class JsonFileConfigStore implements DurableConfigurationStore idsForType = new ArrayList<UUID>(); _idsByType.put(record.getType(), idsForType); } + + if (_rootClass.getSimpleName().equals(record.getType()) && idsForType.size() > 0) + { + throw new IllegalStateException("Only a single root entry of type " + _rootClass.getSimpleName() + " can exist in the store."); + } + idsForType.add(record.getId()); + save(); } } - private void save() + private UUID getRootId() { - Collection<Class<? extends ConfiguredObject>> childClasses = - _parent.getModel().getChildTypes(VirtualHost.class); - - Map<String, Object> virtualHostMap = new LinkedHashMap<String, Object>(); - virtualHostMap.put("modelVersion", BrokerModel.MODEL_VERSION); - virtualHostMap.put("configVersion", _configVersion); - - for(Class<? extends ConfiguredObject> childClass : childClasses) + List<UUID> ids = _idsByType.get(_rootClass.getSimpleName()); + if (ids == null) { - final String type = childClass.getSimpleName(); - String attrName = type.toLowerCase() + "s"; - List<UUID> childIds = _idsByType.get(type); - if(childIds != null && !childIds.isEmpty()) - { - List<Map<String,Object>> entities = new ArrayList<Map<String, Object>>(); - for(UUID id : childIds) - { - entities.add(build(childClass,id)); - } - virtualHostMap.put(attrName, entities); - } + throw new IllegalStateException("Root entry of type " + _rootClass.getSimpleName() + " does not exist in the store."); } + return ids.get(0); + } + + private void save() + { + UUID rootId = getRootId(); + Map<String, Object> data = build(_rootClass, rootId); try { - File tmpFile = File.createTempFile("cfg","tmp", new File(_directoryName)); tmpFile.deleteOnExit(); - _objectMapper.writeValue(tmpFile,virtualHostMap); + _objectMapper.writeValue(tmpFile,data); renameFile(_configFileName,_backupFileName); renameFile(tmpFile.getName(),_configFileName); tmpFile.delete(); @@ -489,6 +466,11 @@ public class JsonFileConfigStore implements DurableConfigurationStore @Override public synchronized UUID[] remove(final ConfiguredObjectRecord... objects) throws StoreException { + if (objects.length == 0) + { + return new UUID[0]; + } + List<UUID> removedIds = new ArrayList<UUID>(); for(ConfiguredObjectRecord requestedRecord : objects) { @@ -508,6 +490,11 @@ public class JsonFileConfigStore implements DurableConfigurationStore public void update(final boolean createIfNecessary, final ConfiguredObjectRecord... records) throws StoreException { + if (records.length == 0) + { + return; + } + for(ConfiguredObjectRecord record : records) { final UUID id = record.getId(); @@ -647,6 +634,15 @@ public class JsonFileConfigStore implements DurableConfigurationStore } return parents; } + + @Override + public String toString() + { + return "ConfiguredObjectRecordImpl [_id=" + _id + ", _type=" + _type + ", _attributes=" + _attributes + ", _parents=" + + _parents + "]"; + } + } + } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java index 83c8ec2a21..b69bd6f45f 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java @@ -40,12 +40,9 @@ public class JsonFileConfigStoreFactory implements DurableConfigurationStoreFact } @Override - public void validateAttributes(Map<String, Object> attributes) + public void validateConfigurationStoreSettings(Map<String, Object> attributes) { - @SuppressWarnings("unchecked") - Map<String, Object> configurationStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.CONFIGURATION_STORE_SETTINGS); - - Object storePath = configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); + Object storePath = attributes.get(DurableConfigurationStore.STORE_PATH); if(!(storePath instanceof String)) { throw new IllegalArgumentException("Setting '"+ DurableConfigurationStore.STORE_PATH @@ -53,4 +50,5 @@ public class JsonFileConfigStoreFactory implements DurableConfigurationStoreFact } } + } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java index 433f618d1a..4545aa9211 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/MessageStore.java @@ -67,6 +67,7 @@ public interface MessageStore String getStoreLocation(); + // TODO change to have separate delete methods for configuration and message store. void onDelete(); void visitMessages(MessageHandler handler) throws StoreException; diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java index b17dd4a6f3..ffa224d0f4 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/NullUpgrader.java @@ -26,17 +26,10 @@ import java.util.UUID; public final class NullUpgrader implements DurableConfigurationStoreUpgrader { - private DurableConfigurationRecoverer _durableConfigurationRecoverer; - - public NullUpgrader(final DurableConfigurationRecoverer durableConfigurationRecoverer) - { - _durableConfigurationRecoverer = durableConfigurationRecoverer; - } @Override public void configuredObject(final ConfiguredObjectRecord record) { - _durableConfigurationRecoverer.onConfiguredObject(record); } @Override diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java new file mode 100644 index 0000000000..226371a065 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/store/VirtualHostStoreUpgraderAndRecoverer.java @@ -0,0 +1,713 @@ +/* + * + * 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.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.startup.StoreUpgraderPhase; +import org.apache.qpid.server.configuration.startup.UpgraderPhaseFactory; +import org.apache.qpid.server.filter.FilterSupport; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.BrokerModel; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.ConfiguredObjectFactory; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.queue.QueueArgumentsConverter; +import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; +import org.apache.qpid.server.util.ServerScopedRuntimeException; + +public class VirtualHostStoreUpgraderAndRecoverer +{ + private final ConfiguredObjectFactory _objectFactory; + private final VirtualHostNode<?> _virtualHostNode; + private Map<String, UpgraderPhaseFactory> _upgraders = new HashMap<String, UpgraderPhaseFactory>(); + + @SuppressWarnings("serial") + private static final Map<String, String> DEFAULT_EXCHANGES = Collections.unmodifiableMap(new HashMap<String, String>() + {{ + put("amq.direct", "direct"); + put("amq.topic", "topic"); + put("amq.fanout", "fanout"); + put("amq.match", "headers"); + }}); + + private final Map<String, UUID> _defaultExchangeIds; + + public VirtualHostStoreUpgraderAndRecoverer(VirtualHostNode<?> virtualHostNode, ConfiguredObjectFactory objectFactory) + { + _virtualHostNode = virtualHostNode; + _objectFactory = objectFactory; + register(new UpgraderFactory_0_0()); + register(new UpgraderFactory_0_1()); + register(new UpgraderFactory_0_2()); + register(new UpgraderFactory_0_3()); + register(new UpgraderFactory_0_4()); + + Map<String, UUID> defaultExchangeIds = new HashMap<String, UUID>(); + for (String exchangeName : DEFAULT_EXCHANGES.keySet()) + { + UUID id = UUIDGenerator.generateExchangeUUID(exchangeName, virtualHostNode.getName()); + defaultExchangeIds.put(exchangeName, id); + } + _defaultExchangeIds = Collections.unmodifiableMap(defaultExchangeIds); + } + + private void register(UpgraderPhaseFactory factory) + { + _upgraders.put(factory.getFromVersion(), factory); + } + + /* + * Removes filters from queue bindings to exchanges other than topic exchanges. In older versions of the broker + * such bindings would have been ignored, starting from the point at which the config version changed, these + * arguments would actually cause selectors to be enforced, thus changing which messages would reach a queue. + */ + private class UpgraderFactory_0_0 extends UpgraderPhaseFactory + { + private final Map<UUID, ConfiguredObjectRecord> _records = new HashMap<UUID, ConfiguredObjectRecord>(); + + public UpgraderFactory_0_0() + { + super("0.0", "0.1"); + } + + + @Override + public StoreUpgraderPhase newInstance() + { + return new StoreUpgraderPhase("modelVersion", getToVersion()) + { + + @Override + public void configuredObject(final ConfiguredObjectRecord record) + { + _records.put(record.getId(), record); + } + + private void removeSelectorArguments(Map<String, Object> binding) + { + @SuppressWarnings("unchecked") + Map<String, Object> arguments = new LinkedHashMap<String, Object>((Map<String,Object>)binding.get(Binding.ARGUMENTS)); + + FilterSupport.removeFilters(arguments); + binding.put(Binding.ARGUMENTS, arguments); + } + + private boolean isTopicExchange(ConfiguredObjectRecord entry) + { + ConfiguredObjectRecord exchangeRecord = entry.getParents().get("Exchange"); + if (exchangeRecord == null) + { + return false; + } + UUID exchangeId = exchangeRecord.getId(); + + if(_records.containsKey(exchangeId)) + { + return "topic".equals(_records.get(exchangeId) + .getAttributes() + .get(org.apache.qpid.server.model.Exchange.TYPE)); + } + else + { + if (_defaultExchangeIds.get("amq.topic").equals(exchangeId)) + { + return true; + } + + return false; + } + + } + + private boolean hasSelectorArguments(Map<String, Object> binding) + { + @SuppressWarnings("unchecked") + Map<String, Object> arguments = (Map<String, Object>) binding.get(Binding.ARGUMENTS); + return (arguments != null) && FilterSupport.argumentsContainFilter(arguments); + } + + @Override + public void complete() + { + for(Map.Entry<UUID,ConfiguredObjectRecord> entry : _records.entrySet()) + { + ConfiguredObjectRecord record = entry.getValue(); + String type = record.getType(); + Map<String, Object> attributes = record.getAttributes(); + UUID id = record.getId(); + if ("org.apache.qpid.server.model.VirtualHost".equals(type)) + { + record = upgradeRootRecord(record); + } + else if(type.equals(Binding.class.getName()) && hasSelectorArguments(attributes) && !isTopicExchange(record)) + { + attributes = new LinkedHashMap<String, Object>(attributes); + removeSelectorArguments(attributes); + + record = new ConfiguredObjectRecordImpl(id, type, attributes, record.getParents()); + getUpdateMap().put(id, record); + entry.setValue(record); + + } + getNextUpgrader().configuredObject(record); + } + + getNextUpgrader().complete(); + } + }; + } + + } + + /* + * Change the type string from org.apache.qpid.server.model.Foo to Foo (in line with the practice in the broker + * configuration store). Also remove bindings which reference nonexistent queues or exchanges. + */ + private class UpgraderFactory_0_1 extends UpgraderPhaseFactory + { + protected UpgraderFactory_0_1() + { + super("0.1", "0.2"); + } + + @Override + public StoreUpgraderPhase newInstance() + { + return new StoreUpgraderPhase("modelVersion", getToVersion()) + { + + @Override + public void configuredObject(final ConfiguredObjectRecord record) + { + String type = record.getType().substring(1 + record.getType().lastIndexOf('.')); + ConfiguredObjectRecord newRecord = new ConfiguredObjectRecordImpl(record.getId(), type, record.getAttributes(), record.getParents()); + getUpdateMap().put(record.getId(), newRecord); + + if ("VirtualHost".equals(type)) + { + newRecord = upgradeRootRecord(newRecord); + } + } + + @Override + public void complete() + { + for (Iterator<Map.Entry<UUID, ConfiguredObjectRecord>> iterator = getUpdateMap().entrySet().iterator(); iterator.hasNext();) + { + Map.Entry<UUID, ConfiguredObjectRecord> entry = iterator.next(); + final ConfiguredObjectRecord record = entry.getValue(); + 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()); + iterator.remove(); + } + else + { + getNextUpgrader().configuredObject(record); + } + } + getNextUpgrader().complete(); + } + + private boolean unknownExchange(final UUID exchangeId) + { + if (_defaultExchangeIds.containsValue(exchangeId)) + { + return false; + } + ConfiguredObjectRecord localRecord = getUpdateMap().get(exchangeId); + return !(localRecord != null && localRecord.getType().equals(Exchange.class.getSimpleName())); + } + + private boolean unknownQueue(final UUID queueId) + { + ConfiguredObjectRecord localRecord = getUpdateMap().get(queueId); + return !(localRecord != null && localRecord.getType().equals(Queue.class.getSimpleName())); + } + + private boolean isBinding(final String type) + { + return Binding.class.getSimpleName().equals(type); + } + }; + } + } + + + /* + * Convert the storage of queue attributes to remove the separate "ARGUMENT" attribute, and flatten the + * attributes into the map using the model attribute names rather than the wire attribute names + */ + private class UpgraderFactory_0_2 extends UpgraderPhaseFactory + { + protected UpgraderFactory_0_2() + { + super("0.2", "0.3"); + } + + @Override + public StoreUpgraderPhase newInstance() + { + return new StoreUpgraderPhase("modelVersion", getToVersion()) + { + private static final String ARGUMENTS = "arguments"; + + @SuppressWarnings("unchecked") + @Override + public void configuredObject(ConfiguredObjectRecord record) + { + if("VirtualHost".equals(record.getType())) + { + record = upgradeRootRecord(record); + } + else if("Queue".equals(record.getType())) + { + Map<String, Object> newAttributes = new LinkedHashMap<String, Object>(); + if(record.getAttributes().get(ARGUMENTS) instanceof Map) + { + newAttributes.putAll(QueueArgumentsConverter.convertWireArgsToModel((Map<String, Object>) record.getAttributes() + .get(ARGUMENTS))); + } + newAttributes.putAll(record.getAttributes()); + + record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), newAttributes, record.getParents()); + getUpdateMap().put(record.getId(), record); + } + + getNextUpgrader().configuredObject(record); + } + + @Override + public void complete() + { + getNextUpgrader().complete(); + } + }; + } + } + + /* + * Convert the storage of queue attribute exclusive to change exclusive from a boolean to an enum + * where exclusive was false it will now be "NONE", and where true it will now be "CONTAINER" + * ensure OWNER is null unless the exclusivity policy is CONTAINER + */ + private class UpgraderFactory_0_3 extends UpgraderPhaseFactory + { + protected UpgraderFactory_0_3() + { + super("0.3", "0.4"); + } + + @Override + public StoreUpgraderPhase newInstance() + { + return new StoreUpgraderPhase("modelVersion", getToVersion()) + { + private static final String EXCLUSIVE = "exclusive"; + + @Override + public void configuredObject(ConfiguredObjectRecord record) + { + if("VirtualHost".equals(record.getType())) + { + record = upgradeRootRecord(record); + } + else if(Queue.class.getSimpleName().equals(record.getType())) + { + Map<String, Object> newAttributes = new LinkedHashMap<String, Object>(record.getAttributes()); + if(record.getAttributes().get(EXCLUSIVE) instanceof Boolean) + { + boolean isExclusive = (Boolean) record.getAttributes().get(EXCLUSIVE); + newAttributes.put(EXCLUSIVE, isExclusive ? "CONTAINER" : "NONE"); + if(!isExclusive && record.getAttributes().containsKey("owner")) + { + newAttributes.remove("owner"); + } + } + else + { + newAttributes.remove("owner"); + } + if(!record.getAttributes().containsKey("durable")) + { + newAttributes.put("durable","true"); + } + + record = new ConfiguredObjectRecordImpl(record.getId(),record.getType(),newAttributes, record.getParents()); + getUpdateMap().put(record.getId(), record); + } + + getNextUpgrader().configuredObject(record); + } + + @Override + public void complete() + { + getNextUpgrader().complete(); + } + }; + } + } + + private class UpgraderFactory_0_4 extends UpgraderPhaseFactory + { + protected UpgraderFactory_0_4() + { + super("0.4", "2.0"); + } + + @Override + public StoreUpgraderPhase newInstance() + { + return new StoreUpgraderPhase("modelVersion", getToVersion()) + { + private Map<String, String> _missingAmqpExchanges = new HashMap<String, String>(DEFAULT_EXCHANGES); + private static final String EXCHANGE_NAME = "name"; + private static final String EXCHANGE_TYPE = "type"; + private static final String EXCHANGE_DURABLE = "durable"; + private ConfiguredObjectRecord _virtualHostRecord; + + @Override + public void configuredObject(ConfiguredObjectRecord record) + { + if("VirtualHost".equals(record.getType())) + { + record = upgradeRootRecord(record); + Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(record.getAttributes()); + virtualHostAttributes.put("name", _virtualHostNode.getName()); + virtualHostAttributes.put("modelVersion", getToVersion()); + record = new ConfiguredObjectRecordImpl(record.getId(), "VirtualHost", virtualHostAttributes, Collections.<String, ConfiguredObjectRecord>emptyMap()); + _virtualHostRecord = record; + } + else if("Exchange".equals(record.getType())) + { + Map<String, Object> attributes = record.getAttributes(); + String name = (String)attributes.get(EXCHANGE_NAME); + _missingAmqpExchanges.remove(name); + } + getNextUpgrader().configuredObject(record); + } + + @Override + public void complete() + { + for (Entry<String, String> entry : _missingAmqpExchanges.entrySet()) + { + String name = entry.getKey(); + String type = entry.getValue(); + UUID id = _defaultExchangeIds.get(name); + + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(EXCHANGE_NAME, name); + attributes.put(EXCHANGE_TYPE, type); + attributes.put(EXCHANGE_DURABLE, true); + + ConfiguredObjectRecord record = new ConfiguredObjectRecordImpl(id, Exchange.class.getSimpleName(), attributes, Collections.singletonMap(_virtualHostRecord.getType(), _virtualHostRecord)); + getUpdateMap().put(id, record); + + getNextUpgrader().configuredObject(record); + + } + + getNextUpgrader().complete(); + } + }; + } + + } + + public void perform(DurableConfigurationStore durableConfigurationStore) + { + UpgradeAndRecoveryHandler vhrh = new UpgradeAndRecoveryHandler(_virtualHostNode, _objectFactory, durableConfigurationStore, _upgraders); + durableConfigurationStore.visitConfiguredObjectRecords(vhrh); + } + + //TODO: generalize this class + private static class UpgradeAndRecoveryHandler implements ConfiguredObjectRecordHandler + { + private static Logger LOGGER = Logger.getLogger(UpgradeAndRecoveryHandler.class); + + private final Map<UUID, ConfiguredObjectRecord> _records = new LinkedHashMap<UUID, ConfiguredObjectRecord>(); + private Map<String, UpgraderPhaseFactory> _upgraders; + + private final VirtualHostNode<?> _parent; + private final ConfiguredObjectFactory _configuredObjectFactory; + private final DurableConfigurationStore _store; + + public UpgradeAndRecoveryHandler(VirtualHostNode<?> parent, ConfiguredObjectFactory configuredObjectFactory, DurableConfigurationStore durableConfigurationStore, Map<String, UpgraderPhaseFactory> upgraders) + { + super(); + _parent = parent; + _configuredObjectFactory = configuredObjectFactory; + _upgraders = upgraders; + _store = durableConfigurationStore; + } + + @Override + public void begin() + { + } + + @Override + public boolean handle(final ConfiguredObjectRecord record) + { + _records.put(record.getId(), record); + return true; + } + + @Override + public void end() + { + String version = getCurrentVersion(); + + if (LOGGER.isInfoEnabled()) + { + LOGGER.info("Store has model version " + version + ". Number of record(s) " + _records.size()); + } + + DurableConfigurationStoreUpgrader upgrader = buildUpgraderChain(version); + + for(ConfiguredObjectRecord record : _records.values()) + { + upgrader.configuredObject(record); + } + + upgrader.complete(); + + Map<UUID, ConfiguredObjectRecord> deletedRecords = upgrader.getDeletedRecords(); + Map<UUID, ConfiguredObjectRecord> updatedRecords = upgrader.getUpdatedRecords(); + + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("VirtualHost store upgrade: " + deletedRecords.size() + " record(s) deleted"); + LOGGER.debug("VirtualHost store upgrade: " + updatedRecords.size() + " record(s) updated"); + LOGGER.debug("VirtualHost store upgrade: " + _records.size() + " total record(s)"); + } + + _store.update(true, updatedRecords.values().toArray(new ConfiguredObjectRecord[updatedRecords.size()])); + _store.remove(deletedRecords.values().toArray(new ConfiguredObjectRecord[deletedRecords.size()])); + + _records.keySet().removeAll(deletedRecords.keySet()); + _records.putAll(updatedRecords); + + ConfiguredObjectRecord virtualHostRecord = null; + for (ConfiguredObjectRecord record : _records.values()) + { + LOGGER.debug("Found type " + record.getType()); + if ("VirtualHost".equals(record.getType())) + { + virtualHostRecord = record; + break; + } + } + + if (virtualHostRecord != null) + { + String parentCategory = _parent.getCategoryClass().getSimpleName(); + ConfiguredObjectRecord parentRecord = new ConfiguredObjectRecordImpl(_parent.getId(), parentCategory, Collections.<String, Object>emptyMap()); + Map<String, ConfiguredObjectRecord> rootParents = Collections.<String, ConfiguredObjectRecord>singletonMap(parentCategory, parentRecord); + _records.put(virtualHostRecord.getId(), new ConfiguredObjectRecordImpl(virtualHostRecord.getId(), VirtualHost.class.getSimpleName(), virtualHostRecord.getAttributes(), rootParents)); + Collection<ConfiguredObjectRecord> records = _records.values(); + resolveObjects(_configuredObjectFactory, _parent, records.toArray(new ConfiguredObjectRecord[records.size()])); + } + } + + private DurableConfigurationStoreUpgrader buildUpgraderChain(String version) + { + DurableConfigurationStoreUpgrader head = null; + while(!BrokerModel.MODEL_VERSION.equals(version)) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Adding virtual host store upgrader from model version: " + version); + } + final UpgraderPhaseFactory upgraderPhaseFactory = _upgraders.get(version); + StoreUpgraderPhase upgrader = upgraderPhaseFactory.newInstance(); + if(head == null) + { + head = upgrader; + } + else + { + head.setNextUpgrader(upgrader); + } + version = upgraderPhaseFactory.getToVersion(); + } + + if(head == null) + { + head = new NullUpgrader(); + } + else + { + head.setNextUpgrader(new NullUpgrader()); + } + + return head; + } + + private String getCurrentVersion() + { + for(ConfiguredObjectRecord record : _records.values()) + { + if(record.getType().equals("VirtualHost")) + { + return (String) record.getAttributes().get(VirtualHost.MODEL_VERSION); + } + } + return BrokerModel.MODEL_VERSION; + } + + + public void resolveObjects(ConfiguredObjectFactory factory, ConfiguredObject<?> root, ConfiguredObjectRecord... records) + { + Map<UUID, ConfiguredObject<?>> resolvedObjects = new HashMap<UUID, ConfiguredObject<?>>(); + resolvedObjects.put(root.getId(), root); + + Collection<ConfiguredObjectRecord> recordsWithUnresolvedParents = new ArrayList<ConfiguredObjectRecord>(Arrays.asList(records)); + Collection<UnresolvedConfiguredObject<? extends ConfiguredObject>> recordsWithUnresolvedDependencies = + new ArrayList<UnresolvedConfiguredObject<? extends ConfiguredObject>>(); + + boolean updatesMade; + + do + { + updatesMade = false; + Iterator<ConfiguredObjectRecord> iter = recordsWithUnresolvedParents.iterator(); + while (iter.hasNext()) + { + ConfiguredObjectRecord record = iter.next(); + Collection<ConfiguredObject<?>> parents = new ArrayList<ConfiguredObject<?>>(); + boolean foundParents = true; + for (ConfiguredObjectRecord parent : record.getParents().values()) + { + if (!resolvedObjects.containsKey(parent.getId())) + { + foundParents = false; + break; + } + else + { + parents.add(resolvedObjects.get(parent.getId())); + } + } + if (foundParents) + { + iter.remove(); + UnresolvedConfiguredObject<? extends ConfiguredObject> recovered = + factory.recover(record, parents.toArray(new ConfiguredObject<?>[parents.size()])); + Collection<ConfiguredObjectDependency<?>> dependencies = + recovered.getUnresolvedDependencies(); + if (dependencies.isEmpty()) + { + updatesMade = true; + ConfiguredObject<?> resolved = recovered.resolve(); + resolvedObjects.put(resolved.getId(), resolved); + } + else + { + recordsWithUnresolvedDependencies.add(recovered); + } + } + + } + + Iterator<UnresolvedConfiguredObject<? extends ConfiguredObject>> unresolvedIter = + recordsWithUnresolvedDependencies.iterator(); + + while(unresolvedIter.hasNext()) + { + UnresolvedConfiguredObject<? extends ConfiguredObject> unresolvedObject = unresolvedIter.next(); + Collection<ConfiguredObjectDependency<?>> dependencies = + new ArrayList<ConfiguredObjectDependency<?>>(unresolvedObject.getUnresolvedDependencies()); + + for(ConfiguredObjectDependency dependency : dependencies) + { + if(dependency instanceof ConfiguredObjectIdDependency) + { + UUID id = ((ConfiguredObjectIdDependency)dependency).getId(); + if(resolvedObjects.containsKey(id)) + { + dependency.resolve(resolvedObjects.get(id)); + } + } + else if(dependency instanceof ConfiguredObjectNameDependency) + { + ConfiguredObject<?> dependentObject = null; + for(ConfiguredObject<?> parent : unresolvedObject.getParents()) + { + dependentObject = parent.findConfiguredObject(dependency.getCategoryClass(), ((ConfiguredObjectNameDependency)dependency).getName()); + if(dependentObject != null) + { + break; + } + } + if(dependentObject != null) + { + dependency.resolve(dependentObject); + } + } + else + { + throw new ServerScopedRuntimeException("Unknown dependency type " + dependency.getClass().getSimpleName()); + } + } + if(unresolvedObject.getUnresolvedDependencies().isEmpty()) + { + updatesMade = true; + unresolvedIter.remove(); + ConfiguredObject<?> resolved = unresolvedObject.resolve(); + resolvedObjects.put(resolved.getId(), resolved); + } + } + + } while(updatesMade && !(recordsWithUnresolvedDependencies.isEmpty() && recordsWithUnresolvedParents.isEmpty())); + + if(!recordsWithUnresolvedDependencies.isEmpty()) + { + throw new IllegalArgumentException("Cannot resolve some objects: " + recordsWithUnresolvedDependencies); + } + if(!recordsWithUnresolvedParents.isEmpty()) + { + throw new IllegalArgumentException("Cannot resolve object because their parents cannot be found" + recordsWithUnresolvedParents); + } + } + + } +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java index 645c6061bd..18f728fdf6 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java @@ -41,7 +41,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import javax.security.auth.Subject; import org.apache.log4j.Logger; - import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; @@ -51,7 +50,6 @@ import org.apache.qpid.server.exchange.AMQUnknownExchangeType; import org.apache.qpid.server.exchange.DefaultDestination; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.logging.messages.ConfigStoreMessages; import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.logging.messages.VirtualHostMessages; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; @@ -60,9 +58,27 @@ import org.apache.qpid.server.message.MessageInstance; import org.apache.qpid.server.message.MessageNode; import org.apache.qpid.server.message.MessageSource; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.model.*; +import org.apache.qpid.server.model.AbstractConfiguredObject; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.BrokerModel; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.IntegrityViolationException; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.SystemContext; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.model.adapter.ConnectionAdapter; import org.apache.qpid.server.model.adapter.VirtualHostAliasAdapter; +import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.plugin.SystemNodeCreator; import org.apache.qpid.server.protocol.AMQConnectionModel; @@ -74,7 +90,6 @@ import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.DurableConfiguredObjectRecoverer; import org.apache.qpid.server.store.Event; import org.apache.qpid.server.store.EventListener; import org.apache.qpid.server.store.MessageStore; @@ -131,14 +146,12 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte private final List<VirtualHostAlias> _aliases = new ArrayList<VirtualHostAlias>(); private final AtomicBoolean _deleted = new AtomicBoolean(); + private final VirtualHostNode<?> _virtualHostNode; @ManagedAttributeField private Map<String, Object> _messageStoreSettings; @ManagedAttributeField - private Map<String, Object> _configurationStoreSettings; - - @ManagedAttributeField private boolean _queue_deadLetterQueueEnabled; @ManagedAttributeField @@ -163,12 +176,13 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte private String _securityAcl; private MessageDestination _defaultDestination; - - public AbstractVirtualHost(final Map<String, Object> attributes, Broker<?> broker) + public AbstractVirtualHost(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode) { - super(parentsMap(broker), - enhanceWithId(attributes), broker.getTaskExecutor()); - _broker = broker; + super(Collections.<Class<? extends ConfiguredObject>,ConfiguredObject<?>>singletonMap(VirtualHostNode.class, virtualHostNode), + enhanceWithId(attributes), ((Broker<?>)virtualHostNode.getParent(Broker.class)).getTaskExecutor()); + _broker = virtualHostNode.getParent(Broker.class); + _virtualHostNode = virtualHostNode; + _dtxRegistry = new DtxRegistry(); _eventLogger = _broker.getParent(SystemContext.class).getEventLogger(); @@ -209,6 +223,41 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte { throw new IllegalArgumentException(getClass().getSimpleName() + " must be durable"); } + + DurableConfigurationStore durableConfigurationStore = _virtualHostNode.getConfigurationStore(); + + boolean nodeIsMessageStoreProvider = _virtualHostNode.isMessageStoreProvider(); + if (nodeIsMessageStoreProvider) + { + if (!(durableConfigurationStore instanceof MessageStore)) + { + throw new IllegalConfigurationException("Virtual host node " + _virtualHostNode.getName() + + " is configured as a provider of message store but the MessageStore interface is not implemented on a configuration store of type " + + durableConfigurationStore.getClass().getName()); + } + } + else + { + Map<String, Object> messageStoreSettings = getMessageStoreSettings(); + if (messageStoreSettings == null) + { + throw new IllegalConfigurationException("Message store settings are missed for VirtualHost " + getName() + + ". You can either configure the message store setting on the host or " + + (durableConfigurationStore instanceof MessageStore ? + " configure VirtualHostNode " + _virtualHostNode.getName() + " as a provider of message store" : + " change the node type to one having configuration store implementing the MessageStore inteface") ); + } + String storeType = (String) messageStoreSettings.get(MessageStore.STORE_TYPE); + if (storeType == null) + { + throw new IllegalConfigurationException("Message store type setting is not set"); + } + MessageStoreFactory factory = MessageStoreFactory.FACTORY_LOADER.get(storeType); + if (factory == null) + { + throw new IllegalConfigurationException("Message store factory is not found for type " + storeType + " for VirtualHost " + getName()); + } + } } @Override @@ -224,18 +273,17 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte protected void onOpen() { super.onOpen(); - _houseKeepingTasks = new ScheduledThreadPoolExecutor(getHousekeepingThreadCount()); registerSystemNodes(); initialiseStatistics(); - Subject.doAs(getSecurityManager().getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>() + Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>() { @Override public Object run() { - initialiseStorage(AbstractVirtualHost.this); + initialiseStorage(); return null; } }); @@ -280,7 +328,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte } } - abstract protected void initialiseStorage(org.apache.qpid.server.model.VirtualHost<?,?,?> virtualHost); + abstract protected void initialiseStorage(); protected boolean isStoreEmpty() { @@ -547,7 +595,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte return _houseKeepingTasks.getActiveCount(); } - public long getCreateTime() { return _createTime; @@ -620,8 +667,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte private AMQQueue<?> addQueueWithoutDLQ(Map<String, Object> attributes) throws QueueExistsException { - - try { return (AMQQueue) getObjectFactory().create(Queue.class, attributes, this); @@ -779,8 +824,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte throws ExchangeExistsException, ReservedExchangeNameException, UnknownExchangeException, AMQUnknownExchangeType { - - try { return (ExchangeImpl) getObjectFactory().create(Exchange.class, attributes, this); @@ -815,6 +858,9 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte _state = VirtualHostState.STOPPED; _eventLogger.message(VirtualHostMessages.CLOSED(getName())); + + // TODO: The state work will replace this with closure of the virtualhost, rather than deleting it. + deleted(); } private void closeStorage() @@ -830,28 +876,11 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte _logger.error("Failed to close message store", e); } } - if (getDurableConfigurationStore() != null) + + if (!_virtualHostNode.isMessageStoreProvider()) { - try - { - getDurableConfigurationStore().closeConfigurationStore(); - MessageStoreLogSubject configurationStoreSubject = getConfigurationStoreLogSubject(); - if (configurationStoreSubject != null) - { - getEventLogger().message(configurationStoreSubject, ConfigStoreMessages.CLOSE()); - } - } - catch (StoreException e) - { - _logger.error("Failed to close configuration store", e); - } + getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CLOSED()); } - getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CLOSED()); - } - - protected MessageStoreLogSubject getConfigurationStoreLogSubject() - { - return null; } public void registerMessageDelivered(long messageSize) @@ -925,11 +954,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte return _dtxRegistry; } - public String toString() - { - return getName(); - } - public VirtualHostState getVirtualHostState() { return _state; @@ -1029,22 +1053,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte _state = state; } - protected void attainActivation() - { - VirtualHostState finalState = VirtualHostState.ERRORED; - - try - { - initialiseHouseKeeping(getHousekeepingCheckPeriod()); - finalState = VirtualHostState.ACTIVE; - } - finally - { - _state = finalState; - reportIfError(_state); - } - } - protected void reportIfError(VirtualHostState state) { if (state == VirtualHostState.ERRORED) @@ -1053,22 +1061,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte } } - protected Map<String, DurableConfiguredObjectRecoverer> getDurableConfigurationRecoverers() - { - DurableConfiguredObjectRecoverer[] recoverers = { - new QueueRecoverer(this), - new ExchangeRecoverer(this), - new BindingRecoverer(this) - }; - - final Map<String, DurableConfiguredObjectRecoverer> recovererMap= new HashMap<String, DurableConfiguredObjectRecoverer>(); - for(DurableConfiguredObjectRecoverer recoverer : recoverers) - { - recovererMap.put(recoverer.getType(), recoverer); - } - return recovererMap; - } - private static class IsStoreEmptyHandler implements ConfiguredObjectRecordHandler { private boolean _empty = true; @@ -1349,20 +1341,12 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte return _storeTransactionOpenTimeoutWarn; } - @SuppressWarnings("unchecked") @Override public Map<String, Object> getMessageStoreSettings() { return _messageStoreSettings; } - @SuppressWarnings("unchecked") - @Override - public Map<String, Object> getConfigurationStoreSettings() - { - return _configurationStoreSettings; - } - @Override public long getQueueCount() { @@ -1424,6 +1408,7 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte { if (desiredState == State.ACTIVE) { + activate(); return true; } else if (desiredState == State.STOPPED) @@ -1473,7 +1458,6 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte return Collections.unmodifiableCollection(_aliases); } - private String createDLQ(final String queueName) { final String dlExchangeName = getDeadLetterExchangeName(queueName); @@ -1609,5 +1593,63 @@ public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> exte return name + System.getProperty(BrokerProperties.PROPERTY_DEAD_LETTER_EXCHANGE_SUFFIX, VirtualHostImpl.DEFAULT_DLE_NAME_SUFFIX); } + @Override + public String getModelVersion() + { + return BrokerModel.MODEL_VERSION; + } + + @Override + public DurableConfigurationStore getDurableConfigurationStore() + { + return _virtualHostNode.getConfigurationStore(); + } + + @Override + protected void onCreate() + { + super.onCreate(); + getDurableConfigurationStore().create(asObjectRecord()); + } + + protected void activate() + { + _houseKeepingTasks = new ScheduledThreadPoolExecutor(getHousekeepingThreadCount()); + + boolean nodeIsMessageStoreProvider = _virtualHostNode.isMessageStoreProvider(); + + MessageStore messageStore = getMessageStore(); + Map<String, Object> messageStoreSettings = getMessageStoreSettings(); + if (messageStoreSettings == null) + { + messageStoreSettings = Collections.emptyMap(); + } + messageStore.openMessageStore(this, messageStoreSettings); + + if (!nodeIsMessageStoreProvider) + { + getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.CREATED()); + getEventLogger().message(getMessageStoreLogSubject(), MessageStoreMessages.STORE_LOCATION(messageStore.getStoreLocation())); + } + + if (isStoreEmpty()) + { + createDefaultExchanges(); + } + + new MessageStoreRecoverer(this, getMessageStoreLogSubject()).recover(); + + VirtualHostState finalState = VirtualHostState.ERRORED; + try + { + initialiseHouseKeeping(getHousekeepingCheckPeriod()); + finalState = VirtualHostState.ACTIVE; + } + finally + { + _state = finalState; + reportIfError(_state); + } + } } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java deleted file mode 100644 index 8aeff7f847..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.binding.BindingImpl; -import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObjectFactory; -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.UnresolvedConfiguredObject; -import org.apache.qpid.server.store.UnresolvedDependency; -import org.apache.qpid.server.store.UnresolvedObject; - -public class BindingRecoverer extends AbstractDurableConfiguredObjectRecoverer<BindingImpl> -{ - private static final Logger _logger = Logger.getLogger(BindingRecoverer.class); - - private final VirtualHostImpl<?,?,?> _virtualHost; - private final ConfiguredObjectFactory _objectFactory; - - public BindingRecoverer(final VirtualHostImpl<?,?,?> virtualHost) - { - _virtualHost = virtualHost; - Broker<?> broker = _virtualHost.getParent(Broker.class); - _objectFactory = broker.getObjectFactory(); - } - - @Override - public UnresolvedObject<BindingImpl> createUnresolvedObject(ConfiguredObjectRecord record) - { - return new UnresolvedBinding(record); - } - - @Override - public String getType() - { - return org.apache.qpid.server.model.Binding.class.getSimpleName(); - } - - private class UnresolvedBinding implements UnresolvedObject<BindingImpl> - { - private final Map<String, Object> _bindingArgumentsMap; - private final String _bindingName; - private final UUID _queueId; - private final UUID _exchangeId; - private final UUID _bindingId; - private final ConfiguredObjectRecord _record; - - private List<UnresolvedDependency> _unresolvedDependencies = - new ArrayList<UnresolvedDependency>(); - - private ExchangeImpl _exchange; - private AMQQueue _queue; - - public UnresolvedBinding(final ConfiguredObjectRecord record) - { - _record = record; - _bindingId = record.getId(); - _exchangeId = record.getParents().get(Exchange.class.getSimpleName()).getId(); - _queueId = record.getParents().get(Queue.class.getSimpleName()).getId(); - _exchange = _virtualHost.getExchange(_exchangeId); - if(_exchange == null) - { - _unresolvedDependencies.add(new ExchangeDependency()); - } - _queue = _virtualHost.getQueue(_queueId); - if(_queue == null) - { - _unresolvedDependencies.add(new QueueDependency()); - } - - - _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 - public UnresolvedDependency[] getUnresolvedDependencies() - { - return _unresolvedDependencies.toArray(new UnresolvedDependency[_unresolvedDependencies.size()]); - } - - @Override - public BindingImpl resolve() - { - if(!_exchange.hasBinding(_bindingName, _queue)) - { - _logger.info("Restoring binding: (Exchange: " + _exchange.getName() + ", Queue: " + _queue.getName() - + ", Routing Key: " + _bindingName + ", Arguments: " + _bindingArgumentsMap + ")"); - - - Map<String,Object> attributesWithId = new HashMap<String,Object>(_record.getAttributes()); - attributesWithId.put(org.apache.qpid.server.model.Exchange.ID,_record.getId()); - attributesWithId.put(org.apache.qpid.server.model.Exchange.DURABLE,true); - - UnresolvedConfiguredObject<? extends Binding> unresolvedConfiguredObject = - _objectFactory.recover(_record, _exchange, _queue); - Binding binding = (Binding<?>) unresolvedConfiguredObject.resolve(); - binding.open(); - - } - return (_exchange).getBinding(_bindingName, _queue); - } - - private class QueueDependency implements UnresolvedDependency<AMQQueue> - { - - @Override - public UUID getId() - { - return _queueId; - } - - @Override - public String getName() - { - return null; - } - - @Override - public String getType() - { - return Queue.class.getSimpleName(); - } - - @Override - public void resolve(final AMQQueue dependency) - { - _queue = dependency; - _unresolvedDependencies.remove(this); - } - - } - - private class ExchangeDependency implements UnresolvedDependency<ExchangeImpl> - { - - @Override - public UUID getId() - { - return _exchangeId; - } - - @Override - public String getName() - { - return null; - } - - @Override - public String getType() - { - return org.apache.qpid.server.model.Exchange.class.getSimpleName(); - } - - @Override - public void resolve(final ExchangeImpl dependency) - { - _exchange = dependency; - _unresolvedDependencies.remove(this); - } - } - } -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java deleted file mode 100644 index 956d44a27e..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java +++ /dev/null @@ -1,413 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost; - -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.UUID; - -import org.apache.log4j.Logger; -import org.apache.qpid.server.exchange.TopicExchange; -import org.apache.qpid.server.filter.FilterSupport; -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.Exchange; -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; -import org.apache.qpid.server.store.NullUpgrader; -import org.apache.qpid.server.store.UpgraderProvider; - -public class DefaultUpgraderProvider implements UpgraderProvider -{ - private static final Logger LOGGER = Logger.getLogger(DefaultUpgraderProvider.class); - - public static final String EXCLUSIVE = "exclusive"; - public static final String NAME = "name"; - private final VirtualHostImpl _virtualHost; - - @SuppressWarnings("serial") - private static final Map<String, String> DEFAULT_EXCHANGES = Collections.unmodifiableMap(new HashMap<String, String>() - {{ - put("amq.direct", "direct"); - put("amq.topic", "topic"); - put("amq.fanout", "fanout"); - put("amq.match", "headers"); - }}); - - private final Map<String, UUID> _defaultExchangeIds; - - public DefaultUpgraderProvider(final VirtualHostImpl virtualHost) - { - _virtualHost = virtualHost; - Map<String, UUID> defaultExchangeIds = new HashMap<String, UUID>(); - for (String exchangeName : DEFAULT_EXCHANGES.keySet()) - { - UUID id = UUIDGenerator.generateExchangeUUID(exchangeName, _virtualHost.getName()); - defaultExchangeIds.put(exchangeName, id); - } - _defaultExchangeIds = Collections.unmodifiableMap(defaultExchangeIds); - } - - public DurableConfigurationStoreUpgrader getUpgrader(final String configVersion, DurableConfigurationRecoverer recoverer) - { - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Getting upgrader for configVersion: " + configVersion); - } - DurableConfigurationStoreUpgrader currentUpgrader = null; - - int conigVersionAsInteger = Integer.parseInt(configVersion.replace(".", "")); - switch(conigVersionAsInteger) - { - case 0: - currentUpgrader = addUpgrader(currentUpgrader, new Version0Upgrader()); - case 1: - currentUpgrader = addUpgrader(currentUpgrader, new Version1Upgrader()); - case 2: - currentUpgrader = addUpgrader(currentUpgrader, new Version2Upgrader()); - case 3: - currentUpgrader = addUpgrader(currentUpgrader, new Version3Upgrader()); - case 4: - currentUpgrader = addUpgrader(currentUpgrader, new Version4Upgrader()); - case (BrokerModel.MODEL_MAJOR_VERSION * 10) + BrokerModel.MODEL_MINOR_VERSION: - currentUpgrader = addUpgrader(currentUpgrader, new NullUpgrader(recoverer)); - break; - - default: - throw new IllegalStateException("Unknown configuration model version: " + configVersion - + ". Attempting to run an older instance against an upgraded configuration?"); - } - return currentUpgrader; - } - - private DurableConfigurationStoreUpgrader addUpgrader(DurableConfigurationStoreUpgrader currentUpgrader, - final DurableConfigurationStoreUpgrader nextUpgrader) - { - if(currentUpgrader == null) - { - currentUpgrader = nextUpgrader; - } - else - { - currentUpgrader.setNextUpgrader(nextUpgrader); - } - return currentUpgrader; - } - - /* - * Removes filters from queue bindings to exchanges other than topic exchanges. In older versions of the broker - * such bindings would have been ignored, starting from the point at which the config version changed, these - * arguments would actually cause selectors to be enforced, thus changing which messages would reach a queue. - */ - private class Version0Upgrader extends NonNullUpgrader - { - private final Map<UUID, ConfiguredObjectRecord> _records = new HashMap<UUID, ConfiguredObjectRecord>(); - - public Version0Upgrader() - { - } - - @Override - public void configuredObject(final ConfiguredObjectRecord record) - { - _records.put(record.getId(), record); - } - - private void removeSelectorArguments(Map<String, Object> binding) - { - @SuppressWarnings("unchecked") - Map<String, Object> arguments = new LinkedHashMap<String, Object>((Map<String,Object>)binding.get(Binding.ARGUMENTS)); - - FilterSupport.removeFilters(arguments); - binding.put(Binding.ARGUMENTS, arguments); - } - - private boolean isTopicExchange(ConfiguredObjectRecord entry) - { - ConfiguredObjectRecord exchangeRecord = entry.getParents().get("Exchange"); - if (exchangeRecord == null) - { - return false; - } - UUID exchangeId = exchangeRecord.getId(); - - if(_records.containsKey(exchangeId)) - { - return "topic".equals(_records.get(exchangeId) - .getAttributes() - .get(org.apache.qpid.server.model.Exchange.TYPE)); - } - else - { - if (_defaultExchangeIds.get("amq.topic").equals(exchangeId)) - { - return true; - } - - return _virtualHost.getExchange(exchangeId) != null - && _virtualHost.getExchange(exchangeId).getExchangeType() == TopicExchange.TYPE; - } - - } - - private boolean hasSelectorArguments(Map<String, Object> binding) - { - @SuppressWarnings("unchecked") - Map<String, Object> arguments = (Map<String, Object>) binding.get(Binding.ARGUMENTS); - return (arguments != null) && FilterSupport.argumentsContainFilter(arguments); - } - - - - @Override - public void complete() - { - for(Map.Entry<UUID,ConfiguredObjectRecord> entry : _records.entrySet()) - { - ConfiguredObjectRecord record = entry.getValue(); - String type = record.getType(); - Map<String, Object> attributes = record.getAttributes(); - UUID id = record.getId(); - if(type.equals(Binding.class.getName()) && hasSelectorArguments(attributes) && !isTopicExchange(record)) - { - attributes = new LinkedHashMap<String, Object>(attributes); - removeSelectorArguments(attributes); - - record = new ConfiguredObjectRecordImpl(id, type, attributes, record.getParents()); - getUpdateMap().put(id, record); - entry.setValue(record); - - } - getNextUpgrader().configuredObject(record); - } - - getNextUpgrader().complete(); - } - - } - - /* - * Change the type string from org.apache.qpid.server.model.Foo to Foo (in line with the practice in the broker - * configuration store). Also remove bindings which reference nonexistent queues or exchanges. - */ - private class Version1Upgrader extends NonNullUpgrader - { - - - @Override - public void configuredObject(final ConfiguredObjectRecord record) - { - String type = record.getType().substring(1 + record.getType().lastIndexOf('.')); - getUpdateMap().put(record.getId(), - new ConfiguredObjectRecordImpl(record.getId(), type, record.getAttributes(), record.getParents())); - } - - @Override - public void complete() - { - for(Map.Entry<UUID, ConfiguredObjectRecord> entry : getUpdateMap().entrySet()) - { - final ConfiguredObjectRecord record = entry.getValue(); - 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); - } - } - getNextUpgrader().complete(); - } - - private boolean unknownExchange(final UUID exchangeId) - { - if (_defaultExchangeIds.containsValue(exchangeId)) - { - return false; - } - ConfiguredObjectRecord localRecord = getUpdateMap().get(exchangeId); - return !((localRecord != null && localRecord.getType().equals(Exchange.class.getSimpleName())) - || _virtualHost.getExchange(exchangeId) != null); - } - - private boolean unknownQueue(final UUID queueId) - { - ConfiguredObjectRecord localRecord = getUpdateMap().get(queueId); - return !((localRecord != null && localRecord.getType().equals(Queue.class.getSimpleName())) - || _virtualHost.getQueue(queueId) != null); - } - - private boolean isBinding(final String type) - { - return Binding.class.getSimpleName().equals(type); - } - - - } - - /* - * Convert the storage of queue attributes to remove the separate "ARGUMENT" attribute, and flatten the - * attributes into the map using the model attribute names rather than the wire attribute names - */ - private class Version2Upgrader extends NonNullUpgrader - { - - private static final String ARGUMENTS = "arguments"; - - @Override - public void configuredObject(ConfiguredObjectRecord record) - { - - if(Queue.class.getSimpleName().equals(record.getType())) - { - Map<String, Object> newAttributes = new LinkedHashMap<String, Object>(); - if(record.getAttributes().get(ARGUMENTS) instanceof Map) - { - newAttributes.putAll(QueueArgumentsConverter.convertWireArgsToModel((Map<String, Object>) record.getAttributes() - .get(ARGUMENTS))); - } - newAttributes.putAll(record.getAttributes()); - - record = new ConfiguredObjectRecordImpl(record.getId(), record.getType(), newAttributes, record.getParents()); - getUpdateMap().put(record.getId(), record); - } - - getNextUpgrader().configuredObject(record); - } - - @Override - public void complete() - { - getNextUpgrader().complete(); - } - } - - /* - * Convert the storage of queue attribute exclusive to change exclusive from a boolean to an enum - * where exclusive was false it will now be "NONE", and where true it will now be "CONTAINER" - * ensure OWNER is null unless the exclusivity policy is CONTAINER - */ - private class Version3Upgrader extends NonNullUpgrader - { - - @Override - public void configuredObject(ConfiguredObjectRecord record) - { - - if(Queue.class.getSimpleName().equals(record.getType())) - { - Map<String, Object> newAttributes = new LinkedHashMap<String, Object>(record.getAttributes()); - if(record.getAttributes().get(EXCLUSIVE) instanceof Boolean) - { - boolean isExclusive = (Boolean) record.getAttributes().get(EXCLUSIVE); - newAttributes.put(EXCLUSIVE, isExclusive ? "CONTAINER" : "NONE"); - if(!isExclusive && record.getAttributes().containsKey("owner")) - { - newAttributes.remove("owner"); - } - } - else - { - newAttributes.remove("owner"); - } - if(!record.getAttributes().containsKey("durable")) - { - newAttributes.put("durable","true"); - } - - record = new ConfiguredObjectRecordImpl(record.getId(),record.getType(),newAttributes, record.getParents()); - getUpdateMap().put(record.getId(), record); - } - - getNextUpgrader().configuredObject(record); - } - - @Override - public void complete() - { - getNextUpgrader().complete(); - } - } - - private class Version4Upgrader extends NonNullUpgrader - { - private Map<String, String> _missingAmqpExchanges = new HashMap<String, String>(DEFAULT_EXCHANGES); - - @Override - public void configuredObject(ConfiguredObjectRecord record) - { - if(Exchange.class.getSimpleName().equals(record.getType())) - { - Map<String, Object> attributes = record.getAttributes(); - String name = (String)attributes.get(NAME); - _missingAmqpExchanges.remove(name); - } - - getNextUpgrader().configuredObject(record); - } - - @Override - public void complete() - { - for (Entry<String, String> entry : _missingAmqpExchanges.entrySet()) - { - String name = entry.getKey(); - String type = entry.getValue(); - UUID id = _defaultExchangeIds.get(name); - - if (LOGGER.isDebugEnabled()) - { - LOGGER.debug("Creating amqp exchange " + name + " with id " + id); - } - - Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(org.apache.qpid.server.model.Exchange.NAME, name); - attributes.put(org.apache.qpid.server.model.Exchange.TYPE, type); - - attributes.put(org.apache.qpid.server.model.Exchange.DURABLE, true); - - 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(record); - - } - - getNextUpgrader().complete(); - } - } - -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java deleted file mode 100644 index 920f9f0675..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost; - -import java.util.HashMap; -import java.util.Map; - -import org.apache.qpid.server.exchange.AMQUnknownExchangeType; -import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObjectFactory; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.store.AbstractDurableConfiguredObjectRecoverer; -import org.apache.qpid.server.store.ConfiguredObjectRecord; -import org.apache.qpid.server.store.UnresolvedConfiguredObject; -import org.apache.qpid.server.store.UnresolvedDependency; -import org.apache.qpid.server.store.UnresolvedObject; -import org.apache.qpid.server.util.ServerScopedRuntimeException; - -public class ExchangeRecoverer extends AbstractDurableConfiguredObjectRecoverer<ExchangeImpl> -{ - private final VirtualHostImpl<?,?,?> _vhost; - private final ConfiguredObjectFactory _objectFactory; - - public ExchangeRecoverer(final VirtualHostImpl vhost) - { - _vhost = vhost; - Broker<?> broker = _vhost.getParent(Broker.class); - _objectFactory = broker.getObjectFactory(); - } - - @Override - public String getType() - { - return org.apache.qpid.server.model.Exchange.class.getSimpleName(); - } - - @Override - public UnresolvedObject<ExchangeImpl> createUnresolvedObject(final ConfiguredObjectRecord record) - { - return new UnresolvedExchange(record); - } - - private class UnresolvedExchange implements UnresolvedObject<ExchangeImpl> - { - private ExchangeImpl<?> _exchange; - - public UnresolvedExchange(ConfiguredObjectRecord record) - { - Map<String,Object> attributeMap = record.getAttributes(); - String exchangeName = (String) attributeMap.get(org.apache.qpid.server.model.Exchange.NAME); - try - { - _exchange = _vhost.getExchange(record.getId()); - if(_exchange == null) - { - _exchange = _vhost.getExchange(exchangeName); - } - if (_exchange == null) - { - Map<String,Object> attributesWithId = new HashMap<String,Object>(attributeMap); - attributesWithId.put(org.apache.qpid.server.model.Exchange.ID,record.getId()); - attributesWithId.put(org.apache.qpid.server.model.Exchange.DURABLE,true); - - UnresolvedConfiguredObject<? extends Exchange> unresolvedConfiguredObject = - _objectFactory.recover(record, _vhost); - _exchange = (ExchangeImpl<?>) unresolvedConfiguredObject.resolve(); - - } - } - catch (AMQUnknownExchangeType e) - { - throw new ServerScopedRuntimeException("Unknown exchange type found when attempting to restore " + - "exchanges, check classpath", e); - } - catch (UnknownExchangeException e) - { - throw new ServerScopedRuntimeException("Unknown alternate exchange type found when attempting to restore " + - "exchanges: ", e); - } - } - - @Override - public UnresolvedDependency[] getUnresolvedDependencies() - { - return new UnresolvedDependency[0]; - } - - @Override - public ExchangeImpl resolve() - { - _exchange.open(); - return _exchange; - } - } -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java deleted file mode 100644 index 221727ab6b..0000000000 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.ConfiguredObjectFactory; -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.UnresolvedConfiguredObject; -import org.apache.qpid.server.store.UnresolvedDependency; -import org.apache.qpid.server.store.UnresolvedObject; - -public class QueueRecoverer extends AbstractDurableConfiguredObjectRecoverer<AMQQueue> -{ - private static final Logger _logger = Logger.getLogger(QueueRecoverer.class); - private final VirtualHostImpl<?,?,?> _virtualHost; - private final ConfiguredObjectFactory _objectFactory; - - public QueueRecoverer(final VirtualHostImpl virtualHost) - { - _virtualHost = virtualHost; - Broker<?> broker = _virtualHost.getParent(Broker.class); - _objectFactory = broker.getObjectFactory(); - } - - @Override - public String getType() - { - return Queue.class.getSimpleName(); - } - - @Override - public UnresolvedObject<AMQQueue> createUnresolvedObject(final ConfiguredObjectRecord record) - { - return new UnresolvedQueue(record); - } - - private class UnresolvedQueue implements UnresolvedObject<AMQQueue> - { - - // private final UUID _alternateExchangeId; - private final ConfiguredObjectRecord _record; - private AMQQueue _queue; - private List<UnresolvedDependency> _dependencies = new ArrayList<UnresolvedDependency>(); - private ExchangeImpl _alternateExchange; - private UUID _alternateExchangeId; - private String _alternateExchangeName; - - public UnresolvedQueue(ConfiguredObjectRecord record) - { - _record = record; - Object altExchObj = record.getAttributes().get(Queue.ALTERNATE_EXCHANGE); - if(altExchObj instanceof UUID) - { - _alternateExchangeId = (UUID) altExchObj; - _dependencies.add(new AlternateExchangeDependency()); - } - else if (altExchObj instanceof String) - { - try - { - _alternateExchangeId = UUID.fromString((String)altExchObj); - } - catch (IllegalArgumentException e) - { - _alternateExchangeName = (String) altExchObj; - } - _dependencies.add(new AlternateExchangeDependency()); - } - - } - - @Override - public UnresolvedDependency[] getUnresolvedDependencies() - { - return _dependencies.toArray(new UnresolvedDependency[_dependencies.size()]); - } - - @Override - public AMQQueue resolve() - { - String queueName = (String) _record.getAttributes().get(Queue.NAME); - - _queue = _virtualHost.getQueue(_record.getId()); - if(_queue == null) - { - _queue = _virtualHost.getQueue(queueName); - } - - if (_queue == null) - { - Map<String,Object> attributesWithId = new HashMap<String,Object>(_record.getAttributes()); - attributesWithId.put(Queue.ID,_record.getId()); - attributesWithId.put(Queue.DURABLE,true); - - UnresolvedConfiguredObject<? extends Queue> unresolvedConfiguredObject = - _objectFactory.recover(_record, _virtualHost); - _queue = (AMQQueue<?>) unresolvedConfiguredObject.resolve(); - } - _queue.open(); - return _queue; - } - - private class AlternateExchangeDependency implements UnresolvedDependency - { - @Override - public UUID getId() - { - return _alternateExchangeId; - } - - @Override - public String getName() - { - return _alternateExchangeName; - } - - @Override - public String getType() - { - return "Exchange"; - } - - @Override - public void resolve(final Object dependency) - { - _alternateExchange = (ExchangeImpl) dependency; - _dependencies.remove(this); - } - } - } -} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java index e2454b0d18..645ee7ceef 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java @@ -21,163 +21,89 @@ package org.apache.qpid.server.virtualhost; import java.util.Collection; -import java.util.HashMap; import java.util.Map; -import org.apache.qpid.server.logging.messages.ConfigStoreMessages; -import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; -import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ManagedObject; -import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.plugin.MessageStoreFactory; -import org.apache.qpid.server.store.ConfiguredObjectRecordRecoveverAndUpgrader; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.store.DurableConfigurationStoreCreator; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; @ManagedObject( category = false, type = "STANDARD") public class StandardVirtualHost extends AbstractVirtualHost<StandardVirtualHost> { - public static final String TYPE = "STANDARD"; - private MessageStore _messageStore; - private DurableConfigurationStore _durableConfigurationStore; + public static final String TYPE = "STANDARD"; + MessageStore _messageStore; private MessageStoreLogSubject _messageStoreLogSubject; - private MessageStoreLogSubject _configurationStoreLogSubject; - - public StandardVirtualHost(final Map<String, Object> attributes, Broker<?> broker) + public StandardVirtualHost(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode) { - super(attributes, broker); + super(attributes, virtualHostNode); } @Override public void validate() { super.validate(); - Map<String,Object> attributes = getActualAttributes(); - Map<String, Object> messageStoreSettings = getMessageStoreSettings(); - if (messageStoreSettings == null) - { - throw new IllegalArgumentException("Attribute '"+ org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS + "' is required."); - } - - Object storeType = messageStoreSettings.get(MessageStore.STORE_TYPE); - - // need store type and path - Collection<String> knownTypes = MessageStoreFactory.FACTORY_LOADER.getSupportedTypes(); - if (storeType == null) - { - throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE - +"' is required in attribute " + org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS + ". Known types are : " + knownTypes); - } - else if (!(storeType instanceof String)) - { - throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE - +"' is required and must be of type String. " - +"Known types are : " + knownTypes); - } - MessageStoreFactory factory = MessageStoreFactory.FACTORY_LOADER.get((String)storeType); - if(factory == null) + VirtualHostNode<?> virtualHostNode = getParent(VirtualHostNode.class); + if (!virtualHostNode.isMessageStoreProvider()) { - throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE - +"' has value '" + storeType + "' which is not one of the valid values: " - + "Known types are : " + knownTypes); + Map<String,Object> attributes = getActualAttributes(); + Map<String, Object> messageStoreSettings = getMessageStoreSettings(); + if (messageStoreSettings == null) + { + throw new IllegalArgumentException("Attribute '"+ org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS + "' is required."); + } + + Object storeType = messageStoreSettings.get(MessageStore.STORE_TYPE); + + // need store type and path + Collection<String> knownTypes = MessageStoreFactory.FACTORY_LOADER.getSupportedTypes(); + + if (storeType == null) + { + throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE + +"' is required in attribute " + org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS + ". Known types are : " + knownTypes); + } + else if (!(storeType instanceof String)) + { + throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE + +"' is required and must be of type String. " + +"Known types are : " + knownTypes); + } + + MessageStoreFactory factory = MessageStoreFactory.FACTORY_LOADER.get((String)storeType); + if(factory == null) + { + throw new IllegalArgumentException("Setting '"+ MessageStore.STORE_TYPE + +"' has value '" + storeType + "' which is not one of the valid values: " + + "Known types are : " + knownTypes); + } + + factory.validateAttributes(attributes); } - - factory.validateAttributes(attributes); - - - - } - - private DurableConfigurationStore initialiseConfigurationStore(String storeType) - { - DurableConfigurationStore configurationStore; - - if(storeType != null) - { - configurationStore = new DurableConfigurationStoreCreator().createMessageStore(storeType); - } - else if(getMessageStore() instanceof DurableConfigurationStore) - { - configurationStore = (DurableConfigurationStore) getMessageStore(); - } - else - { - throw new ClassCastException(getMessageStore().getClass().getSimpleName() + - " is not an instance of DurableConfigurationStore"); - } - return configurationStore; } @Override - protected void initialiseStorage(VirtualHost virtualHost) + protected void initialiseStorage() { - Map<String, Object> messageStoreSettings = virtualHost.getMessageStoreSettings(); - String storeType = (String) messageStoreSettings.get(MessageStore.STORE_TYPE); - _messageStore = MessageStoreFactory.FACTORY_LOADER.get(storeType).createMessageStore(); - _messageStoreLogSubject = new MessageStoreLogSubject(getName(), _messageStore.getClass().getSimpleName()); - getEventLogger().message(_messageStoreLogSubject, MessageStoreMessages.CREATED()); - - Map<String, Object> configurationStoreSettings = virtualHost.getConfigurationStoreSettings(); - String configurationStoreType = configurationStoreSettings == null - ? null - : (String) configurationStoreSettings.get(DurableConfigurationStore.STORE_TYPE); - _durableConfigurationStore = initialiseConfigurationStore(configurationStoreType); - boolean combinedStores = _durableConfigurationStore == _messageStore; - if (combinedStores) + VirtualHostNode<?> virtualHostNode = getParent(VirtualHostNode.class); + if (virtualHostNode.isMessageStoreProvider()) { - configurationStoreSettings = new HashMap<String, Object>(messageStoreSettings); - configurationStoreSettings.put(DurableConfigurationStore.IS_MESSAGE_STORE_TOO, true); - } - - if (!combinedStores) - { - _configurationStoreLogSubject = - new MessageStoreLogSubject(getName(), _durableConfigurationStore.getClass().getSimpleName()); - getEventLogger().message(_configurationStoreLogSubject, ConfigStoreMessages.CREATED()); - } - - _durableConfigurationStore.openConfigurationStore(virtualHost, configurationStoreSettings); - - _messageStore.openMessageStore(virtualHost, virtualHost.getMessageStoreSettings()); - - getEventLogger().message(_messageStoreLogSubject, - MessageStoreMessages.STORE_LOCATION(_messageStore.getStoreLocation())); - - if (_configurationStoreLogSubject != null) - { - getEventLogger().message(_configurationStoreLogSubject, - ConfigStoreMessages.STORE_LOCATION(configurationStoreSettings.toString())); - getEventLogger().message(_configurationStoreLogSubject, ConfigStoreMessages.RECOVERY_START()); - } - - - if (isStoreEmpty()) - { - createDefaultExchanges(); + _messageStore = (MessageStore)virtualHostNode.getConfigurationStore(); } else { - ConfiguredObjectRecordHandler upgraderRecoverer = - new ConfiguredObjectRecordRecoveverAndUpgrader(this, getDurableConfigurationRecoverers()); - _durableConfigurationStore.visitConfiguredObjectRecords(upgraderRecoverer); + Map<String, Object> messageStoreSettings = getMessageStoreSettings(); + String storeType = (String) messageStoreSettings.get(MessageStore.STORE_TYPE); + _messageStore = MessageStoreFactory.FACTORY_LOADER.get(storeType).createMessageStore(); } - if (_configurationStoreLogSubject != null) - { - getEventLogger().message(_configurationStoreLogSubject, ConfigStoreMessages.RECOVERY_COMPLETE()); - } - - new MessageStoreRecoverer(this, getMessageStoreLogSubject()).recover(); - - attainActivation(); + _messageStoreLogSubject = new MessageStoreLogSubject(getName(), _messageStore.getClass().getSimpleName()); } @Override @@ -187,21 +113,9 @@ public class StandardVirtualHost extends AbstractVirtualHost<StandardVirtualHost } @Override - public DurableConfigurationStore getDurableConfigurationStore() - { - return _durableConfigurationStore; - } - - @Override protected MessageStoreLogSubject getMessageStoreLogSubject() { return _messageStoreLogSubject; } - @Override - protected MessageStoreLogSubject getConfigurationStoreLogSubject() - { - return _configurationStoreLogSubject; - } - } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java new file mode 100644 index 0000000000..1b2e505df9 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java @@ -0,0 +1,354 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode; + +import java.io.File; +import java.security.PrivilegedAction; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; + +import javax.security.auth.Subject; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.logging.EventLogger; +import org.apache.qpid.server.logging.messages.ConfigStoreMessages; +import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; +import org.apache.qpid.server.model.AbstractConfiguredObject; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.BrokerModel; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.SystemContext; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer; +import org.apache.qpid.server.virtualhost.StandardVirtualHost; + +public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandardVirtualHostNode<X>> extends AbstractConfiguredObject<X> + implements VirtualHostNode<X> +{ + private static final Logger LOGGER = Logger.getLogger(AbstractStandardVirtualHostNode.class); + + private final Broker<?> _broker; + private final AtomicReference<State> _state = new AtomicReference<State>(State.INITIALISING); + private final EventLogger _eventLogger; + + @ManagedAttributeField + private boolean _messageStoreProvider; + + private MessageStoreLogSubject _configurationStoreLogSubject; + private DurableConfigurationStore _durableConfigurationStore; + + @SuppressWarnings("rawtypes") + public AbstractStandardVirtualHostNode(Broker<?> parent, Map<String, Object> attributes, TaskExecutor taskExecutor) + { + super(Collections.<Class<? extends ConfiguredObject>,ConfiguredObject<?>>singletonMap(Broker.class, parent), + attributes, taskExecutor); + _broker = parent; + SystemContext systemContext = _broker.getParent(SystemContext.class); + _eventLogger = systemContext.getEventLogger(); + } + + @Override + public void validate() + { + super.validate(); + DurableConfigurationStoreFactory durableConfigurationStoreFactory = getDurableConfigurationStoreFactory(); + Map<String, Object> storeSettings = new HashMap<String, Object>(getActualAttributes()); + storeSettings.put(DurableConfigurationStore.STORE_TYPE, durableConfigurationStoreFactory.getType()); + durableConfigurationStoreFactory.validateConfigurationStoreSettings(storeSettings); + } + + @Override + public void onOpen() + { + super.onOpen(); + DurableConfigurationStoreFactory durableConfigurationStoreFactory = getDurableConfigurationStoreFactory(); + _durableConfigurationStore = durableConfigurationStoreFactory.createDurableConfigurationStore(); + _configurationStoreLogSubject = new MessageStoreLogSubject(getName(), _durableConfigurationStore.getClass().getSimpleName()); + + } + + protected abstract DurableConfigurationStoreFactory getDurableConfigurationStoreFactory(); + + protected Map<String, Object> getDefaultMessageStoreSettings() + { + // TODO perhaps look for the MS with the default annotation and associated default. + Map<String, Object> settings = new HashMap<String, Object>(); + settings.put(MessageStore.STORE_TYPE, "DERBY"); + settings.put(MessageStore.STORE_PATH, "${qpid.work_dir}" + File.separator + "derbystore" + File.separator + getName()); + return settings; + } + + @SuppressWarnings({ "rawtypes", "unchecked" }) + @Override + protected <C extends ConfiguredObject> C addChild(Class<C> childClass, Map<String, Object> attributes, + ConfiguredObject... otherParents) + { + if(childClass == VirtualHost.class) + { + return (C) getObjectFactory().create(VirtualHost.class, attributes, this); + } + return super.addChild(childClass, attributes, otherParents); + } + + + + @SuppressWarnings({ "unchecked", "rawtypes" }) + @Override + public <T extends ConfiguredObject> T getParent(Class<T> clazz) + { + if (clazz == Broker.class) + { + return (T) _broker; + } + return super.getParent(clazz); + } + + + @Override + public State getState() + { + return _state.get(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + protected boolean setState(State currentState, State desiredState) + { + State state = _state.get(); + if (desiredState == State.DELETED) + { + if (state == State.INITIALISING || state == State.ACTIVE || state == State.STOPPED || state == State.ERRORED) + { + if( _state.compareAndSet(state, State.DELETED)) + { + delete(); + return true; + } + } + else + { + throw new IllegalStateException("Cannot delete virtual host node in " + state + " state"); + } + } + else if (desiredState == State.ACTIVE) + { + if ((state == State.INITIALISING || state == State.STOPPED) && _state.compareAndSet(state, State.ACTIVE)) + { + try + { + activate(); + } + catch(RuntimeException e) + { + _state.compareAndSet(State.ACTIVE, State.ERRORED); + if (_broker.isManagementMode()) + { + LOGGER.warn("Failed to make " + this + " active.", e); + } + else + { + throw e; + } + } + return true; + } + else + { + throw new IllegalStateException("Cannot activate virtual host node in " + state + " state"); + } + } + else if (desiredState == State.STOPPED) + { + if (_state.compareAndSet(state, State.STOPPED)) + { + stop(); + return true; + } + else + { + throw new IllegalStateException("Cannot stop virtual host node in " + state + " state"); + } + } + return false; + } + + + @Override + public boolean isMessageStoreProvider() + { + return _messageStoreProvider; + } + + @Override + public VirtualHost<?,?,?> getVirtualHost() + { + Collection<VirtualHost> children = getChildren(VirtualHost.class); + if (children.size() == 0) + { + return null; + } + else if (children.size() == 1) + { + return children.iterator().next(); + } + else + { + throw new IllegalStateException(this + " has an unexpected number of virtualhost children, size " + children.size()); + } + } + + @Override + public DurableConfigurationStore getConfigurationStore() + { + return _durableConfigurationStore; + } + + private void activate() + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Activating virtualhost node " + this); + } + + Map<String, Object> attributes = buildAttributesForStore(); + + _durableConfigurationStore.openConfigurationStore(this, attributes); + + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.CREATED()); + + if (this instanceof FileBasedVirtualHostNode) + { + @SuppressWarnings("rawtypes") + FileBasedVirtualHostNode fileBasedVirtualHostNode = (FileBasedVirtualHostNode) this; + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.STORE_LOCATION(fileBasedVirtualHostNode.getStorePath())); + } + + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.RECOVERY_START()); + + VirtualHostStoreUpgraderAndRecoverer upgrader = new VirtualHostStoreUpgraderAndRecoverer(this, getObjectFactory()); + upgrader.perform(_durableConfigurationStore); + + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.RECOVERY_COMPLETE()); + + VirtualHost<?,?,?> host = getVirtualHost(); + + if (host == null) + { + if (LOGGER.isDebugEnabled()) + { + LOGGER.debug("Creating new virtualhost with name : " + getName()); + } + Map<String, Object> hostAttributes = new HashMap<String, Object>(); + hostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION); + hostAttributes.put(VirtualHost.NAME, getName()); + hostAttributes.put(VirtualHost.TYPE, StandardVirtualHost.TYPE); + if (!isMessageStoreProvider()) + { + hostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, getDefaultMessageStoreSettings()); + } + host = createChild(VirtualHost.class, hostAttributes); + } + else + { + final VirtualHost<?,?,?> recoveredHost = host; + Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>() + { + @Override + public Object run() + { + recoveredHost.open(); + return null; + } + }); + } + + host.setDesiredState(host.getState(), State.ACTIVE); + } + + private Map<String, Object> buildAttributesForStore() + { + final Map<String, Object> attributes = new HashMap<String, Object>(); + Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>() + { + @Override + public Object run() + { + for (String attributeName : getAttributeNames()) + { + Object value = getAttribute(attributeName); + attributes.put(attributeName, value); + } + return null; + } + }); + + return attributes; + } + + private void delete() + { + VirtualHost<?, ?, ?> virtualHost = getVirtualHost(); + if (virtualHost != null) + { + virtualHost.setDesiredState(virtualHost.getState(), State.DELETED); + } + //TODO: this needs to be called from parent + deleted(); + + // TODO Split onDelete into deleteMessageStore/deleteConfigStore + if (_durableConfigurationStore instanceof MessageStore) + { + ((MessageStore)_durableConfigurationStore).onDelete(); + } + + } + + private void stop() + { + VirtualHost<?, ?, ?> virtualHost = getVirtualHost(); + if (virtualHost != null) + { + virtualHost.setDesiredState(virtualHost.getState(), State.STOPPED); + } + _durableConfigurationStore.closeConfigurationStore(); + + _eventLogger.message(_configurationStoreLogSubject, ConfigStoreMessages.CLOSE()); + } + + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/FileBasedVirtualHostNode.java index 4c618f5089..52c8825e76 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/FileBasedVirtualHostNode.java @@ -18,15 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.store; +package org.apache.qpid.server.virtualhostnode; -import java.util.Map; -import java.util.UUID; +import org.apache.qpid.server.model.ManagedAttribute; +import org.apache.qpid.server.model.VirtualHostNode; -public interface DurableConfiguredObjectRecoverer +public interface FileBasedVirtualHostNode<X extends FileBasedVirtualHostNode<X>> extends VirtualHostNode<X> { - public void load(final DurableConfigurationRecoverer durableConfigurationRecoverer, - final ConfiguredObjectRecord record); + public static final String STORE_PATH = "storePath"; + + @ManagedAttribute(automate = true, mandatory = true) + public String getStorePath(); - public String getType(); } diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeFactory.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeFactory.java new file mode 100644 index 0000000000..5a753444cc --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeFactory.java @@ -0,0 +1,43 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; + +public class JsonVirtualHostNodeFactory extends AbstractConfiguredObjectTypeFactory<JsonVirtualHostNodeImpl> +{ + public JsonVirtualHostNodeFactory() + { + super(JsonVirtualHostNodeImpl.class); + } + + @Override + public JsonVirtualHostNodeImpl createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents) + { + Broker<?> parent = getParent(Broker.class, parents); + return new JsonVirtualHostNodeImpl(parent, attributes, parent.getTaskExecutor()); + } + +} diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeImpl.java b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeImpl.java new file mode 100644 index 0000000000..8f697ada76 --- /dev/null +++ b/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/JsonVirtualHostNodeImpl.java @@ -0,0 +1,61 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode; + +import java.util.Map; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.store.JsonFileConfigStoreFactory; + +@ManagedObject(category=false, type="JSON") +public class JsonVirtualHostNodeImpl extends AbstractStandardVirtualHostNode<JsonVirtualHostNodeImpl> implements FileBasedVirtualHostNode<JsonVirtualHostNodeImpl> +{ + @ManagedAttributeField + private String _storePath; + + public JsonVirtualHostNodeImpl(Broker<?> parent, Map<String, Object> attributes, TaskExecutor taskExecutor) + { + super(parent, attributes, taskExecutor); + } + + @Override + protected DurableConfigurationStoreFactory getDurableConfigurationStoreFactory() + { + return new JsonFileConfigStoreFactory(); + } + + @Override + public String getStorePath() + { + return _storePath; + } + + @Override + public String toString() + { + return getClass().getSimpleName() + " [id=" + getId() + ", name=" + getName() + ", storePath=" + getStorePath() + "]"; + } + +} diff --git a/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory b/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory index 3ec2b900e3..6d8dd61ab1 100644 --- a/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory +++ b/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory @@ -45,6 +45,5 @@ org.apache.qpid.server.exchange.FanoutExchangeFactory org.apache.qpid.server.exchange.HeadersExchangeFactory org.apache.qpid.server.exchange.TopicExchangeFactory org.apache.qpid.server.binding.BindingFactory - - +org.apache.qpid.server.virtualhostnode.JsonVirtualHostNodeFactory diff --git a/java/broker-core/src/main/resources/initial-config.json b/java/broker-core/src/main/resources/initial-config.json index 600822a033..45b02bd550 100644 --- a/java/broker-core/src/main/resources/initial-config.json +++ b/java/broker-core/src/main/resources/initial-config.json @@ -21,7 +21,7 @@ { "name": "${broker.name}", "storeVersion": 1, - "modelVersion": "1.4", + "modelVersion": "2.0", "defaultVirtualHost" : "default", "authenticationproviders" : [ { "name" : "passwordFile", @@ -52,13 +52,10 @@ "authenticationProvider" : "passwordFile", "protocols" : [ "JMX_RMI" ] }], - "virtualhosts" : [ { + "virtualhostnodes" : [ { "name" : "default", - "type" : "STANDARD", - "messageStoreSettings" : { - "storeType" : "DERBY", - "storePath" : "${qpid.work_dir}/derbystore/default" - } + "type" : "JSON", + "storePath" : "${qpid.work_dir}/json/default" } ], "plugins" : [ { "type" : "MANAGEMENT-HTTP", diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java index 9eca7458f2..28d7830290 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java @@ -23,8 +23,6 @@ package org.apache.qpid.server.configuration.startup; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -49,11 +47,8 @@ import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.SystemContext; import org.apache.qpid.server.model.SystemContextImpl; -import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.TestMemoryMessageStore; import org.apache.qpid.server.store.UnresolvedConfiguredObject; public class BrokerRecovererTest extends TestCase @@ -61,8 +56,6 @@ public class BrokerRecovererTest extends TestCase private ConfiguredObjectRecord _brokerEntry = mock(ConfiguredObjectRecord.class); private UUID _brokerId = UUID.randomUUID(); - private Map<String, Collection<ConfiguredObjectRecord>> _brokerEntryChildren = new HashMap<String, Collection<ConfiguredObjectRecord>>(); - private ConfiguredObjectRecord _authenticationProviderEntry1; private AuthenticationProvider _authenticationProvider1; private UUID _authenticationProvider1Id = UUID.randomUUID(); private SystemContext _systemContext; @@ -93,8 +86,6 @@ public class BrokerRecovererTest extends TestCase _authenticationProvider1 = mock(AuthenticationProvider.class); when(_authenticationProvider1.getName()).thenReturn("authenticationProvider1"); when(_authenticationProvider1.getId()).thenReturn(_authenticationProvider1Id); - _authenticationProviderEntry1 = mock(ConfiguredObjectRecord.class); - _brokerEntryChildren.put(AuthenticationProvider.class.getSimpleName(), Arrays.asList(_authenticationProviderEntry1)); } @Override @@ -140,37 +131,6 @@ public class BrokerRecovererTest extends TestCase } } - public void testCreateBrokerWithVirtualHost() - { - final ConfiguredObjectRecord virtualHostEntry = mock(ConfiguredObjectRecord.class); - - String typeName = VirtualHost.class.getSimpleName(); - when(virtualHostEntry.getType()).thenReturn(typeName); - _brokerEntryChildren.put(typeName, Arrays.asList(virtualHostEntry)); - - UUID vhostId = UUID.randomUUID(); - _systemContext.resolveObjects(_brokerEntry, createVhostRecord(vhostId)); - Broker<?> broker = _systemContext.getBroker(); - - assertNotNull(broker); - broker.open(); - assertEquals(_brokerId, broker.getId()); - assertEquals(1, broker.getVirtualHosts().size()); - assertEquals(vhostId, broker.getVirtualHosts().iterator().next().getId()); - - } - - public ConfiguredObjectRecord createVhostRecord(UUID id) - { - final Map<String, Object> vhostAttributes = new HashMap<String, Object>(); - vhostAttributes.put(VirtualHost.NAME, "vhost"); - vhostAttributes.put(VirtualHost.TYPE, "STANDARD"); - vhostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, Collections.singletonMap(MessageStore.STORE_TYPE, - TestMemoryMessageStore.TYPE)); - return new ConfiguredObjectRecordImpl(id, VirtualHost.class.getSimpleName(), vhostAttributes, Collections - .singletonMap(Broker.class.getSimpleName(), _brokerEntry)); - } - public ConfiguredObjectRecord createAuthProviderRecord(UUID id, String name) { final Map<String, Object> authProviderAttrs = new HashMap<String, Object>(); diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostCreationTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostCreationTest.java index 9a56d30ac6..78595afb36 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostCreationTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostCreationTest.java @@ -31,7 +31,6 @@ import java.util.UUID; import junit.framework.TestCase; -import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.model.Broker; @@ -41,41 +40,58 @@ import org.apache.qpid.server.model.ConfiguredObjectFactory; import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl; import org.apache.qpid.server.model.SystemContext; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestMemoryMessageStore; +import org.apache.qpid.server.virtualhost.AbstractVirtualHost; import org.apache.qpid.server.virtualhost.StandardVirtualHost; public class VirtualHostCreationTest extends TestCase { + private VirtualHostNode<?> _virtualHostNode; - public void testCreateVirtualHostFromStoreConfigAttributes() + @Override + public void setUp() throws Exception { + super.setUp(); + + EventLogger eventLogger = mock(EventLogger.class); SecurityManager securityManager = mock(SecurityManager.class); - ConfigurationEntry entry = mock(ConfigurationEntry.class); + SystemContext systemContext = mock(SystemContext.class); ConfiguredObjectFactory objectFactory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); when(systemContext.getObjectFactory()).thenReturn(objectFactory); when(systemContext.getModel()).thenReturn(objectFactory.getModel()); + when(systemContext.getEventLogger()).thenReturn(eventLogger); + + Broker broker = mock(Broker.class); + when(broker.getObjectFactory()).thenReturn(objectFactory); + when(broker.getModel()).thenReturn(objectFactory.getModel()); + when(broker.getSecurityManager()).thenReturn(securityManager); + when(broker.getCategoryClass()).thenReturn(Broker.class); + when(broker.getParent(eq(SystemContext.class))).thenReturn(systemContext); + + _virtualHostNode = mock(VirtualHostNode.class); + when(_virtualHostNode.getParent(Broker.class)).thenReturn(broker); + when(_virtualHostNode.getObjectFactory()).thenReturn(objectFactory); + when(_virtualHostNode.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class)); + when(_virtualHostNode.getModel()).thenReturn(objectFactory.getModel()); + } - Broker parent = mock(Broker.class); - when(parent.getObjectFactory()).thenReturn(objectFactory); - when(parent.getModel()).thenReturn(objectFactory.getModel()); - when(parent.getSecurityManager()).thenReturn(securityManager); - when(parent.getCategoryClass()).thenReturn(Broker.class); - when(systemContext.getEventLogger()).thenReturn(mock(EventLogger.class)); - when(parent.getParent(eq(SystemContext.class))).thenReturn(systemContext); - + public void testCreateVirtualHostFromStoreConfigAttributes() + { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); attributes.put(VirtualHost.TYPE, StandardVirtualHost.TYPE); attributes.put(VirtualHost.ID, UUID.randomUUID()); attributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, Collections.singletonMap(MessageStore.STORE_TYPE, TestMemoryMessageStore.TYPE)); - when(entry.getAttributes()).thenReturn(attributes); - VirtualHost host = new StandardVirtualHost(attributes,parent); + VirtualHost<?,?,?> host = new StandardVirtualHost(attributes, _virtualHostNode); host.open(); + assertNotNull("Null is returned", host); assertEquals("Unexpected name", getName(), host.getName()); } @@ -94,19 +110,6 @@ public class VirtualHostCreationTest extends TestCase public void checkMandatoryAttributesAreValidated(String[] mandatoryAttributes, Map<String, Object> attributes) { - SecurityManager securityManager = mock(SecurityManager.class); - SystemContext systemContext = mock(SystemContext.class); - ConfiguredObjectFactory objectFactory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); - when(systemContext.getObjectFactory()).thenReturn(objectFactory); - when(systemContext.getModel()).thenReturn(objectFactory.getModel()); - - Broker parent = mock(Broker.class); - when(parent.getSecurityManager()).thenReturn(securityManager); - when(parent.getParent(eq(SystemContext.class))).thenReturn(systemContext); - when(systemContext.getEventLogger()).thenReturn(mock(EventLogger.class)); - when(parent.getObjectFactory()).thenReturn(objectFactory); - when(parent.getModel()).thenReturn(objectFactory.getModel()); - for (String name : mandatoryAttributes) { Map<String, Object> copy = new HashMap<String, Object>(attributes); @@ -114,7 +117,7 @@ public class VirtualHostCreationTest extends TestCase copy.put(ConfiguredObject.ID, UUID.randomUUID()); try { - VirtualHost host = new StandardVirtualHost(copy,parent); + AbstractVirtualHost<StandardVirtualHost> host = new StandardVirtualHost(copy,_virtualHostNode); host.open(); fail("Cannot create a virtual host without a mandatory attribute " + name); } @@ -126,7 +129,6 @@ public class VirtualHostCreationTest extends TestCase { // pass } - } } } diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java index bc44d00879..691a4f9abf 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/ConfigurationEntryStoreTestCase.java @@ -47,6 +47,7 @@ import org.apache.qpid.server.model.SystemContextImpl; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; import org.apache.qpid.server.security.FileKeyStore; import org.apache.qpid.server.security.FileTrustStore; @@ -60,11 +61,11 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase private MemoryConfigurationEntryStore _store; private UUID _brokerId; - private UUID _virtualHostId; + private UUID _virtualHostNodeId; protected UUID _authenticationProviderId; private Map<String, Object> _brokerAttributes; - private Map<String, Object> _virtualHostAttributes; + private Map<String, Object> _virtualHostNodeAttributes; private Map<String, Object> _authenticationProviderAttributes; private TaskExecutor _taskExecutor; @@ -90,10 +91,10 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase _brokerAttributes.put(Broker.STATISTICS_REPORTING_PERIOD, 4000); _brokerAttributes.put(Broker.STATISTICS_REPORTING_RESET_ENABLED, true); - _virtualHostId = UUID.randomUUID(); - _virtualHostAttributes = new HashMap<String, Object>(); - _virtualHostAttributes.put(VirtualHost.NAME, "test"); - _virtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); + _virtualHostNodeId = UUID.randomUUID(); + _virtualHostNodeAttributes = new HashMap<String, Object>(); + _virtualHostNodeAttributes.put(VirtualHost.NAME, "test"); + _virtualHostNodeAttributes.put(VirtualHost.TYPE, "JSON"); _authenticationProviderId = UUID.randomUUID(); _authenticationProviderAttributes = new HashMap<String, Object>(); @@ -101,7 +102,7 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase _authenticationProviderAttributes.put(AuthenticationProvider.TYPE, AnonymousAuthenticationManager.class.getSimpleName()); _store = createStore(_brokerId, _brokerAttributes); - addConfiguration(_virtualHostId, VirtualHost.class.getSimpleName(), _virtualHostAttributes); + addConfiguration(_virtualHostNodeId, VirtualHostNode.class.getSimpleName(), _virtualHostNodeAttributes); addConfiguration(_authenticationProviderId, AuthenticationProvider.class.getSimpleName(), _authenticationProviderAttributes); } @@ -282,18 +283,18 @@ public abstract class ConfigurationEntryStoreTestCase extends QpidTestCase public void testSaveExistingVirtualHost() { - ConfigurationEntry hostEntry = _store.getEntry(_virtualHostId); + ConfigurationEntry hostEntry = _store.getEntry(_virtualHostNodeId); assertNotNull("Host configuration is not found", hostEntry); Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); virtualHostAttributes.put(VirtualHost.NAME, "test"); virtualHostAttributes.put(VirtualHost.TYPE, "STANDARD"); - ConfigurationEntry updatedEntry = new ConfigurationEntryImpl(_virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes, + ConfigurationEntry updatedEntry = new ConfigurationEntryImpl(_virtualHostNodeId, VirtualHost.class.getSimpleName(), virtualHostAttributes, hostEntry.getChildrenIds(), _store); _store.save(updatedEntry); - ConfigurationEntry newHostEntry = _store.getEntry(_virtualHostId); + ConfigurationEntry newHostEntry = _store.getEntry(_virtualHostNodeId); assertEquals("Unexpected virtual host configuration", updatedEntry, newHostEntry); assertEquals("Unexpected type", VirtualHost.class.getSimpleName(), newHostEntry.getType()); assertEquals("Unexpected virtual host attributes", updatedEntry.getAttributes(), newHostEntry.getAttributes()); diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java index f8277f0113..c832f47af1 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/configuration/store/StoreConfigurationChangeListenerTest.java @@ -32,9 +32,9 @@ import java.util.UUID; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.test.utils.QpidTestCase; @@ -82,13 +82,13 @@ public class StoreConfigurationChangeListenerTest extends QpidTestCase verify(_store).update(eq(false),any(ConfiguredObjectRecord.class)); } - public void testChildAddedForVirtualHost() + public void testChildAddedForVirtualHostNode() { notifyBrokerStarted(); - VirtualHost object = mock(VirtualHost.class); - Queue queue = mock(Queue.class); - _listener.childAdded(object, queue); + VirtualHostNode<?> object = mock(VirtualHostNode.class); + VirtualHost<?,?,?> virtualHost = mock(VirtualHost.class); + _listener.childAdded(object, virtualHost); verifyNoMoreInteractions(_store); } diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseActorTestCase.java b/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseActorTestCase.java index 3fa6c475cf..896127cc08 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseActorTestCase.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseActorTestCase.java @@ -23,15 +23,13 @@ package org.apache.qpid.server.logging.actors; import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.logging.MessageLogger; import org.apache.qpid.server.logging.UnitTestMessageLogger; import org.apache.qpid.test.utils.QpidTestCase; -public class BaseActorTestCase extends QpidTestCase +public abstract class BaseActorTestCase extends QpidTestCase { private boolean _statusUpdatesEnabled = true; private UnitTestMessageLogger _rawLogger; - private MessageLogger _rootLogger; private EventLogger _eventLogger; @Override @@ -40,7 +38,6 @@ public class BaseActorTestCase extends QpidTestCase super.setUp(); _rawLogger = new UnitTestMessageLogger(_statusUpdatesEnabled); _eventLogger = new EventLogger(_rawLogger); - _rootLogger = _rawLogger; } @Override @@ -57,10 +54,10 @@ public class BaseActorTestCase extends QpidTestCase { String message = "Test logging: " + getName(); sendTestLogMessage(message); - + return message; } - + public void sendTestLogMessage(final String message) { getEventLogger().message(new LogSubject() diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java b/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java index 7fee259e29..65f9b4b148 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java @@ -25,7 +25,7 @@ import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHostImpl; -public class BaseConnectionActorTestCase extends BaseActorTestCase +public abstract class BaseConnectionActorTestCase extends BaseActorTestCase { private AMQConnectionModel _session; private VirtualHostImpl _virtualHost; diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java index ec108a419d..26d54761cc 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java @@ -28,9 +28,8 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.configuration.updater.TaskExecutor; -import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestMemoryMessageStore; import org.apache.qpid.server.util.BrokerTestHelper; @@ -39,11 +38,9 @@ import org.apache.qpid.test.utils.QpidTestCase; public class VirtualHostTest extends QpidTestCase { - private Broker _broker; - private StatisticsGatherer _statisticsGatherer; - private RecovererProvider _recovererProvider; private TaskExecutor _taskExecutor; + private VirtualHostNode<?> _virtualHostNode; @Override protected void setUp() throws Exception @@ -55,8 +52,12 @@ public class VirtualHostTest extends QpidTestCase _taskExecutor.start(); when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); - _recovererProvider = mock(RecovererProvider.class); - _statisticsGatherer = mock(StatisticsGatherer.class); + _virtualHostNode = mock(VirtualHostNode.class); + when(_virtualHostNode.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class)); + when(_virtualHostNode.getParent(Broker.class)).thenReturn(_broker); + ConfiguredObjectFactory objectFactory = _broker.getObjectFactory(); + when(_virtualHostNode.getModel()).thenReturn(objectFactory.getModel()); + when(_virtualHostNode.getObjectFactory()).thenReturn(objectFactory); } @@ -69,26 +70,26 @@ public class VirtualHostTest extends QpidTestCase public void testInitialisingState() { - VirtualHost host = createHost(); + VirtualHost<?,?,?> host = createHost(); assertEquals("Unexpected state", State.INITIALISING, host.getAttribute(VirtualHost.STATE)); } public void testActiveState() { - VirtualHost host = createHost(); + VirtualHost<?,?,?> host = createHost(); + host.setDesiredState(State.INITIALISING, State.ACTIVE); - host.open(); assertEquals("Unexpected state", State.ACTIVE, host.getAttribute(VirtualHost.STATE)); } public void testStoppedState() { - VirtualHost host = createHost(); + VirtualHost<?,?,?> host = createHost(); assertEquals("Unexpected state", State.INITIALISING, host.getAttribute(VirtualHost.STATE)); - host.open(); + host.setDesiredState(State.INITIALISING, State.ACTIVE); assertEquals("Unexpected state", State.ACTIVE, host.getAttribute(VirtualHost.STATE)); @@ -98,7 +99,7 @@ public class VirtualHostTest extends QpidTestCase public void testDeletedState() { - VirtualHost host = createHost(); + VirtualHost<?,?,?> host = createHost(); assertEquals("Unexpected state", State.INITIALISING, host.getAttribute(VirtualHost.STATE)); @@ -108,8 +109,8 @@ public class VirtualHostTest extends QpidTestCase public void testCreateQueueChildHavingMessageGroupingAttributes() { - VirtualHost host = createHost(); - host.open(); + VirtualHost<?,?,?> host = createHost(); + host.setDesiredState(State.INITIALISING, State.ACTIVE); String queueName = getTestName(); @@ -120,7 +121,7 @@ public class VirtualHostTest extends QpidTestCase host.createChild(Queue.class, arguments); - Queue queue = (Queue) ConfiguredObjectFinder.findConfiguredObjectByName(host.getQueues(), queueName); + Queue<?> queue = (Queue<?>) ConfiguredObjectFinder.findConfiguredObjectByName(host.getQueues(), queueName); Object messageGroupKey = queue.getAttribute(Queue.MESSAGE_GROUP_KEY); assertEquals("Unexpected message group key attribute", "mykey", messageGroupKey); @@ -129,22 +130,24 @@ public class VirtualHostTest extends QpidTestCase } - private VirtualHost createHost() + private VirtualHost<?,?,?> createHost() { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); attributes.put(VirtualHost.TYPE, StandardVirtualHost.TYPE); attributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, Collections.singletonMap(MessageStore.STORE_TYPE, TestMemoryMessageStore.TYPE)); - VirtualHost host = createHost(attributes); + VirtualHost<?,?,?> host = createHost(attributes); return host; } - private VirtualHost createHost(Map<String, Object> attributes) + private VirtualHost<?,?,?> createHost(Map<String, Object> attributes) { attributes = new HashMap<String, Object>(attributes); attributes.put(VirtualHost.ID, UUID.randomUUID()); - return new StandardVirtualHost(attributes, _broker); + StandardVirtualHost host= new StandardVirtualHost(attributes, _virtualHostNode); + host.create(); + return host; } } diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java b/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java index 4e3e6d3e8a..f0838be380 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import java.io.File; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -37,7 +38,6 @@ import org.mockito.ArgumentCaptor; import org.mockito.ArgumentMatcher; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; - import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.server.binding.BindingImpl; import org.apache.qpid.server.exchange.ExchangeImpl; @@ -51,6 +51,7 @@ import org.apache.qpid.server.model.ExclusivityPolicy; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.SecurityManager; @@ -86,6 +87,10 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest protected Map<String, Object> _configurationStoreSettings; private ConfiguredObjectFactoryImpl _factory; + private ConfiguredObject<?> _parent; + + private ConfiguredObjectRecord _rootRecord; + public void setUp() throws Exception { super.setUp(); @@ -108,7 +113,16 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest String argValue = "some selector expression"; _bindingArgs.put(argKey, argValue); - reopenStore(); + + _parent = mock(ConfiguredObject.class); + when(_parent.getName()).thenReturn("testName"); + when(_parent.getObjectFactory()).thenReturn(_factory); + when(_parent.getModel()).thenReturn(_factory.getModel()); + + _configStore = createConfigStore(); + _configStore.openConfigurationStore(_parent, _configurationStoreSettings); + _rootRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), VirtualHost.class.getSimpleName(), Collections.<String, Object>emptyMap()); + _configStore.create(_rootRecord); } public void tearDown() throws Exception @@ -130,6 +144,8 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest _configStore.create(exchange.asObjectRecord()); reopenStore(); + _configStore.visitConfiguredObjectRecords(_handler); + verify(_handler).handle(matchesRecord(_exchangeId, EXCHANGE, map( org.apache.qpid.server.model.Exchange.NAME, getName(), org.apache.qpid.server.model.Exchange.TYPE, getName()+"Type", @@ -178,6 +194,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest _configStore.create(binding.asObjectRecord()); reopenStore(); + _configStore.visitConfiguredObjectRecords(_handler); Map<String,Object> map = new HashMap<String, Object>(); map.put(Binding.NAME, ROUTING_KEY); @@ -280,6 +297,8 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest _configStore.create(queue.asObjectRecord()); reopenStore(); + _configStore.visitConfiguredObjectRecords(_handler); + Map<String, Object> queueAttributes = new HashMap<String, Object>(); queueAttributes.put(Queue.NAME, getName()); queueAttributes.put(Queue.OWNER, getName()+"Owner"); @@ -297,7 +316,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest _configStore.create(queue.asObjectRecord()); reopenStore(); - + _configStore.visitConfiguredObjectRecords(_handler); Map<String,Object> queueAttributes = new HashMap<String, Object>(); @@ -317,6 +336,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest _configStore.create(queue.asObjectRecord()); reopenStore(); + _configStore.visitConfiguredObjectRecords(_handler); Map<String, Object> queueAttributes = new HashMap<String, Object>(); queueAttributes.put(Queue.NAME, getName()); @@ -351,6 +371,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest _configStore.update(false, queue.asObjectRecord()); reopenStore(); + _configStore.visitConfiguredObjectRecords(_handler); Map<String,Object> queueAttributes = new HashMap<String, Object>(); @@ -377,6 +398,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest _configStore.update(false, queue.asObjectRecord()); reopenStore(); + _configStore.visitConfiguredObjectRecords(_handler); Map<String,Object> queueAttributes = new HashMap<String, Object>(); @@ -461,6 +483,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest when(objectRecord.getId()).thenReturn(_queueId); when(objectRecord.getType()).thenReturn(Queue.class.getSimpleName()); when(objectRecord.getAttributes()).thenReturn(attributes); + when(objectRecord.getParents()).thenReturn(Collections.singletonMap(_rootRecord.getType(), _rootRecord)); when(queue.asObjectRecord()).thenReturn(objectRecord); return queue; } @@ -485,6 +508,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest when(exchangeRecord.getId()).thenReturn(_exchangeId); when(exchangeRecord.getType()).thenReturn(Exchange.class.getSimpleName()); when(exchangeRecord.getAttributes()).thenReturn(actualAttributes); + when(exchangeRecord.getParents()).thenReturn(Collections.singletonMap(_rootRecord.getType(), _rootRecord)); when(exchange.asObjectRecord()).thenReturn(exchangeRecord); when(exchange.getExchangeType()).thenReturn(mock(ExchangeType.class)); when(exchange.getEventLogger()).thenReturn(new EventLogger()); @@ -495,14 +519,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest { closeConfigStore(); _configStore = createConfigStore(); - - ConfiguredObject<?> parent = mock(ConfiguredObject.class); - when(parent.getName()).thenReturn("testName"); - - when(parent.getObjectFactory()).thenReturn(_factory); - when(parent.getModel()).thenReturn(_factory.getModel()); - _configStore.openConfigurationStore(parent, _configurationStoreSettings); - _configStore.visitConfiguredObjectRecords(_handler); + _configStore.openConfigurationStore(_parent, _configurationStoreSettings); } protected abstract DurableConfigurationStore createConfigStore() throws Exception; diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java index 27c1b7db13..67161370de 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java @@ -24,7 +24,6 @@ import static org.mockito.Matchers.any; import static org.mockito.Matchers.argThat; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -35,9 +34,6 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; -import org.mockito.ArgumentMatcher; -import org.mockito.InOrder; - import org.apache.qpid.server.model.BrokerModel; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.ConfiguredObjectFactory; @@ -48,29 +44,34 @@ 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; public class JsonFileConfigStoreTest extends QpidTestCase { private JsonFileConfigStore _store; private HashMap<String, Object> _configurationStoreSettings; - private ConfiguredObject<?> _virtualHost; + private ConfiguredObject<?> _parent; private File _storeLocation; private ConfiguredObjectRecordHandler _handler; private static final UUID ANY_UUID = UUID.randomUUID(); private static final Map<String, Object> ANY_MAP = new HashMap<String, Object>(); + private static final String VIRTUAL_HOST_TYPE = "VirtualHost"; + private ConfiguredObjectRecord _rootRecord; @Override public void setUp() throws Exception { super.setUp(); - _virtualHost = mock(ConfiguredObject.class); - when(_virtualHost.getName()).thenReturn(getName()); ConfiguredObjectFactory factory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); - when(_virtualHost.getObjectFactory()).thenReturn(factory); - when(_virtualHost.getModel()).thenReturn(factory.getModel()); + + _parent = mock(ConfiguredObject.class); + when(_parent.getName()).thenReturn(getName()); + when(_parent.getObjectFactory()).thenReturn(factory); + when(_parent.getModel()).thenReturn(factory.getModel()); _storeLocation = TestFileUtils.createTestDirectory("json", true); _configurationStoreSettings = new HashMap<String, Object>(); _configurationStoreSettings.put(JsonFileConfigStore.STORE_TYPE, JsonFileConfigStore.TYPE); @@ -99,7 +100,7 @@ public class JsonFileConfigStoreTest extends QpidTestCase _configurationStoreSettings.put(JsonFileConfigStore.STORE_PATH, null); try { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); fail("Store should not successfully configure if there is no path set"); } catch (ServerScopedRuntimeException e) @@ -114,7 +115,7 @@ public class JsonFileConfigStoreTest extends QpidTestCase _configurationStoreSettings.put(JsonFileConfigStore.STORE_PATH, System.getProperty("file.separator")); try { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); fail("Store should not successfully configure if there is an invalid path set"); } catch (ServerScopedRuntimeException e) @@ -125,50 +126,76 @@ public class JsonFileConfigStoreTest extends QpidTestCase public void testVisitEmptyStore() { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); _store.visitConfiguredObjectRecords(_handler); InOrder inorder = inOrder(_handler); inorder.verify(_handler).begin(); - inorder.verify(_handler,never()).handle(any(ConfiguredObjectRecord.class)); + inorder.verify(_handler,times(0)).handle(any(ConfiguredObjectRecord.class)); inorder.verify(_handler).end(); + + _store.closeConfigurationStore(); + } + + public void testInsertAndUpdateTopLevelObject() throws Exception + { + _store.openConfigurationStore(_parent, _configurationStoreSettings); + createRootRecord(); + _store.closeConfigurationStore(); + + _store.openConfigurationStore(_parent, _configurationStoreSettings); + Map<String, Object> newAttributes = new HashMap<String, Object>(_rootRecord.getAttributes()); + newAttributes.put("attributeName", "attributeValue"); + _store.update(false, new ConfiguredObjectRecordImpl(_rootRecord.getId(), _rootRecord.getType(), newAttributes)); + _store.closeConfigurationStore(); + + _store.openConfigurationStore(_parent, _configurationStoreSettings); + + _store.visitConfiguredObjectRecords(_handler); + + Map<String, Object> expectedAttributes = new HashMap<String, Object>(newAttributes); + verify(_handler, times(1)).handle(matchesRecord(_rootRecord.getId(), _rootRecord.getType(), expectedAttributes)); _store.closeConfigurationStore(); } public void testCreateObject() throws Exception { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); + createRootRecord(); + final UUID queueId = new UUID(0, 1); final String queueType = Queue.class.getSimpleName(); final Map<String,Object> queueAttr = Collections.singletonMap("name", (Object) "q1"); - _store.create(new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr)); + _store.create(new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr, getRootAsParentMap())); _store.closeConfigurationStore(); - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); _store.visitConfiguredObjectRecords(_handler); - verify(_handler, times(1)).handle(matchesRecord(queueId, queueType, queueAttr)); + verify(_handler).handle(matchesRecord(queueId, queueType, queueAttr)); + verify(_handler).handle(matchesRecord(ANY_UUID, VIRTUAL_HOST_TYPE, ANY_MAP)); _store.closeConfigurationStore(); } public void testCreateAndUpdateObject() throws Exception { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); + createRootRecord(); + final UUID queueId = new UUID(0, 1); final String queueType = Queue.class.getSimpleName(); Map<String,Object> queueAttr = Collections.singletonMap("name", (Object) "q1"); - _store.create(new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr)); - + _store.create(new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr, getRootAsParentMap())); queueAttr = new HashMap<String,Object>(queueAttr); queueAttr.put("owner", "theowner"); - _store.update(false, new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr)); + _store.update(false, new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr, getRootAsParentMap())); _store.closeConfigurationStore(); - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); _store.visitConfiguredObjectRecords(_handler); verify(_handler, times(1)).handle(matchesRecord(queueId, queueType, queueAttr)); _store.closeConfigurationStore(); @@ -177,12 +204,14 @@ public class JsonFileConfigStoreTest extends QpidTestCase public void testCreateAndRemoveObject() throws Exception { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); + createRootRecord(); + final UUID queueId = new UUID(0, 1); final String queueType = Queue.class.getSimpleName(); Map<String,Object> queueAttr = Collections.singletonMap("name", (Object) "q1"); - final ConfiguredObjectRecordImpl record = new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr); + final ConfiguredObjectRecordImpl record = new ConfiguredObjectRecordImpl(queueId, queueType, queueAttr, getRootAsParentMap()); _store.create(record); @@ -190,18 +219,20 @@ public class JsonFileConfigStoreTest extends QpidTestCase _store.closeConfigurationStore(); - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); _store.visitConfiguredObjectRecords(_handler); - verify(_handler, never()).handle(any(ConfiguredObjectRecord.class)); + verify(_handler, times(1)).handle(matchesRecord(ANY_UUID, VIRTUAL_HOST_TYPE, ANY_MAP)); _store.closeConfigurationStore(); } public void testCreateUnknownObjectType() throws Exception { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); + createRootRecord(); + try { - _store.create(new ConfiguredObjectRecordImpl(UUID.randomUUID(), "wibble", Collections.<String, Object>emptyMap())); + _store.create(new ConfiguredObjectRecordImpl(UUID.randomUUID(), "wibble", Collections.<String, Object>emptyMap(), getRootAsParentMap())); fail("Should not be able to create instance of type wibble"); } catch (StoreException e) @@ -212,12 +243,14 @@ public class JsonFileConfigStoreTest extends QpidTestCase public void testTwoObjectsWithSameId() throws Exception { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); + createRootRecord(); + final UUID id = UUID.randomUUID(); - _store.create(new ConfiguredObjectRecordImpl(id, "Queue", Collections.<String, Object>emptyMap())); + _store.create(new ConfiguredObjectRecordImpl(id, "Queue", Collections.<String, Object>emptyMap(), getRootAsParentMap())); try { - _store.create(new ConfiguredObjectRecordImpl(id, "Exchange", Collections.<String, Object>emptyMap())); + _store.create(new ConfiguredObjectRecordImpl(id, "Exchange", Collections.<String, Object>emptyMap(), getRootAsParentMap())); fail("Should not be able to create two objects with same id"); } catch (StoreException e) @@ -229,15 +262,17 @@ public class JsonFileConfigStoreTest extends QpidTestCase public void testChangeTypeOfObject() throws Exception { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); + createRootRecord(); + final UUID id = UUID.randomUUID(); - _store.create(new ConfiguredObjectRecordImpl(id, "Queue", Collections.<String, Object>emptyMap())); + _store.create(new ConfiguredObjectRecordImpl(id, "Queue", Collections.<String, Object>emptyMap(), getRootAsParentMap())); _store.closeConfigurationStore(); - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); try { - _store.update(false, new ConfiguredObjectRecordImpl(id, "Exchange", Collections.<String, Object>emptyMap())); + _store.update(false, new ConfiguredObjectRecordImpl(id, "Exchange", Collections.<String, Object>emptyMap(), getRootAsParentMap())); fail("Should not be able to update object to different type"); } catch (StoreException e) @@ -248,13 +283,13 @@ public class JsonFileConfigStoreTest extends QpidTestCase public void testLockFileGuaranteesExclusiveAccess() throws Exception { - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); JsonFileConfigStore secondStore = new JsonFileConfigStore(); try { - secondStore.openConfigurationStore(_virtualHost, _configurationStoreSettings); + secondStore.openConfigurationStore(_parent, _configurationStoreSettings); fail("Should not be able to open a second store with the same path"); } catch(ServerScopedRuntimeException e) @@ -262,15 +297,16 @@ public class JsonFileConfigStoreTest extends QpidTestCase // pass } _store.closeConfigurationStore(); - secondStore.openConfigurationStore(_virtualHost, _configurationStoreSettings); + secondStore.openConfigurationStore(_parent, _configurationStoreSettings); } public void testCreatedNestedObjects() throws Exception { + _store.openConfigurationStore(_parent, _configurationStoreSettings); + createRootRecord(); - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); final UUID queueId = new UUID(0, 1); final UUID queue2Id = new UUID(1, 1); @@ -280,11 +316,12 @@ public class JsonFileConfigStoreTest extends QpidTestCase final UUID bindingId = new UUID(0, 3); final UUID binding2Id = new UUID(1, 3); - final ConfiguredObjectRecordImpl queueRecord = new ConfiguredObjectRecordImpl(queueId, "Queue", EMPTY_ATTR); + Map<String, ConfiguredObjectRecord> parents = getRootAsParentMap(); + final ConfiguredObjectRecordImpl queueRecord = new ConfiguredObjectRecordImpl(queueId, "Queue", EMPTY_ATTR, parents); _store.create(queueRecord); - final ConfiguredObjectRecordImpl queue2Record = new ConfiguredObjectRecordImpl(queue2Id, "Queue", EMPTY_ATTR); + final ConfiguredObjectRecordImpl queue2Record = new ConfiguredObjectRecordImpl(queue2Id, "Queue", EMPTY_ATTR, parents); _store.create(queue2Record); - final ConfiguredObjectRecordImpl exchangeRecord = new ConfiguredObjectRecordImpl(exchangeId, "Exchange", EMPTY_ATTR); + final ConfiguredObjectRecordImpl exchangeRecord = new ConfiguredObjectRecordImpl(exchangeId, "Exchange", EMPTY_ATTR, parents); _store.create(exchangeRecord); Map<String,ConfiguredObjectRecord> bindingParents = new HashMap<String, ConfiguredObjectRecord>(); bindingParents.put("Exchange", exchangeRecord); @@ -300,7 +337,7 @@ public class JsonFileConfigStoreTest extends QpidTestCase new ConfiguredObjectRecordImpl(binding2Id, "Binding", EMPTY_ATTR, binding2Parents); _store.update(true, bindingRecord, binding2Record); _store.closeConfigurationStore(); - _store.openConfigurationStore(_virtualHost, _configurationStoreSettings); + _store.openConfigurationStore(_parent, _configurationStoreSettings); _store.visitConfiguredObjectRecords(_handler); verify(_handler).handle(matchesRecord(queueId, "Queue", EMPTY_ATTR)); verify(_handler).handle(matchesRecord(queue2Id, "Queue", EMPTY_ATTR)); @@ -311,22 +348,36 @@ public class JsonFileConfigStoreTest extends QpidTestCase } + + private void createRootRecord() + { + UUID rootRecordId = UUID.randomUUID(); + _rootRecord = new ConfiguredObjectRecordImpl(rootRecordId, VIRTUAL_HOST_TYPE, Collections.<String, Object>emptyMap()); + _store.create(_rootRecord); + } + + private Map<String, ConfiguredObjectRecord> getRootAsParentMap() + { + return Collections.<String, ConfiguredObjectRecord>singletonMap(VIRTUAL_HOST_TYPE, _rootRecord); + } + 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 final Map<String,Object> _expectedAttributes; + private final UUID _expectedId; + private final String _expectedType; private ConfiguredObjectMatcher(final UUID id, final String type, final Map<String, Object> matchingMap) { - _id = id; - _name = type; - _matchingMap = matchingMap; + _expectedId = id; + _expectedType = type; + _expectedAttributes = matchingMap; } @Override @@ -339,9 +390,9 @@ public class JsonFileConfigStoreTest extends QpidTestCase 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 (_expectedId == ANY_UUID || _expectedId.equals(binding.getId())) + && _expectedType.equals(binding.getType()) + && (_expectedAttributes == ANY_MAP || arg.equals(_expectedAttributes)); } return false; diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java b/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java index 73e14389d5..d7c11ea226 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java @@ -23,9 +23,10 @@ package org.apache.qpid.server.store; import java.util.Map; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; import org.apache.qpid.server.plugin.MessageStoreFactory; -public class TestMemoryMessageStoreFactory implements MessageStoreFactory +public class TestMemoryMessageStoreFactory implements MessageStoreFactory, DurableConfigurationStoreFactory { @Override @@ -44,4 +45,15 @@ public class TestMemoryMessageStoreFactory implements MessageStoreFactory public void validateAttributes(Map<String, Object> attributes) { } + + @Override + public DurableConfigurationStore createDurableConfigurationStore() + { + return new TestMemoryMessageStore(); + } + + @Override + public void validateConfigurationStoreSettings(Map<String, Object> attributes) + { + } } diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java index 0f2813f1d1..da03509524 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.util; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -50,6 +49,7 @@ import org.apache.qpid.server.model.SystemContext; import org.apache.qpid.server.model.SystemContextImpl; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; @@ -75,29 +75,31 @@ public class BrokerTestHelper TASK_EXECUTOR.start(); } - public static Broker createBrokerMock() + public static Broker<?> createBrokerMock() { ConfiguredObjectFactory objectFactory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); - SubjectCreator subjectCreator = mock(SubjectCreator.class); + EventLogger eventLogger = new EventLogger(); + + SystemContext systemContext = mock(SystemContext.class); + when(systemContext.getEventLogger()).thenReturn(eventLogger); + when(systemContext.getObjectFactory()).thenReturn(objectFactory); + when(systemContext.getModel()).thenReturn(objectFactory.getModel()); + when(systemContext.getCategoryClass()).thenReturn(SystemContext.class); + SubjectCreator subjectCreator = mock(SubjectCreator.class); when(subjectCreator.getMechanisms()).thenReturn(""); + Broker broker = mock(Broker.class); when(broker.getConnection_sessionCountLimit()).thenReturn(1); when(broker.getConnection_closeWhenNoRoute()).thenReturn(false); when(broker.getId()).thenReturn(UUID.randomUUID()); when(broker.getSubjectCreator(any(SocketAddress.class))).thenReturn(subjectCreator); - when(broker.getSecurityManager()).thenReturn(new SecurityManager(mock(Broker.class), false)); + when(broker.getSecurityManager()).thenReturn(new SecurityManager(broker, false)); when(broker.getObjectFactory()).thenReturn(objectFactory); when(broker.getModel()).thenReturn(objectFactory.getModel()); - when(broker.getEventLogger()).thenReturn(new EventLogger()); + when(broker.getEventLogger()).thenReturn(eventLogger); when(broker.getCategoryClass()).thenReturn(Broker.class); - - SystemContext systemContext = mock(SystemContext.class); - when(systemContext.getObjectFactory()).thenReturn(objectFactory); - when(systemContext.getModel()).thenReturn(objectFactory.getModel()); - when(systemContext.getCategoryClass()).thenReturn(SystemContext.class); - when(systemContext.getEventLogger()).thenReturn(new EventLogger()); - when(broker.getParent(eq(SystemContext.class))).thenReturn(systemContext); + when(broker.getParent(SystemContext.class)).thenReturn(systemContext); return broker; } @@ -110,34 +112,33 @@ public class BrokerTestHelper { } - public static VirtualHostImpl createVirtualHost(Map<String, Object> attributes) + public static VirtualHostImpl<?,?,?> createVirtualHost(Map<String, Object> attributes) throws Exception { //VirtualHostFactory factory = new PluggableFactoryLoader<VirtualHostFactory>(VirtualHostFactory.class).get(hostType); + Broker<?> broker = createBrokerMock(); + ConfiguredObjectFactory objectFactory = broker.getObjectFactory(); SystemContext systemContext = new SystemContextImpl(TASK_EXECUTOR, - new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()), + objectFactory, mock(EventLogger.class), mock(LogRecorder.class), new BrokerOptions()); - ConfiguredObjectFactory objectFactory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); - Broker broker = mock(Broker.class); - when(broker.getParent(eq(SystemContext.class))).thenReturn(systemContext); when(broker.getTaskExecutor()).thenReturn(TASK_EXECUTOR); - SecurityManager securityManager = new SecurityManager(broker, false); - when(broker.getSecurityManager()).thenReturn(securityManager); - when(broker.getCategoryClass()).thenReturn(Broker.class); - when(broker.getObjectFactory()).thenReturn(objectFactory); - when(broker.getModel()).thenReturn(objectFactory.getModel()); - - AbstractVirtualHost host = (AbstractVirtualHost) objectFactory.create(VirtualHost.class,attributes, broker); + VirtualHostNode<?> virtualHostNode = mock(VirtualHostNode.class); + DurableConfigurationStore dcs = mock(DurableConfigurationStore.class); + when(virtualHostNode.getConfigurationStore()).thenReturn(dcs); + when(virtualHostNode.getParent(Broker.class)).thenReturn(broker); + when(virtualHostNode.getModel()).thenReturn(objectFactory.getModel()); + when(virtualHostNode.getObjectFactory()).thenReturn(objectFactory); + AbstractVirtualHost host = (AbstractVirtualHost) objectFactory.create(VirtualHost.class, attributes, virtualHostNode ); host.setDesiredState(host.getState(), State.ACTIVE); return host; } - public static VirtualHostImpl createVirtualHost(String name) throws Exception + public static VirtualHostImpl<?,?,?> createVirtualHost(String name) throws Exception { Map<String,Object> attributes = new HashMap<String, Object>(); attributes.put(org.apache.qpid.server.model.VirtualHost.TYPE, StandardVirtualHost.TYPE); @@ -151,41 +152,40 @@ public class BrokerTestHelper return createVirtualHost(attributes); } - public static AMQSessionModel createSession(int channelId, AMQConnectionModel connection) + public static AMQSessionModel<?,?> createSession(int channelId, AMQConnectionModel<?,?> connection) { + @SuppressWarnings("rawtypes") AMQSessionModel session = mock(AMQSessionModel.class); when(session.getConnectionModel()).thenReturn(connection); when(session.getChannelId()).thenReturn(channelId); return session; } - public static AMQSessionModel createSession(int channelId) throws Exception + public static AMQSessionModel<?,?> createSession(int channelId) throws Exception { - AMQConnectionModel session = createConnection(); + AMQConnectionModel<?,?> session = createConnection(); return createSession(channelId, session); } - public static AMQSessionModel createSession() throws Exception + public static AMQSessionModel<?,?> createSession() throws Exception { return createSession(1); } - public static AMQConnectionModel createConnection() throws Exception + public static AMQConnectionModel<?,?> createConnection() throws Exception { return createConnection("test"); } - public static AMQConnectionModel createConnection(String hostName) throws Exception + public static AMQConnectionModel<?,?> createConnection(String hostName) throws Exception { - VirtualHostImpl virtualHost = createVirtualHost(hostName); - AMQConnectionModel connection = mock(AMQConnectionModel.class); - return connection; + return mock(AMQConnectionModel.class); } - public static ExchangeImpl createExchange(String hostName, final boolean durable, final EventLogger eventLogger) throws Exception + public static ExchangeImpl<?> createExchange(String hostName, final boolean durable, final EventLogger eventLogger) throws Exception { SecurityManager securityManager = new SecurityManager(mock(Broker.class), false); - final VirtualHostImpl virtualHost = mock(VirtualHostImpl.class); + final VirtualHostImpl<?,?,?> virtualHost = mock(VirtualHostImpl.class); when(virtualHost.getName()).thenReturn(hostName); when(virtualHost.getSecurityManager()).thenReturn(securityManager); when(virtualHost.getEventLogger()).thenReturn(eventLogger); @@ -210,13 +210,13 @@ public class BrokerTestHelper } - public static AMQQueue createQueue(String queueName, VirtualHostImpl virtualHost) + public static AMQQueue<?> createQueue(String queueName, VirtualHostImpl<?,?,?> virtualHost) throws QueueExistsException { Map<String,Object> attributes = new HashMap<String, Object>(); attributes.put(Queue.ID, UUIDGenerator.generateRandomUUID()); attributes.put(Queue.NAME, queueName); - AMQQueue queue = virtualHost.createQueue(attributes); + AMQQueue<?> queue = virtualHost.createQueue(attributes); return queue; } diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java deleted file mode 100644 index 17c1958cec..0000000000 --- a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java +++ /dev/null @@ -1,545 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - * - */ -package org.apache.qpid.server.virtualhost; - -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyBoolean; -import static org.mockito.Matchers.anyMap; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.UUID; - -import org.mockito.ArgumentCaptor; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.exchange.DirectExchange; -import org.apache.qpid.server.exchange.ExchangeImpl; -import org.apache.qpid.server.exchange.HeadersExchange; -import org.apache.qpid.server.exchange.TopicExchange; -import org.apache.qpid.server.logging.EventLogger; -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.model.BrokerModel; -import org.apache.qpid.server.model.ConfiguredObject; -import org.apache.qpid.server.model.ConfiguredObjectFactory; -import org.apache.qpid.server.model.Exchange; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.model.SystemContext; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory; -import org.apache.qpid.server.plugin.ExchangeType; -import org.apache.qpid.server.queue.AMQQueue; -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.DurableConfigurationStore; -import org.apache.qpid.server.store.DurableConfiguredObjectRecoverer; -import org.apache.qpid.server.store.StoreException; -import org.apache.qpid.server.store.UnresolvedConfiguredObject; -import org.apache.qpid.test.utils.QpidTestCase; - -public class DurableConfigurationRecovererTest extends QpidTestCase -{ - private static final String VIRTUAL_HOST_NAME = "test"; - private static final UUID VIRTUAL_HOST_ID = UUID.randomUUID(); - private static final UUID QUEUE_ID = new UUID(0,0); - private static final UUID TOPIC_EXCHANGE_ID = UUIDGenerator.generateExchangeUUID(TopicExchange.TYPE.getDefaultExchangeName(), VIRTUAL_HOST_NAME); - private static final UUID DIRECT_EXCHANGE_ID = UUIDGenerator.generateExchangeUUID(DirectExchange.TYPE.getDefaultExchangeName(), VIRTUAL_HOST_NAME); - private static final String CUSTOM_EXCHANGE_NAME = "customExchange"; - - private DurableConfigurationRecoverer _durableConfigurationRecoverer; - private VirtualHostImpl _vhost; - private DurableConfigurationStore _store; - private ConfiguredObjectFactory _configuredObjectFactory; - private ConfiguredObjectTypeFactory _exchangeFactory; - private ConfiguredObjectTypeFactory _queueFactory; - private ConfiguredObjectTypeFactory _bindingFactory; - - @Override - public void setUp() throws Exception - { - super.setUp(); - _configuredObjectFactory = mock(ConfiguredObjectFactory.class); - _exchangeFactory = mock(ConfiguredObjectTypeFactory.class); - _queueFactory = mock(ConfiguredObjectTypeFactory.class); - _bindingFactory = mock(ConfiguredObjectTypeFactory.class); - - - - AMQQueue<?> queue = mock(AMQQueue.class); - - _vhost = mock(VirtualHostImpl.class); - when(_vhost.getName()).thenReturn(VIRTUAL_HOST_NAME); - final Broker<?> broker = mock(Broker.class); - final SystemContext systemContext = mock(SystemContext.class); - when(systemContext.getObjectFactory()).thenReturn(_configuredObjectFactory); - when(broker.getObjectFactory()).thenReturn(_configuredObjectFactory); - when(broker.getParent(eq(SystemContext.class))).thenReturn(systemContext); - when(_vhost.getParent(eq(Broker.class))).thenReturn(broker); - - when(_vhost.getQueue(eq(QUEUE_ID))).thenReturn(queue); - - when(_configuredObjectFactory.getConfiguredObjectTypeFactory(eq(Exchange.class), anyMap())).thenReturn(_exchangeFactory); - when(_configuredObjectFactory.getConfiguredObjectTypeFactory(eq(Queue.class), anyMap())).thenReturn(_queueFactory); - when(_configuredObjectFactory.getConfiguredObjectTypeFactory(eq(Binding.class), anyMap())).thenReturn(_bindingFactory); - final ArgumentCaptor<ConfiguredObjectRecord> recordArgumentCaptor = ArgumentCaptor.forClass(ConfiguredObjectRecord.class); - when(_configuredObjectFactory.recover(recordArgumentCaptor.capture(), any(ConfiguredObject.class))).thenAnswer(new Answer<Object>() - { - @Override - public Object answer(final InvocationOnMock invocation) throws Throwable - { - ConfiguredObjectRecord record = recordArgumentCaptor.getValue(); - if(record.getType().equals("Queue")) - { - return _queueFactory.recover(mock(ConfiguredObjectFactory.class), record, _vhost); - } - else if(record.getType().equals("Exchange")) - { - return _exchangeFactory.recover(mock(ConfiguredObjectFactory.class), record, _vhost); - } - return null; - } - }); - - final ArgumentCaptor<ConfiguredObjectRecord> bindingRecordArgumentCaptor = ArgumentCaptor.forClass(ConfiguredObjectRecord.class); - when(_configuredObjectFactory.recover(bindingRecordArgumentCaptor.capture(), any(ConfiguredObject.class), any(ConfiguredObject.class))).thenAnswer(new Answer<Object>() - { - @Override - public Object answer(final InvocationOnMock invocation) throws Throwable - { - ConfiguredObjectRecord record = bindingRecordArgumentCaptor.getValue(); - if(record.getType().equals("Binding")) - { - return _bindingFactory.recover(mock(ConfiguredObjectFactory.class), record, mock(ConfiguredObject.class),mock(ConfiguredObject.class)); - } - return null; - } - }); - - - final ArgumentCaptor<ConfiguredObjectRecord> recoveredExchange = ArgumentCaptor.forClass(ConfiguredObjectRecord.class); - doAnswer(new Answer() - { - - @Override - public Object answer(final InvocationOnMock invocation) throws Throwable - { - ConfiguredObjectRecord exchangeRecord = recoveredExchange.getValue(); - ExchangeImpl exchange = mock(ExchangeImpl.class); - UUID id = exchangeRecord.getId(); - String name = (String) exchangeRecord.getAttributes().get("name"); - when(exchange.getId()).thenReturn(id); - when(exchange.getName()).thenReturn(name); - when(_vhost.getExchange(eq(id))).thenReturn(exchange); - when(_vhost.getExchange(eq(name))).thenReturn(exchange); - - UnresolvedConfiguredObject unresolved = mock(UnresolvedConfiguredObject.class); - when(unresolved.resolve()).thenReturn(exchange); - return unresolved; - } - }).when(_exchangeFactory).recover(any(ConfiguredObjectFactory.class), recoveredExchange.capture(), any(ConfiguredObject.class)); - - - - - final ArgumentCaptor<ConfiguredObjectRecord> recoveredQueue = ArgumentCaptor.forClass(ConfiguredObjectRecord.class); - doAnswer(new Answer() - { - - @Override - public Object answer(final InvocationOnMock invocation) throws Throwable - { - ConfiguredObjectRecord queueRecord = recoveredQueue.getValue(); - AMQQueue queue = mock(AMQQueue.class); - UUID id = queueRecord.getId(); - String name = (String) queueRecord.getAttributes().get("name"); - when(queue.getId()).thenReturn(id); - when(queue.getName()).thenReturn(name); - when(_vhost.getQueue(eq(id))).thenReturn(queue); - when(_vhost.getQueue(eq(name))).thenReturn(queue); - - UnresolvedConfiguredObject unresolved = mock(UnresolvedConfiguredObject.class); - when(unresolved.resolve()).thenReturn(queue); - - Map args = queueRecord.getAttributes(); - if (args.containsKey(Queue.ALTERNATE_EXCHANGE)) - { - final UUID exchangeId = UUID.fromString(args.get(Queue.ALTERNATE_EXCHANGE).toString()); - final ExchangeImpl exchange = - _vhost.getExchange(exchangeId); - when(queue.getAlternateExchange()).thenReturn(exchange); - } - - return unresolved; - } - }).when(_queueFactory).recover(any(ConfiguredObjectFactory.class), recoveredQueue.capture(), any(ConfiguredObject.class)); - - - final ArgumentCaptor<ConfiguredObjectRecord> recoveredBinding = ArgumentCaptor.forClass(ConfiguredObjectRecord.class); - final ArgumentCaptor<ConfiguredObject> parent1 = ArgumentCaptor.forClass(ConfiguredObject.class); - final ArgumentCaptor<ConfiguredObject> parent2 = ArgumentCaptor.forClass(ConfiguredObject.class); - - doAnswer(new Answer() - { - - @Override - public Object answer(final InvocationOnMock invocation) throws Throwable - { - ConfiguredObjectRecord bindingRecord = recoveredBinding.getValue(); - Binding binding = mock(Binding.class); - UUID id = bindingRecord.getId(); - String name = (String) bindingRecord.getAttributes().get("name"); - when(binding.getId()).thenReturn(id); - when(binding.getName()).thenReturn(name); - - UnresolvedConfiguredObject unresolved = mock(UnresolvedConfiguredObject.class); - when(unresolved.resolve()).thenReturn(binding); - - - return unresolved; - } - }).when(_bindingFactory).recover(any(ConfiguredObjectFactory.class), recoveredBinding.capture(), parent1.capture(), parent2.capture()); - - - - DurableConfiguredObjectRecoverer[] recoverers = { - new QueueRecoverer(_vhost), - new ExchangeRecoverer(_vhost), - new BindingRecoverer(_vhost) - }; - - final Map<String, DurableConfiguredObjectRecoverer> recovererMap= new HashMap<String, DurableConfiguredObjectRecoverer>(); - for(DurableConfiguredObjectRecoverer recoverer : recoverers) - { - recovererMap.put(recoverer.getType(), recoverer); - } - _durableConfigurationRecoverer = - new DurableConfigurationRecoverer(_vhost.getName(), recovererMap, - new DefaultUpgraderProvider(_vhost), new EventLogger()); - - _store = mock(DurableConfigurationStore.class); - - } - - public void testUpgradeEmptyStore() throws Exception - { - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - assertEquals("Did not upgrade to the expected version", - BrokerModel.MODEL_VERSION, - _durableConfigurationRecoverer.completeConfigurationRecovery()); - } - - public void testUpgradeNewerStoreFails() throws Exception - { - String bumpedModelVersion = BrokerModel.MODEL_MAJOR_VERSION + "." + (BrokerModel.MODEL_MINOR_VERSION + 1); - try - { - - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - _durableConfigurationRecoverer.configuredObject(getVirtualHostModelRecord(bumpedModelVersion)); - String newVersion = _durableConfigurationRecoverer.completeConfigurationRecovery(); - fail("Should not be able to start when config model is newer than current. Actually upgraded to " + newVersion); - } - catch (IllegalStateException e) - { - // pass - } - } - - private ConfiguredObjectRecordImpl getVirtualHostModelRecord( - String modelVersion) - { - ConfiguredObjectRecordImpl virtualHostRecord = new ConfiguredObjectRecordImpl(VIRTUAL_HOST_ID, - VirtualHost.class.getSimpleName(), - Collections.<String,Object>singletonMap("modelVersion", modelVersion)); - return virtualHostRecord; - } - - public void testUpgradeRemovesBindingsToNonTopicExchanges() throws Exception - { - - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - _durableConfigurationRecoverer.configuredObject(getVirtualHostModelRecord("0.0")); - - _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0), - "org.apache.qpid.server.model.Binding", - createBinding("key", - "x-filter-jms-selector", - "wibble"), - createBindingParents(DIRECT_EXCHANGE_ID, QUEUE_ID))); - - final ConfiguredObjectRecord[] expected = { - new ConfiguredObjectRecordImpl(new UUID(1, 0), "Binding", - createBinding("key")) - }; - - verifyCorrectUpdates(expected); - - _durableConfigurationRecoverer.completeConfigurationRecovery(); - } - - - - public void testUpgradeOnlyRemovesSelectorBindings() throws Exception - { - - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - _durableConfigurationRecoverer.configuredObject(getVirtualHostModelRecord("0.0")); - - _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0), - "org.apache.qpid.server.model.Binding", - createBinding("key", - "x-filter-jms-selector", - "wibble", - "not-a-selector", - "moo"), - createBindingParents(DIRECT_EXCHANGE_ID, QUEUE_ID))); - - - final UUID customExchangeId = new UUID(3,0); - - _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(2, 0), - "org.apache.qpid.server.model.Binding", - createBinding("key", - "x-filter-jms-selector", - "wibble", - "not-a-selector", - "moo"), - createBindingParents(customExchangeId,QUEUE_ID))); - - _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(customExchangeId, - "org.apache.qpid.server.model.Exchange", - createExchange(CUSTOM_EXCHANGE_NAME, HeadersExchange.TYPE))); - - final ConfiguredObjectRecord[] expected = { - 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); - - _durableConfigurationRecoverer.completeConfigurationRecovery(); - } - - - public void testUpgradeKeepsBindingsToTopicExchanges() throws Exception - { - - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - _durableConfigurationRecoverer.configuredObject(getVirtualHostModelRecord("0.0")); - - _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0), - "org.apache.qpid.server.model.Binding", - createBinding("key", - "x-filter-jms-selector", - "wibble"), - createBindingParents(TOPIC_EXCHANGE_ID,QUEUE_ID))); - - final ConfiguredObjectRecord[] expected = { - new ConfiguredObjectRecordImpl(new UUID(1, 0), "Binding", - createBinding("key", "x-filter-jms-selector", "wibble")) - }; - - verifyCorrectUpdates(expected); - - _durableConfigurationRecoverer.completeConfigurationRecovery(); - } - - public void testUpgradeDoesNotRecur() throws Exception - { - - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - _durableConfigurationRecoverer.configuredObject(getVirtualHostModelRecord("0.0")); - - _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0), - "Binding", - createBinding("key", - "x-filter-jms-selector", - "wibble"), - createBindingParents(DIRECT_EXCHANGE_ID,QUEUE_ID))); - - doThrow(new RuntimeException("Update Should not be called")) - .when(_store).update(anyBoolean(), any(ConfiguredObjectRecordImpl[].class)); - - _durableConfigurationRecoverer.completeConfigurationRecovery(); - } - - public void testFailsWithUnresolvedObjects() - { - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - - - _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0), - "Binding", - createBinding("key", - "x-filter-jms-selector", - "wibble"), - createBindingParents(new UUID(3,0), - QUEUE_ID))); - - try - { - _durableConfigurationRecoverer.completeConfigurationRecovery(); - fail("Expected resolution to fail due to unknown object"); - } - catch(IllegalConfigurationException e) - { - assertEquals("Durable configuration has unresolved dependencies", e.getMessage()); - } - - } - - public void testFailsWithUnknownObjectType() - { - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - - - try - { - final Map<String, Object> emptyArguments = Collections.emptyMap(); - _durableConfigurationRecoverer.configuredObject(new ConfiguredObjectRecordImpl(new UUID(1, 0), - "Wibble", emptyArguments)); - _durableConfigurationRecoverer.completeConfigurationRecovery(); - fail("Expected resolution to fail due to unknown object type"); - } - catch(IllegalConfigurationException e) - { - assertEquals("Unknown type for configured object: Wibble", e.getMessage()); - } - - - } - - public void testRecoveryOfQueueAlternateExchange() throws Exception - { - - final UUID queueId = new UUID(1, 0); - final UUID exchangeId = new UUID(2, 0); - - _durableConfigurationRecoverer.beginConfigurationRecovery(_store); - - _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))); - - _durableConfigurationRecoverer.completeConfigurationRecovery(); - - assertEquals(CUSTOM_EXCHANGE_NAME, _vhost.getQueue(queueId).getAlternateExchange().getName()); - } - - private void verifyCorrectUpdates(final ConfiguredObjectRecord[] expected) throws StoreException - { - doAnswer(new Answer() - { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable - { - Object[] args = invocation.getArguments(); - final HashSet actual = new HashSet(Arrays.asList(args[1])); - assertEquals("Updated records are not as expected", new HashSet(Arrays.asList( - expected)), actual); - - return null; - } - }).when(_store).update(anyBoolean(), any(ConfiguredObjectRecordImpl[].class)); - } - - private Map<String,Object> createBinding(String bindingKey, String... args) - { - Map<String, Object> binding = new LinkedHashMap<String, Object>(); - - binding.put("name", bindingKey); - Map<String,String> argumentMap = new LinkedHashMap<String, String>(); - if(args != null && args.length != 0) - { - String key = null; - for(String arg : args) - { - if(key == null) - { - key = arg; - } - else - { - argumentMap.put(key, arg); - key = null; - } - } - } - binding.put(Binding.ARGUMENTS, argumentMap); - 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) - { - Map<String, Object> exchange = new LinkedHashMap<String, Object>(); - - exchange.put(org.apache.qpid.server.model.Exchange.NAME, name); - exchange.put(org.apache.qpid.server.model.Exchange.TYPE, type.getType()); - - return exchange; - - } - - - private Map<String, Object> createQueue(String name, UUID alternateExchangeId) - { - Map<String, Object> queue = new LinkedHashMap<String, Object>(); - - queue.put(Queue.NAME, name); - if(alternateExchangeId != null) - { - queue.put(Queue.ALTERNATE_EXCHANGE, alternateExchangeId.toString()); - } - - return queue; - - } - - -} diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java index e92d63a6fc..3f104de77b 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java @@ -287,12 +287,6 @@ public class MockVirtualHost implements VirtualHostImpl<MockVirtualHost, AMQQueu } @Override - public Map<String, Object> getConfigurationStoreSettings() - { - return null; - } - - @Override public long getQueueCount() { return 0; @@ -658,4 +652,11 @@ public class MockVirtualHost implements VirtualHostImpl<MockVirtualHost, AMQQueu { return false; } + + @Override + public String getModelVersion() + { + return null; + } + } diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostQueueCreationTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostQueueCreationTest.java index 6a27946c29..37d8c2ca8c 100644 --- a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostQueueCreationTest.java +++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostQueueCreationTest.java @@ -32,42 +32,80 @@ import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.exchange.ExchangeImpl; +import org.apache.qpid.server.logging.EventLogger; import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.BrokerModel; import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.ConfiguredObjectFactory; +import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.SystemContext; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.PriorityQueue; import org.apache.qpid.server.queue.PriorityQueueImpl; import org.apache.qpid.server.queue.StandardQueueImpl; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestMemoryMessageStore; -import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.test.utils.QpidTestCase; public class VirtualHostQueueCreationTest extends QpidTestCase { - private VirtualHostImpl _virtualHost; - private Broker _broker; + private VirtualHostImpl<?,?,?> _virtualHost; + private VirtualHostNode<?> _virtualHostNode; + private TaskExecutor _taskExecutor; + @SuppressWarnings({ "rawtypes", "unchecked" }) @Override public void setUp() throws Exception { super.setUp(); - _broker = BrokerTestHelper.createBrokerMock(); - TaskExecutor taskExecutor = mock(TaskExecutor.class); - when(taskExecutor.isTaskExecutorThread()).thenReturn(true); - when(_broker.getTaskExecutor()).thenReturn(taskExecutor); + EventLogger eventLogger = mock(EventLogger.class); + SecurityManager securityManager = mock(SecurityManager.class); + ConfiguredObjectFactory objectFactory = new ConfiguredObjectFactoryImpl(BrokerModel.getInstance()); - _virtualHost = createHost(); - _virtualHost.open(); + _taskExecutor = new TaskExecutor(); + _taskExecutor.start(); + + SystemContext<?> context = mock(SystemContext.class); + when(context.getEventLogger()).thenReturn(eventLogger); + + Broker broker = mock(Broker.class); + when(broker.getObjectFactory()).thenReturn(objectFactory); + when(broker.getCategoryClass()).thenReturn(Broker.class); + when(broker.getParent(SystemContext.class)).thenReturn(context); + when(broker.getSecurityManager()).thenReturn(securityManager); + when(broker.getModel()).thenReturn(objectFactory.getModel()); + when(broker.getTaskExecutor()).thenReturn(_taskExecutor); + _virtualHostNode = mock(VirtualHostNode.class); + when(_virtualHostNode.getParent(Broker.class)).thenReturn(broker); + when(_virtualHostNode.getConfigurationStore()).thenReturn(mock(DurableConfigurationStore.class)); + when(_virtualHostNode.getObjectFactory()).thenReturn(objectFactory); + when(_virtualHostNode.getModel()).thenReturn(objectFactory.getModel()); + _virtualHost = createHost(); + } + @Override + public void tearDown() throws Exception + { + try + { + _taskExecutor.stopImmediately(); + } + finally + { + super.tearDown(); + } } - private VirtualHostImpl createHost() + private VirtualHostImpl<?,?,?> createHost() { Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); @@ -77,13 +115,10 @@ public class VirtualHostQueueCreationTest extends QpidTestCase attributes = new HashMap<String, Object>(attributes); attributes.put(VirtualHost.ID, UUID.randomUUID()); - return new StandardVirtualHost(attributes, _broker); - } - - @Override - public void tearDown() throws Exception - { - super.tearDown(); + StandardVirtualHost host = new StandardVirtualHost(attributes, _virtualHostNode); + host.create(); + host.setDesiredState(host.getState(), State.ACTIVE); + return host; } private void verifyRegisteredQueueCount(int count) diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java new file mode 100644 index 0000000000..3154a1e524 --- /dev/null +++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java @@ -0,0 +1,170 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.BrokerModel; +import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.SystemContext; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.store.ConfiguredObjectRecord; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.NullMessageStore; +import org.apache.qpid.server.store.StoreException; +import org.apache.qpid.server.store.TestMemoryMessageStore; +import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.StandardVirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; + +public class AbstractStandardVirtualHostNodeTest extends QpidTestCase +{ + private static final String TEST_VIRTUAL_HOST_NODE_NAME = "testNode"; + private static final String TEST_VIRTUAL_HOST_NAME = "testVirtualHost"; + + private DurableConfigurationStoreFactory _configStoreFactory = mock(DurableConfigurationStoreFactory.class); + private UUID _nodeId = UUID.randomUUID(); + private Broker<?> _broker; + private DurableConfigurationStore _configStore; + private ConfiguredObjectRecord _record; + private TaskExecutor _taskExecutor; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + _broker = BrokerTestHelper.createBrokerMock(); + SystemContext<?> systemContext = _broker.getParent(SystemContext.class); + when(systemContext.getObjectFactory()).thenReturn(new ConfiguredObjectFactoryImpl(mock(Model.class))); + + _taskExecutor = new TaskExecutor(); + _taskExecutor.start(); + when(_broker.getTaskExecutor()).thenReturn(_taskExecutor); + } + + @Override + protected void tearDown() throws Exception + { + try + { + _taskExecutor.stopImmediately(); + } + finally + { + super.tearDown(); + } + } + public void testActivationOpensConfigStoreWithExistingVirtualHostRecord() throws Exception + { + UUID virtualHostId = UUID.randomUUID(); + _record = createMockVirtualHostCOR(virtualHostId); + + _configStore = new NullMessageStore(){ + + @Override + public void visitConfiguredObjectRecords(ConfiguredObjectRecordHandler handler) throws StoreException + { + handler.begin(); + handler.handle(_record); + handler.end(); + } + }; + when(_configStoreFactory.createDurableConfigurationStore()).thenReturn(_configStore); + + Map<String, Object> nodeAttributes = new HashMap<String, Object>(); + nodeAttributes.put(VirtualHostNode.NAME, TEST_VIRTUAL_HOST_NODE_NAME); + nodeAttributes.put(VirtualHostNode.ID, _nodeId); + + VirtualHostNode<?> node = new TestVirtualHostNode(_broker, nodeAttributes, _taskExecutor, _configStore); + node.open(); + node.setDesiredState(node.getState(), State.ACTIVE); + + VirtualHost<?, ?, ?> virtualHost = node.getVirtualHost(); + assertNotNull("Virtual host was not recovered", virtualHost); + assertTrue("Unexpected virtual host type", virtualHost instanceof StandardVirtualHost); + assertEquals("Unexpected virtual host name", TEST_VIRTUAL_HOST_NAME, virtualHost.getName()); + assertEquals("Unexpected virtual host state", State.ACTIVE, virtualHost.getState()); + assertEquals("Unexpected virtual host id", virtualHostId, virtualHost.getId()); + } + + public void testActivationOpensConfigStoreWithoutVirtualHostRecord() throws Exception + { + _configStore = new NullMessageStore() { + + @Override + public void visitConfiguredObjectRecords(ConfiguredObjectRecordHandler handler) throws StoreException + { + handler.begin(); + // No records + handler.end(); + } + }; + when(_configStoreFactory.createDurableConfigurationStore()).thenReturn(_configStore); + + Map<String, Object> nodeAttributes = new HashMap<String, Object>(); + nodeAttributes.put(VirtualHostNode.NAME, TEST_VIRTUAL_HOST_NODE_NAME); + nodeAttributes.put(VirtualHostNode.ID, _nodeId); + + VirtualHostNode<?> node = new TestVirtualHostNode(_broker, nodeAttributes, _taskExecutor, _configStore); + node.open(); + node.setDesiredState(node.getState(), State.ACTIVE); + + VirtualHost<?, ?, ?> virtualHost = node.getVirtualHost(); + assertNotNull("Virtual host was not recovered", virtualHost); + assertTrue("Unexpected virtual host type", virtualHost instanceof StandardVirtualHost); + + // Virtualhost name taken from VHN and ID is random. + assertEquals("Unexpected virtual host name", TEST_VIRTUAL_HOST_NODE_NAME, virtualHost.getName()); + assertEquals("Unexpected virtual host state", State.ACTIVE, virtualHost.getState()); + assertNotNull("Unexpected virtual host id", virtualHost.getId()); + } + + private ConfiguredObjectRecord createMockVirtualHostCOR(UUID virtualHostId) + { + Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put(VirtualHost.NAME, TEST_VIRTUAL_HOST_NAME); + virtualHostAttributes.put(VirtualHost.TYPE, StandardVirtualHost.TYPE); + virtualHostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION); + Map<String,Object> messageStoreSettings = new HashMap<String, Object>(); + virtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); + messageStoreSettings.put(MessageStore.STORE_TYPE, TestMemoryMessageStore.TYPE); + + ConfiguredObjectRecord record = mock(ConfiguredObjectRecord.class); + when(record.getId()).thenReturn(virtualHostId); + when(record.getAttributes()).thenReturn(virtualHostAttributes); + when(record.getType()).thenReturn(VirtualHost.class.getSimpleName()); + return record; + } +} diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java new file mode 100644 index 0000000000..e129ce778f --- /dev/null +++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNode.java @@ -0,0 +1,85 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode; + +import java.util.Collections; +import java.util.Map; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TestMemoryMessageStore; +import org.apache.qpid.server.store.TestMemoryMessageStoreFactory; +@ManagedObject(type="TestMemory", category=false) +public class TestVirtualHostNode extends AbstractStandardVirtualHostNode<TestVirtualHostNode> +{ + private final DurableConfigurationStore _store; + + public TestVirtualHostNode(Broker<?> parent, Map<String, Object> attributes, TaskExecutor taskExecutor) + { + this(parent, attributes, taskExecutor, null); + } + + public TestVirtualHostNode(Broker<?> parent, Map<String, Object> attributes, TaskExecutor taskExecutor, DurableConfigurationStore store) + { + super(parent, attributes, taskExecutor); + _store = store; + } + + @Override + protected DurableConfigurationStoreFactory getDurableConfigurationStoreFactory() + { + if (_store != null) + { + return new DurableConfigurationStoreFactory() + { + + @Override + public void validateConfigurationStoreSettings(Map<String, Object> attributes) + { + } + + @Override + public String getType() + { + return null; + } + + @Override + public DurableConfigurationStore createDurableConfigurationStore() + { + return _store; + } + }; + } + + return new TestMemoryMessageStoreFactory(); + } + + @Override + public Map<String, Object> getDefaultMessageStoreSettings() + { + return Collections.<String, Object>singletonMap(MessageStore.STORE_TYPE, TestMemoryMessageStore.TYPE); + } +}
\ No newline at end of file diff --git a/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNodeFactory.java b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNodeFactory.java new file mode 100644 index 0000000000..2f21c21e67 --- /dev/null +++ b/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/TestVirtualHostNodeFactory.java @@ -0,0 +1,43 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; + +public class TestVirtualHostNodeFactory extends AbstractConfiguredObjectTypeFactory<TestVirtualHostNode> +{ + public TestVirtualHostNodeFactory() + { + super(TestVirtualHostNode.class); + } + + @Override + public TestVirtualHostNode createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents) + { + Broker<?> broker = getParent(Broker.class, parents); + return new TestVirtualHostNode(broker, attributes, broker.getTaskExecutor()); + } + +} diff --git a/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory b/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory new file mode 100644 index 0000000000..58b646abbf --- /dev/null +++ b/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.virtualhostnode.TestVirtualHostNodeFactory + diff --git a/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory b/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory new file mode 100644 index 0000000000..9512fb8117 --- /dev/null +++ b/java/broker-core/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.store.TestMemoryMessageStoreFactory diff --git a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java index e7a330102e..75711547e1 100644 --- a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java +++ b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java @@ -66,8 +66,11 @@ public class DerbyMessageStoreFactory implements MessageStoreFactory, DurableCon } } - @SuppressWarnings("unchecked") - Map<String, Object> configurationStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.CONFIGURATION_STORE_SETTINGS); + } + + @Override + public void validateConfigurationStoreSettings(Map<String, Object> configurationStoreSettings) + { if(configurationStoreSettings != null && getType().equals(configurationStoreSettings.get(DurableConfigurationStore.STORE_TYPE))) { Object storePath = configurationStoreSettings.get(DurableConfigurationStore.STORE_PATH); diff --git a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNode.java b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNode.java new file mode 100644 index 0000000000..f01391c0bf --- /dev/null +++ b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNode.java @@ -0,0 +1,63 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.virtualhostnode.derby; + +import java.util.Map; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.store.derby.DerbyMessageStoreFactory; +import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode; +import org.apache.qpid.server.virtualhostnode.FileBasedVirtualHostNode; + +@ManagedObject( category = false, type = "DERBY" ) +public class DerbyVirtualHostNode extends AbstractStandardVirtualHostNode<DerbyVirtualHostNode> implements FileBasedVirtualHostNode<DerbyVirtualHostNode> +{ + @ManagedAttributeField + private String _storePath; + + public DerbyVirtualHostNode(Broker<?> parent, Map<String, Object> attributes, TaskExecutor taskExecutor) + { + super(parent, attributes, taskExecutor); + } + + @Override + protected DurableConfigurationStoreFactory getDurableConfigurationStoreFactory() + { + return new DerbyMessageStoreFactory(); + } + + @Override + public String getStorePath() + { + return _storePath; + } + + @Override + public String toString() + { + return getClass().getSimpleName() + " [id=" + getId() + ", name=" + getName() + ", storePath=" + getStorePath() + "]"; + } +} diff --git a/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNodeFactory.java b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNodeFactory.java new file mode 100644 index 0000000000..7b01511036 --- /dev/null +++ b/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhostnode/derby/DerbyVirtualHostNodeFactory.java @@ -0,0 +1,45 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.virtualhostnode.derby; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; + +public class DerbyVirtualHostNodeFactory extends AbstractConfiguredObjectTypeFactory<DerbyVirtualHostNode> +{ + + public DerbyVirtualHostNodeFactory() + { + super(DerbyVirtualHostNode.class); + } + + @Override + public DerbyVirtualHostNode createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents) + { + Broker<?> broker = getParent(Broker.class, parents); + return new DerbyVirtualHostNode(broker, attributes, broker.getTaskExecutor()); + } + +} diff --git a/java/broker-plugins/derby-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory b/java/broker-plugins/derby-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory new file mode 100644 index 0000000000..9a942db521 --- /dev/null +++ b/java/broker-plugins/derby-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.virtualhostnode.derby.DerbyVirtualHostNodeFactory diff --git a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java index 509184d243..037b9ee037 100644 --- a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java +++ b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java @@ -51,11 +51,11 @@ public class JDBCMessageStore extends AbstractJDBCMessageStore implements Messag public static final String TYPE = "JDBC"; public static final String CONNECTION_URL = "connectionURL"; - public static final String CONNECTION_POOL = "connectionPool"; - public static final String JDBC_BIG_INT_TYPE = "jdbcBigIntType"; - public static final String JDBC_BYTES_FOR_BLOB = "jdbcBytesForBlob"; - public static final String JDBC_VARBINARY_TYPE = "jdbcVarbinaryType"; - public static final String JDBC_BLOB_TYPE = "jdbcBlobType"; + public static final String CONNECTION_POOL_TYPE = "connectionPoolType"; + public static final String JDBC_BIG_INT_TYPE = "bigIntType"; + public static final String JDBC_BYTES_FOR_BLOB = "bytesForBlob"; + public static final String JDBC_VARBINARY_TYPE = "varbinaryType"; + public static final String JDBC_BLOB_TYPE = "blobType"; protected String _connectionURL; private ConnectionProvider _connectionProvider; @@ -290,7 +290,7 @@ public class JDBCMessageStore extends AbstractJDBCMessageStore implements Messag throws ClassNotFoundException, SQLException { _connectionURL = String.valueOf(storeSettings.get(CONNECTION_URL)); - Object poolAttribute = storeSettings.get(CONNECTION_POOL); + Object poolAttribute = storeSettings.get(CONNECTION_POOL_TYPE); JDBCDetails details = null; diff --git a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java index acce1b75a2..b5a9d64a04 100644 --- a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java +++ b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java @@ -64,9 +64,11 @@ public class JDBCMessageStoreFactory implements MessageStoreFactory, DurableConf } } + } - @SuppressWarnings("unchecked") - Map<String, Object> configurationStoreSettings = (Map<String, Object>) attributes.get(VirtualHost.CONFIGURATION_STORE_SETTINGS); + @Override + public void validateConfigurationStoreSettings(Map<String, Object> configurationStoreSettings) + { if(configurationStoreSettings != null && getType().equals(configurationStoreSettings.get(DurableConfigurationStore.STORE_TYPE))) { Object connectionURL = configurationStoreSettings.get(JDBCMessageStore.CONNECTION_URL); diff --git a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNode.java b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNode.java new file mode 100644 index 0000000000..e6e4f960d8 --- /dev/null +++ b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNode.java @@ -0,0 +1,48 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode.jdbc; + +import org.apache.qpid.server.model.ManagedAttribute; +import org.apache.qpid.server.store.jdbc.DefaultConnectionProviderFactory; + + +public interface JDBCVirtualHostNode +{ + //TODO: Split this attribute into connectionUrl, username and password. Make the password attribute secure. + @ManagedAttribute(automate=true, mandatory=true) + String getConnectionUrl(); + + @ManagedAttribute(automate=true, defaultValue=DefaultConnectionProviderFactory.TYPE) + String getConnectionPoolType(); + + @ManagedAttribute(automate=true) + String getBigIntType(); + + @ManagedAttribute(automate=true) + boolean isBytesForBlob(); + + @ManagedAttribute(automate=true) + String getVarBinaryType(); + + @ManagedAttribute(automate=true) + String getBlobType(); + +}
\ No newline at end of file diff --git a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeFactory.java b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeFactory.java new file mode 100644 index 0000000000..aa3c38ce65 --- /dev/null +++ b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeFactory.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.virtualhostnode.jdbc; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; + +public class JDBCVirtualHostNodeFactory extends AbstractConfiguredObjectTypeFactory<JDBCVirtualHostNodeImpl> +{ + public JDBCVirtualHostNodeFactory() + { + super(JDBCVirtualHostNodeImpl.class); + } + + @Override + public JDBCVirtualHostNodeImpl createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents) + { + Broker<?> broker = getParent(Broker.class, parents); + return new JDBCVirtualHostNodeImpl(broker, attributes, broker.getTaskExecutor()); + } + +} diff --git a/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeImpl.java b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeImpl.java new file mode 100644 index 0000000000..2a1279e74b --- /dev/null +++ b/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhostnode/jdbc/JDBCVirtualHostNodeImpl.java @@ -0,0 +1,103 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode.jdbc; + +import java.util.Map; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedAttribute; +import org.apache.qpid.server.model.ManagedAttributeField; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.store.jdbc.JDBCMessageStore; +import org.apache.qpid.server.store.jdbc.JDBCMessageStoreFactory; +import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode; + +@ManagedObject( category = false, type = "JDBC" ) +public class JDBCVirtualHostNodeImpl extends AbstractStandardVirtualHostNode<JDBCVirtualHostNodeImpl> implements JDBCVirtualHostNode +{ + @ManagedAttributeField + private String _connectionUrl; + + @ManagedAttributeField + private String _connectionPoolType; + + @ManagedAttributeField + private String _bigIntType; + + @ManagedAttributeField + private boolean _bytesForBlob; + + @ManagedAttributeField + private String _varBinaryType; + + @ManagedAttributeField + private String _blobType; + + public JDBCVirtualHostNodeImpl(Broker<?> parent, Map<String, Object> attributes, TaskExecutor taskExecutor) + { + super(parent, attributes, taskExecutor); + } + + @Override + protected DurableConfigurationStoreFactory getDurableConfigurationStoreFactory() + { + return new JDBCMessageStoreFactory(); + } + + @Override + public String getConnectionUrl() + { + return _connectionUrl; + } + + @Override + public String getConnectionPoolType() + { + return _connectionPoolType; + } + + @Override + public String getBigIntType() + { + return _bigIntType; + } + + @Override + public boolean isBytesForBlob() + { + return _bytesForBlob; + } + + @Override + public String getVarBinaryType() + { + return _varBinaryType; + } + + @Override + public String getBlobType() + { + return _blobType; + } + +} diff --git a/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory b/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory new file mode 100644 index 0000000000..03e3a963a5 --- /dev/null +++ b/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.virtualhostnode.jdbc.JDBCVirtualHostNodeFactory diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java index b72ecb950d..b9651c2d8f 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -320,24 +320,26 @@ public class HttpManagement extends AbstractPluginAdapter<HttpManagement> implem root.addFilter(new FilterHolder(new RedirectingAuthorisationFilter()), "/", EnumSet.of(DispatcherType.REQUEST)); addRestServlet(root, "broker"); - addRestServlet(root, "virtualhost", VirtualHost.class); + addRestServlet(root, "virtualhostnode", VirtualHostNode.class); addRestServlet(root, "authenticationprovider", AuthenticationProvider.class); addRestServlet(root, "accesscontrolprovider", AccessControlProvider.class); addRestServlet(root, "user", AuthenticationProvider.class, User.class); addRestServlet(root, "groupprovider", GroupProvider.class); addRestServlet(root, "group", GroupProvider.class, Group.class); addRestServlet(root, "groupmember", GroupProvider.class, Group.class, GroupMember.class); - addRestServlet(root, "exchange", VirtualHost.class, Exchange.class); - addRestServlet(root, "queue", VirtualHost.class, Queue.class); - addRestServlet(root, "connection", VirtualHost.class, Connection.class); - addRestServlet(root, "binding", VirtualHost.class, Exchange.class, Queue.class, Binding.class); addRestServlet(root, "port", Port.class); - addRestServlet(root, "session", VirtualHost.class, Connection.class, Session.class); addRestServlet(root, "keystore", KeyStore.class); addRestServlet(root, "truststore", TrustStore.class); addRestServlet(root, "plugin", Plugin.class); addRestServlet(root, "preferencesprovider", AuthenticationProvider.class, PreferencesProvider.class); + addRestServlet(root, "virtualhost", VirtualHostNode.class, VirtualHost.class); + addRestServlet(root, "exchange", VirtualHostNode.class, VirtualHost.class, Exchange.class); + addRestServlet(root, "queue", VirtualHostNode.class, VirtualHost.class, Queue.class); + addRestServlet(root, "connection", VirtualHostNode.class, VirtualHost.class, Connection.class); + addRestServlet(root, "binding", VirtualHostNode.class, VirtualHost.class, Exchange.class, Queue.class, Binding.class); + addRestServlet(root, "session", VirtualHostNode.class, VirtualHost.class, Connection.class, Session.class); + root.addServlet(new ServletHolder(new UserPreferencesServlet()), "/rest/userpreferences/*"); root.addServlet(new ServletHolder(new LoggedOnUserPreferencesServlet()), "/rest/preferences"); root.addServlet(new ServletHolder(new StructureServlet()), "/rest/structure"); diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java index 7aa86313b2..074ca865a6 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageContentServlet.java @@ -77,17 +77,11 @@ public class MessageContentServlet extends AbstractServlet String vhostName = pathInfoElements[0]; String queueName = pathInfoElements[1]; - VirtualHost<?,?,?> vhost = null; - - for(VirtualHost vh : getBroker().getVirtualHosts()) + VirtualHost<?,?,?> vhost = getBroker().findVirtualHostByName(vhostName); + if (vhost == null) { - if(vh.getName().equals(vhostName)) - { - vhost = vh; - break; - } + throw new IllegalArgumentException("Could not find virtual host with name '" + vhostName + "'"); } - return getQueueFromVirtualHost(queueName, vhost); } diff --git a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java index f72471b7d4..3ee53ad892 100644 --- a/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java +++ b/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java @@ -33,7 +33,6 @@ import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.SerializationConfig; - import org.apache.qpid.server.consumer.ConsumerImpl; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; @@ -135,15 +134,10 @@ public class MessageServlet extends AbstractServlet String vhostName = pathInfoElements[0]; String queueName = pathInfoElements[1]; - VirtualHost<?,?,?> vhost = null; - - for(VirtualHost<?,?,?> vh : getBroker().getVirtualHosts()) + VirtualHost<?,?,?> vhost = getBroker().findVirtualHostByName(vhostName); + if (vhost == null) { - if(vh.getName().equals(vhostName)) - { - vhost = vh; - break; - } + throw new IllegalArgumentException("Could not find virtual host with name '" + vhostName + "'"); } return getQueueFromVirtualHost(queueName, vhost); diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java index 9ece703973..82aa806bba 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagementPluginImpl.java @@ -31,7 +31,6 @@ import java.util.Set; import javax.management.JMException; import org.apache.log4j.Logger; - import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.jmx.mbeans.LoggingManagementMBean; import org.apache.qpid.server.jmx.mbeans.ServerInformationMBean; @@ -49,6 +48,7 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.model.adapter.AbstractPluginAdapter; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.util.ServerScopedRuntimeException; @@ -74,6 +74,7 @@ public class JMXManagementPluginImpl private JMXManagedObjectRegistry _objectRegistry; + private final Object _childrenLock = new Object(); private final Map<ConfiguredObject, AMQManagedObject> _children = new HashMap<ConfiguredObject, AMQManagedObject>(); @ManagedAttributeField @@ -142,25 +143,25 @@ public class JMXManagementPluginImpl broker.addChangeListener(this); - synchronized (_children) + synchronized (_childrenLock) { - for(VirtualHost<?,?,?> virtualHost : broker.getVirtualHosts()) + for(VirtualHostNode<?> virtualHostNode : broker.getVirtualHostNodes()) { - if(!_children.containsKey(virtualHost)) + virtualHostNode.addChangeListener(this); + + // Virtualhostnodes may or may not have a virtualhost at this point. In the HA + // case, JE may spontaneously make the node a master causing it to create a virtualhost. + // Creation of the vhost uses the task executor (same thread that executes this code + // so there is no potential for a race here). + VirtualHost host = virtualHostNode.getVirtualHost(); + if (host != null) { - if(LOGGER.isDebugEnabled()) - { - LOGGER.debug("Create MBean for virtual host:" + virtualHost.getName()); - } - VirtualHostMBean mbean = new VirtualHostMBean(virtualHost, _objectRegistry); - - if(LOGGER.isDebugEnabled()) - { - LOGGER.debug("Check for additional MBeans for virtual host:" + virtualHost.getName()); - } - createAdditionalMBeansFromProviders(virtualHost, mbean); + VirtualHostMBean mbean = new VirtualHostMBean(host, _objectRegistry); + _children.put(host, mbean); } + createAdditionalMBeansFromProviders(virtualHostNode, _objectRegistry); } + Collection<AuthenticationProvider<?>> authenticationProviders = broker.getAuthenticationProviders(); for (AuthenticationProvider<?> authenticationProvider : authenticationProviders) { @@ -171,6 +172,7 @@ public class JMXManagementPluginImpl _objectRegistry); _children.put(authenticationProvider, mbean); } + createAdditionalMBeansFromProviders(authenticationProvider, _objectRegistry); } } new Shutdown(_objectRegistry); @@ -182,6 +184,13 @@ public class JMXManagementPluginImpl _objectRegistry.start(); } + @Override + protected void onOpen() + { + super.onOpen(); + + } + private boolean isConnectorPort(Port port) { return port.getAvailableProtocols().contains(Protocol.JMX_RMI); @@ -194,7 +203,7 @@ public class JMXManagementPluginImpl private void stop() { - synchronized (_children) + synchronized (_childrenLock) { for(ConfiguredObject object : _children.keySet()) { @@ -227,11 +236,16 @@ public class JMXManagementPluginImpl @Override public void childAdded(ConfiguredObject object, ConfiguredObject child) { - synchronized (_children) + + synchronized (_childrenLock) { try { AMQManagedObject mbean; + if (child instanceof VirtualHostNode) + { + child.addChangeListener(this); + } if(child instanceof VirtualHost) { VirtualHost vhostChild = (VirtualHost)child; @@ -248,8 +262,9 @@ public class JMXManagementPluginImpl if (mbean != null) { - createAdditionalMBeansFromProviders(child, mbean); + _children.put(child, mbean); } + createAdditionalMBeansFromProviders(child, _objectRegistry); } catch(Exception e) { @@ -262,8 +277,10 @@ public class JMXManagementPluginImpl @Override public void childRemoved(ConfiguredObject object, ConfiguredObject child) { - synchronized (_children) + synchronized (_childrenLock) { + child.removeChangeListener(this); + AMQManagedObject mbean = _children.remove(child); if(mbean != null) { @@ -286,10 +303,8 @@ public class JMXManagementPluginImpl // no-op } - private void createAdditionalMBeansFromProviders(ConfiguredObject child, AMQManagedObject mbean) throws JMException + private void createAdditionalMBeansFromProviders(ConfiguredObject child, ManagedObjectRegistry registry) throws JMException { - _children.put(child, mbean); - QpidServiceLoader<MBeanProvider> qpidServiceLoader = new QpidServiceLoader<MBeanProvider>(); for (MBeanProvider provider : qpidServiceLoader.instancesOf(MBeanProvider.class)) { @@ -298,16 +313,22 @@ public class JMXManagementPluginImpl LOGGER.debug("Consulting mbean provider : " + provider + " for child : " + child); } + ManagedObject mBean = null; if (provider.isChildManageableByMBean(child)) { if(LOGGER.isDebugEnabled()) { LOGGER.debug("Provider will create mbean"); } - provider.createMBean(child, mbean); + mBean = provider.createMBean(child, registry); // TODO track the mbeans that have been created on behalf of a child in a map, then // if the child is ever removed, destroy these beans too. } + + if(LOGGER.isDebugEnabled()) + { + LOGGER.debug("Provider " + provider + " mBean for child " + child + " " + mBean); + } } } diff --git a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java index a0ef052314..8817c16f83 100644 --- a/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java +++ b/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/MBeanProvider.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.jmx; import javax.management.JMException; -import javax.management.StandardMBean; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.plugin.Pluggable; @@ -44,9 +43,10 @@ public interface MBeanProvider extends Pluggable /** * Creates a mbean for this child. This method should only be called if * {@link #isChildManageableByMBean(ConfiguredObject)} has previously returned true. + * @param registry managed object registry * * @return newly created mbean */ - StandardMBean createMBean(ConfiguredObject child, StandardMBean parent) throws JMException; + ManagedObject createMBean(ConfiguredObject child, ManagedObjectRegistry registry) throws JMException; } diff --git a/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java index db4cae1258..92f1e05870 100644 --- a/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java +++ b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java @@ -22,9 +22,10 @@ package org.apache.qpid.server.store; import java.util.Map; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; import org.apache.qpid.server.plugin.MessageStoreFactory; -public class MemoryMessageStoreFactory implements MessageStoreFactory +public class MemoryMessageStoreFactory implements MessageStoreFactory, DurableConfigurationStoreFactory { @Override @@ -43,4 +44,15 @@ public class MemoryMessageStoreFactory implements MessageStoreFactory public void validateAttributes(Map<String, Object> attributes) { } + + @Override + public DurableConfigurationStore createDurableConfigurationStore() + { + return new MemoryMessageStore(); + } + + @Override + public void validateConfigurationStoreSettings(Map<String, Object> attributes) + { + } } diff --git a/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNode.java b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNode.java new file mode 100644 index 0000000000..89c4851b38 --- /dev/null +++ b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNode.java @@ -0,0 +1,47 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode.memory; + +import java.util.Map; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ManagedObject; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.store.MemoryMessageStoreFactory; +import org.apache.qpid.server.virtualhostnode.AbstractStandardVirtualHostNode; + +@ManagedObject(type="Memory",category=false) +public class MemoryVirtualHostNode extends AbstractStandardVirtualHostNode<MemoryVirtualHostNode> +{ + + public MemoryVirtualHostNode(Broker<?> parent, Map<String, Object> attributes, TaskExecutor taskExecutor) + { + super(parent, attributes, taskExecutor); + } + + @Override + public DurableConfigurationStoreFactory getDurableConfigurationStoreFactory() + { + return new MemoryMessageStoreFactory(); + } + +} diff --git a/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNodeFactory.java b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNodeFactory.java new file mode 100644 index 0000000000..f19ff037de --- /dev/null +++ b/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/virtualhostnode/memory/MemoryVirtualHostNodeFactory.java @@ -0,0 +1,44 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhostnode.memory; + +import java.util.Map; + +import org.apache.qpid.server.model.AbstractConfiguredObjectTypeFactory; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; + +public class MemoryVirtualHostNodeFactory extends AbstractConfiguredObjectTypeFactory<MemoryVirtualHostNode> +{ + + public MemoryVirtualHostNodeFactory() + { + super(MemoryVirtualHostNode.class); + } + + @Override + protected MemoryVirtualHostNode createInstance(Map<String, Object> attributes, ConfiguredObject<?>... parents) + { + Broker<?> broker = getParent(Broker.class, parents); + return new MemoryVirtualHostNode(broker, attributes, broker.getTaskExecutor()); + } + +} diff --git a/java/broker-plugins/memory-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory b/java/broker-plugins/memory-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory new file mode 100644 index 0000000000..a29a1b43f9 --- /dev/null +++ b/java/broker-plugins/memory-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.virtualhostnode.memory.MemoryVirtualHostNodeFactory diff --git a/java/common/src/main/java/org/apache/qpid/util/Strings.java b/java/common/src/main/java/org/apache/qpid/util/Strings.java index 3a1a619981..5b544014a3 100644 --- a/java/common/src/main/java/org/apache/qpid/util/Strings.java +++ b/java/common/src/main/java/org/apache/qpid/util/Strings.java @@ -227,6 +227,10 @@ public final class Strings private static final String expand(String input, Resolver resolver, Stack<String> stack, boolean failOnUnresolved) { + if (input == null) + { + throw new IllegalArgumentException("Expansion input cannot be null"); + } Matcher m = VAR.matcher(input); StringBuffer result = new StringBuffer(); while (m.find()) diff --git a/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java b/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java index 7113f79829..f30e856ef4 100644 --- a/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java +++ b/java/qpid-test-utils/src/main/java/org/apache/qpid/test/utils/QpidTestCase.java @@ -157,6 +157,10 @@ public class QpidTestCase extends TestCase return storeType != null ? storeType : "TestableMemory"; } + public String getTestProfileVirtualHostNodeType() + { + return getTestProfileMessageStoreType(); + } public static final int MIN_PORT_NUMBER = 1; public static final int MAX_PORT_NUMBER = 49151; diff --git a/java/systests/etc/config-systests.json b/java/systests/etc/config-systests.json index dac8ee4fd4..b01399fbd8 100644 --- a/java/systests/etc/config-systests.json +++ b/java/systests/etc/config-systests.json @@ -22,7 +22,7 @@ "name": "Broker", "defaultVirtualHost" : "test", "storeVersion": 1, - "modelVersion": "1.4", + "modelVersion": "2.0", "authenticationproviders" : [ { "name" : "plain", "type" : "PlainPasswordFile", @@ -57,12 +57,10 @@ "port" : "${test.cport}", "protocols" : [ "JMX_RMI" ] }], - "virtualhosts" : [ { + "virtualhostnodes" : [ { "name" : "test", - "type" : "STANDARD", - "messageStoreSettings": { - "storeType": "${messagestore.type}", - "storePath" : "${QPID_WORK}/test/${test.port}" - } + "type" : "${messagestore.type}", + "messageStoreProvider": true, + "storePath" : "${QPID_WORK}/test/${test.port}" } ] } diff --git a/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java b/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java index afc630296d..15ec0f9a4d 100644 --- a/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java +++ b/java/systests/src/main/java/org/apache/qpid/client/failover/MultipleBrokersFailoverTest.java @@ -98,7 +98,7 @@ public class MultipleBrokersFailoverTest extends QpidBrokerTestCase implements C { host = NON_FAILOVER_VIRTUAL_HOST; } - createTestVirtualHost(port, host); + createTestVirtualHostNode(port, host); startBroker(port); revertSystemProperties(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java index c5049467c9..31888167af 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/logging/AlertingTest.java @@ -186,7 +186,7 @@ public class AlertingTest extends AbstractTestLogging setTestSystemProperty("queue.alertThresholdQueueDepthMessages","5"); brokerConfiguration.setSaved(false); - restTestHelper.submitRequest("/rest/queue/test/" + getTestQueueName(), "PUT", Collections.<String, Object>singletonMap(org.apache.qpid.server.model.Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 5)); + restTestHelper.submitRequest("/rest/queue/test/test/" + getTestQueueName(), "PUT", Collections.<String, Object>singletonMap(org.apache.qpid.server.model.Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 5)); // Trigger the new value sendMessage(_session, _destination, 3); _session.commit(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java index 1ecf43aa9b..165fbed00c 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLJMXTest.java @@ -45,10 +45,10 @@ public class ExternalACLJMXTest extends AbstractACLTestCase public void setUp() throws Exception { //remove the normal 'test' vhost, we will configure the vhosts below - getBrokerConfiguration(0).removeObjectConfiguration(org.apache.qpid.server.model.VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + getBrokerConfiguration(0).removeObjectConfiguration(org.apache.qpid.server.model.VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); - createTestVirtualHost(0, TEST_VHOST); - createTestVirtualHost(0, TEST2_VHOST); + createTestVirtualHostNode(0, TEST_VHOST); + createTestVirtualHostNode(0, TEST2_VHOST); getBrokerConfiguration().addJmxManagementConfiguration(); diff --git a/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java b/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java index f2e72be447..04b8385e69 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/stats/StatisticsReportingTest.java @@ -39,6 +39,7 @@ import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.util.LogMonitor; @@ -66,14 +67,14 @@ public class StatisticsReportingTest extends QpidBrokerTestCase @Override public void setUp() throws Exception { - createTestVirtualHost(0, VHOST_NAME1); - createTestVirtualHost(0, VHOST_NAME2); - createTestVirtualHost(0, VHOST_NAME3); + createTestVirtualHostNode(0, VHOST_NAME1); + createTestVirtualHostNode(0, VHOST_NAME2); + createTestVirtualHostNode(0, VHOST_NAME3); if (getName().equals("testEnabledStatisticsReporting")) { TestBrokerConfiguration config = getBrokerConfiguration(); - config.removeObjectConfiguration(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + config.removeObjectConfiguration(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); config.setBrokerAttribute(Broker.STATISTICS_REPORTING_PERIOD, STATISTICS_REPORTING_PERIOD_IN_SECONDS); } diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/SplitStoreTest.java b/java/systests/src/main/java/org/apache/qpid/server/store/SplitStoreTest.java index 1b7f443705..6b93338f3f 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/store/SplitStoreTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/store/SplitStoreTest.java @@ -31,9 +31,11 @@ import javax.jms.Queue; import javax.jms.Session; import org.apache.qpid.configuration.ClientProperties; -import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.test.utils.TestUtils; import org.apache.qpid.util.FileUtils; public class SplitStoreTest extends QpidBrokerTestCase @@ -52,6 +54,19 @@ public class SplitStoreTest extends QpidBrokerTestCase } @Override + protected void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + TestFileUtils.delete(new File(_messageStorePath), true); + } + } + + @Override public void startBroker() throws Exception { // Overridden to prevent QBTC starting the Broker. @@ -59,38 +74,32 @@ public class SplitStoreTest extends QpidBrokerTestCase public void testJsonConfigurationStoreWithPersistentMessageStore() throws Exception { - Map<String, Object> configurationStoreSettings = new HashMap<String, Object>(); - configurationStoreSettings.put(DurableConfigurationStore.STORE_TYPE, JsonFileConfigStore.TYPE); - configurationStoreSettings.put(DurableConfigurationStore.STORE_PATH, _configStorePath); - doTest(configurationStoreSettings); + doTest(JsonFileConfigStore.TYPE, _configStorePath); } public void testSeparateConfigurationAndMessageStoresOfTheSameType() throws Exception { - Map<String, Object> configurationStoreSettings = new HashMap<String, Object>(); - configurationStoreSettings.put(DurableConfigurationStore.STORE_TYPE, getTestProfileMessageStoreType()); - configurationStoreSettings.put(DurableConfigurationStore.STORE_PATH, _configStorePath); - - doTest(configurationStoreSettings); + doTest(getTestProfileVirtualHostNodeType(), _configStorePath); } - private void configureAndStartBroker(Map<String, Object> configurationStoreSettings) throws Exception + private void configureAndStartBroker(String nodeType, String storePath) throws Exception { + TestBrokerConfiguration config = getBrokerConfiguration(); + config.setObjectAttribute(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHostNode.TYPE, nodeType); + config.setObjectAttribute(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, DurableConfigurationStore.STORE_PATH, storePath); + config.setObjectAttribute(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHostNode.IS_MESSAGE_STORE_PROVIDER, false); + Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); messageStoreSettings.put(MessageStore.STORE_TYPE, getTestProfileMessageStoreType()); messageStoreSettings.put(MessageStore.STORE_PATH, _messageStorePath); - - TestBrokerConfiguration config = getBrokerConfiguration(); - config.setObjectAttribute(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); - config.setObjectAttribute(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.CONFIGURATION_STORE_SETTINGS, configurationStoreSettings); - + TestUtils.createStoreWithVirtualHostEntry(messageStoreSettings, config, nodeType); super.startBroker(); } - private void doTest(Map<String, Object> configurationStoreSettings) throws Exception + private void doTest(String nodeType, String path) throws Exception { - configureAndStartBroker(configurationStoreSettings); + configureAndStartBroker(nodeType, path); Connection connection = getConnection(); Session session = connection.createSession(true, Session.SESSION_TRANSACTED); diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java b/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java index 25a3571787..67484ce01b 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/store/StoreOverfullTest.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.store; +import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.concurrent.CountDownLatch; @@ -39,9 +40,9 @@ import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQSession; import org.apache.qpid.exchange.ExchangeDefaults; -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.test.utils.TestUtils; +import org.apache.qpid.util.FileUtils; public class StoreOverfullTest extends QpidBrokerTestCase { @@ -59,9 +60,12 @@ public class StoreOverfullTest extends QpidBrokerTestCase private MessageConsumer _consumer; private Queue _queue; + private String _storePath; + private static final int OVERFULL_SIZE = 400000; private static final int UNDERFULL_SIZE = 350000; + @Override public void setUp() throws Exception { Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); @@ -69,8 +73,7 @@ public class StoreOverfullTest extends QpidBrokerTestCase messageStoreSettings.put(MessageStore.OVERFULL_SIZE, OVERFULL_SIZE); messageStoreSettings.put(MessageStore.UNDERFULL_SIZE, UNDERFULL_SIZE); - TestBrokerConfiguration config = getBrokerConfiguration(); - config.setObjectAttribute(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); + _storePath = TestUtils.createStoreWithVirtualHostEntry(messageStoreSettings, getBrokerConfiguration(), getTestProfileVirtualHostNodeType()); super.setUp(); @@ -93,7 +96,17 @@ public class StoreOverfullTest extends QpidBrokerTestCase } finally { - super.tearDown(); + try + { + super.tearDown(); + } + finally + { + if (_storePath != null) + { + FileUtils.delete(new File(_storePath), true); + } + } } } diff --git a/java/systests/src/main/java/org/apache/qpid/server/store/VirtualHostMessageStoreTest.java b/java/systests/src/main/java/org/apache/qpid/server/store/VirtualHostMessageStoreTest.java index 1b0f44af49..c016cf25c0 100644 --- a/java/systests/src/main/java/org/apache/qpid/server/store/VirtualHostMessageStoreTest.java +++ b/java/systests/src/main/java/org/apache/qpid/server/store/VirtualHostMessageStoreTest.java @@ -20,13 +20,15 @@ */ package org.apache.qpid.server.store; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; - -import org.apache.log4j.Logger; +import java.util.UUID; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQShortString; @@ -35,16 +37,22 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.framing.amqp_8_0.BasicConsumeBodyImpl; +import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.exchange.DirectExchange; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.exchange.TopicExchange; import org.apache.qpid.server.message.InstanceProperties; import org.apache.qpid.server.message.MessageSource; import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.ConfiguredObjectFactory; import org.apache.qpid.server.model.ExclusivityPolicy; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.protocol.v0_8.MessageMetaData; @@ -57,9 +65,8 @@ import org.apache.qpid.server.queue.StandardQueueImpl; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.virtualhost.AbstractVirtualHost; -import org.apache.qpid.server.virtualhost.StandardVirtualHost; import org.apache.qpid.server.virtualhost.VirtualHostImpl; +import org.apache.qpid.server.virtualhostnode.FileBasedVirtualHostNode; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; @@ -73,7 +80,6 @@ import org.apache.qpid.util.FileUtils; */ public class VirtualHostMessageStoreTest extends QpidTestCase { - private static final Logger _logger = Logger.getLogger(VirtualHostMessageStoreTest.class); public static final int DEFAULT_PRIORTY_LEVEL = 5; public static final String SELECTOR_VALUE = "Test = 'MST'"; @@ -100,41 +106,36 @@ public class VirtualHostMessageStoreTest extends QpidTestCase private String queueOwner = "MST"; - private AbstractVirtualHost<?> _virtualHost; + private VirtualHostImpl<?,?,?> _virtualHost; private String _storePath; - private Map<String, Object> _attributes; + private VirtualHostNode<?> _node; + private TaskExecutor _taskExecutor; public void setUp() throws Exception { super.setUp(); - BrokerTestHelper.setUp(); String hostName = getName(); _storePath = System.getProperty("QPID_WORK", TMP_FOLDER + File.separator + getTestName()) + File.separator + hostName; - - Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); - messageStoreSettings.put(MessageStore.STORE_PATH, _storePath); - messageStoreSettings.put(MessageStore.STORE_TYPE, getTestProfileMessageStoreType()); - - _attributes = new HashMap<String, Object>(); - _attributes.put(org.apache.qpid.server.model.VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); - _attributes.put(org.apache.qpid.server.model.VirtualHost.TYPE, StandardVirtualHost.TYPE); - _attributes.put(org.apache.qpid.server.model.VirtualHost.NAME, hostName); - - cleanup(new File(_storePath)); - reloadVirtualHost(); - } + Broker<?> broker = BrokerTestHelper.createBrokerMock(); + _taskExecutor = new TaskExecutor(); + _taskExecutor.start(); + when(broker.getTaskExecutor()).thenReturn(_taskExecutor); - protected String getStorePath() - { - return _storePath; - } + ConfiguredObjectFactory factory = broker.getObjectFactory(); + Map<String, Object> nodeAttributes = new HashMap<String, Object>(); + nodeAttributes.put(ConfiguredObject.TYPE, getTestProfileVirtualHostNodeType()); + nodeAttributes.put(FileBasedVirtualHostNode.STORE_PATH, _storePath); + nodeAttributes.put(VirtualHostNode.IS_MESSAGE_STORE_PROVIDER, true); + nodeAttributes.put(VirtualHostNode.NAME, hostName); + nodeAttributes.put(VirtualHostNode.ID, UUID.randomUUID()); + _node = factory.create(VirtualHostNode.class, nodeAttributes, broker); + _node.setDesiredState(_node.getState(), State.ACTIVE); + + _virtualHost = (VirtualHostImpl<?,?,?>)_node.getVirtualHost(); - protected org.apache.qpid.server.model.VirtualHost<?,?,?> getVirtualHostModel() - { - return _virtualHost; } @Override @@ -144,54 +145,31 @@ public class VirtualHostMessageStoreTest extends QpidTestCase { if (_virtualHost != null) { - _virtualHost.close(); + VirtualHostNode<?> node = _virtualHost.getParent(VirtualHostNode.class); + node.setDesiredState(node.getState(), State.STOPPED); } } finally { - BrokerTestHelper.tearDown(); + _taskExecutor.stopImmediately(); super.tearDown(); } } - public VirtualHostImpl getVirtualHost() - { - return _virtualHost; - } - protected void reloadVirtualHost() { - VirtualHostImpl original = getVirtualHost(); - - if (getVirtualHost() != null) - { - try - { - getVirtualHost().close(); - } - catch (Exception e) - { - _logger.error("Error closing virtual host", e); - fail(e.getMessage()); - } - } - - try - { - _virtualHost = (AbstractVirtualHost<?>) BrokerTestHelper.createVirtualHost(_attributes); - } - catch (Exception e) - { - _logger.error("Error creating virtual host", e); - fail(e.getMessage()); - } + assertEquals("Virtual host node is not active", State.ACTIVE, _virtualHost.getState()); + State currentState = _node.setDesiredState(State.ACTIVE, State.STOPPED); + assertEquals("Virtual host node is not stopped", State.STOPPED, currentState); - assertTrue("Virtualhost has not changed, reload was not successful", original != getVirtualHost()); + currentState = _node.setDesiredState(State.STOPPED, State.ACTIVE); + assertEquals("Virtual host node is not active", State.ACTIVE, currentState); + _virtualHost = (VirtualHostImpl<?, ?, ?>) _node.getVirtualHost(); } public void testQueueExchangeAndBindingCreation() throws Exception { - assertEquals("Should not be any existing queues", 0, getVirtualHost().getQueues().size()); + assertEquals("Should not be any existing queues", 0, _virtualHost.getQueues().size()); createAllQueues(); createAllTopicQueues(); @@ -229,7 +207,7 @@ public class VirtualHostMessageStoreTest extends QpidTestCase validateMessageOnTopics(2, true); assertEquals("Not all queues correctly registered", - 10, getVirtualHost().getQueues().size()); + 10, _virtualHost.getQueues().size()); } public void testMessagePersistence() throws Exception @@ -253,7 +231,7 @@ public class VirtualHostMessageStoreTest extends QpidTestCase testMessagePersistence(); assertEquals("Incorrect number of queues registered after recovery", - 6, getVirtualHost().getQueues().size()); + 6, _virtualHost.getQueues().size()); //clear the queue _virtualHost.getQueue(durableQueueName).clearQueue(); @@ -275,7 +253,7 @@ public class VirtualHostMessageStoreTest extends QpidTestCase public void testQueuePersistence() throws Exception { assertEquals("Should not be any existing queues", - 0, getVirtualHost().getQueues().size()); + 0, _virtualHost.getQueues().size()); //create durable and non durable queues/topics createAllQueues(); @@ -285,17 +263,17 @@ public class VirtualHostMessageStoreTest extends QpidTestCase reloadVirtualHost(); assertEquals("Incorrect number of queues registered after recovery", - 6, getVirtualHost().getQueues().size()); + 6, _virtualHost.getQueues().size()); //Validate the non-Durable Queues were not recovered. assertNull("Non-Durable queue still registered:" + priorityQueueName, - getVirtualHost().getQueue(priorityQueueName)); + _virtualHost.getQueue(priorityQueueName)); assertNull("Non-Durable queue still registered:" + queueName, - getVirtualHost().getQueue(queueName)); + _virtualHost.getQueue(queueName)); assertNull("Non-Durable queue still registered:" + priorityTopicQueueName, - getVirtualHost().getQueue(priorityTopicQueueName)); + _virtualHost.getQueue(priorityTopicQueueName)); assertNull("Non-Durable queue still registered:" + topicQueueName, - getVirtualHost().getQueue(topicQueueName)); + _virtualHost.getQueue(topicQueueName)); //Validate normally expected properties of Queues/Topics validateDurableQueueProperties(); @@ -316,23 +294,24 @@ public class VirtualHostMessageStoreTest extends QpidTestCase createQueue(durableQueueName, false, true, false, false); assertEquals("Incorrect number of queues registered before recovery", - 1, getVirtualHost().getQueues().size()); + 1, _virtualHost.getQueues().size()); reloadVirtualHost(); assertEquals("Incorrect number of queues registered after first recovery", - 1, getVirtualHost().getQueues().size()); + 1, _virtualHost.getQueues().size()); //test that removing the queue means it is not recovered next time - final AMQQueue<?> queue = getVirtualHost().getQueue(durableQueueName); - getVirtualHost().getDurableConfigurationStore().remove(queue.asObjectRecord()); + + final AMQQueue<?> queue = _virtualHost.getQueue(durableQueueName); + _virtualHost.getDurableConfigurationStore().remove(queue.asObjectRecord()); reloadVirtualHost(); assertEquals("Incorrect number of queues registered after second recovery", - 0, getVirtualHost().getQueues().size()); + 0, _virtualHost.getQueues().size()); assertNull("Durable queue was not removed:" + durableQueueName, - getVirtualHost().getQueue(durableQueueName)); + _virtualHost.getQueue(durableQueueName)); } /** @@ -342,12 +321,12 @@ public class VirtualHostMessageStoreTest extends QpidTestCase */ public void testExchangePersistence() throws Exception { - int origExchangeCount = getVirtualHost().getExchanges().size(); + int origExchangeCount = _virtualHost.getExchanges().size(); Map<String, ExchangeImpl<?>> oldExchanges = createExchanges(); assertEquals("Incorrect number of exchanges registered before recovery", - origExchangeCount + 3, getVirtualHost().getExchanges().size()); + origExchangeCount + 3, _virtualHost.getExchanges().size()); reloadVirtualHost(); @@ -362,28 +341,29 @@ public class VirtualHostMessageStoreTest extends QpidTestCase */ public void testDurableExchangeRemoval() throws Exception { - int origExchangeCount = getVirtualHost().getExchanges().size(); + int origExchangeCount = _virtualHost.getExchanges().size(); createExchange(DirectExchange.TYPE, directExchangeName, true); assertEquals("Incorrect number of exchanges registered before recovery", - origExchangeCount + 1, getVirtualHost().getExchanges().size()); + origExchangeCount + 1, _virtualHost.getExchanges().size()); reloadVirtualHost(); assertEquals("Incorrect number of exchanges registered after first recovery", - origExchangeCount + 1, getVirtualHost().getExchanges().size()); + origExchangeCount + 1, _virtualHost.getExchanges().size()); //test that removing the exchange means it is not recovered next time - final ExchangeImpl<?> exchange = getVirtualHost().getExchange(directExchangeName); - getVirtualHost().getDurableConfigurationStore().remove(exchange.asObjectRecord()); + + final ExchangeImpl<?> exchange = _virtualHost.getExchange(directExchangeName); + _virtualHost.getDurableConfigurationStore().remove(exchange.asObjectRecord()); reloadVirtualHost(); assertEquals("Incorrect number of exchanges registered after second recovery", - origExchangeCount, getVirtualHost().getExchanges().size()); + origExchangeCount, _virtualHost.getExchanges().size()); assertNull("Durable exchange was not removed:" + directExchangeName, - getVirtualHost().getExchange(directExchangeName)); + _virtualHost.getExchange(directExchangeName)); } /** @@ -394,7 +374,7 @@ public class VirtualHostMessageStoreTest extends QpidTestCase */ public void testBindingPersistence() throws Exception { - int origExchangeCount = getVirtualHost().getExchanges().size(); + int origExchangeCount = _virtualHost.getExchanges().size(); createAllQueues(); createAllTopicQueues(); @@ -410,7 +390,7 @@ public class VirtualHostMessageStoreTest extends QpidTestCase bindAllTopicQueuesToExchange(topicExchange, topicRouting); assertEquals("Incorrect number of exchanges registered before recovery", - origExchangeCount + 3, getVirtualHost().getExchanges().size()); + origExchangeCount + 3, _virtualHost.getExchanges().size()); reloadVirtualHost(); @@ -429,27 +409,27 @@ public class VirtualHostMessageStoreTest extends QpidTestCase //create durable queue and exchange, bind them ExchangeImpl<?> exch = createExchange(DirectExchange.TYPE, directExchangeName, true); createQueue(durableQueueName, false, true, false, false); - bindQueueToExchange(exch, directRouting, getVirtualHost().getQueue(durableQueueName), false); + bindQueueToExchange(exch, directRouting, _virtualHost.getQueue(durableQueueName), false); assertEquals("Incorrect number of bindings registered before recovery", - 1, getVirtualHost().getQueue(durableQueueName).getBindings().size()); + 1, _virtualHost.getQueue(durableQueueName).getBindings().size()); //verify binding is actually normally recovered reloadVirtualHost(); assertEquals("Incorrect number of bindings registered after first recovery", - 1, getVirtualHost().getQueue(durableQueueName).getBindings().size()); + 1, _virtualHost.getQueue(durableQueueName).getBindings().size()); - exch = getVirtualHost().getExchange(directExchangeName); + exch = _virtualHost.getExchange(directExchangeName); assertNotNull("Exchange was not recovered", exch); //remove the binding and verify result after recovery - unbindQueueFromExchange(exch, directRouting, getVirtualHost().getQueue(durableQueueName), false); + unbindQueueFromExchange(exch, directRouting, _virtualHost.getQueue(durableQueueName), false); reloadVirtualHost(); assertEquals("Incorrect number of bindings registered after second recovery", - 0, getVirtualHost().getQueue(durableQueueName).getBindings().size()); + 0, _virtualHost.getQueue(durableQueueName).getBindings().size()); } /** @@ -459,7 +439,7 @@ public class VirtualHostMessageStoreTest extends QpidTestCase */ private void validateExchanges(int originalNumExchanges, Map<String, ExchangeImpl<?>> oldExchanges) { - Collection<ExchangeImpl<?>> exchanges = getVirtualHost().getExchanges(); + Collection<ExchangeImpl<?>> exchanges = (Collection<ExchangeImpl<?>>) _virtualHost.getExchanges(); Collection<String> exchangeNames = new ArrayList<String>(exchanges.size()); for(ExchangeImpl<?> exchange : exchanges) { @@ -474,27 +454,26 @@ public class VirtualHostMessageStoreTest extends QpidTestCase //check the old exchange objects are not the same as the new exchanges assertTrue(directExchangeName + " exchange NOT reloaded", - getVirtualHost().getExchange(directExchangeName) != oldExchanges.get(directExchangeName)); + _virtualHost.getExchange(directExchangeName) != oldExchanges.get(directExchangeName)); assertTrue(topicExchangeName + " exchange NOT reloaded", - getVirtualHost().getExchange(topicExchangeName) != oldExchanges.get(topicExchangeName)); + _virtualHost.getExchange(topicExchangeName) != oldExchanges.get(topicExchangeName)); // There should only be the original exchanges + our 2 recovered durable exchanges assertEquals("Incorrect number of exchanges available", - originalNumExchanges + 2, getVirtualHost().getExchanges().size()); + originalNumExchanges + 2, _virtualHost.getExchanges().size()); } /** Validates the Durable queues and their properties are as expected following recovery */ - @SuppressWarnings("unchecked") private void validateBindingProperties() { - assertEquals("Incorrect number of (durable) queues following recovery", 6, getVirtualHost().getQueues().size()); + assertEquals("Incorrect number of (durable) queues following recovery", 6, _virtualHost.getQueues().size()); - validateBindingProperties(getVirtualHost().getQueue(durablePriorityQueueName).getBindings(), false); - validateBindingProperties(getVirtualHost().getQueue(durablePriorityTopicQueueName).getBindings(), true); - validateBindingProperties(getVirtualHost().getQueue(durableQueueName).getBindings(), false); - validateBindingProperties(getVirtualHost().getQueue(durableTopicQueueName).getBindings(), true); - validateBindingProperties(getVirtualHost().getQueue(durableExclusiveQueueName).getBindings(), false); + validateBindingProperties(_virtualHost.getQueue(durablePriorityQueueName).getBindings(), false); + validateBindingProperties(_virtualHost.getQueue(durablePriorityTopicQueueName).getBindings(), true); + validateBindingProperties(_virtualHost.getQueue(durableQueueName).getBindings(), false); + validateBindingProperties(_virtualHost.getQueue(durableTopicQueueName).getBindings(), true); + validateBindingProperties(_virtualHost.getQueue(durableExclusiveQueueName).getBindings(), false); } /** @@ -522,13 +501,13 @@ public class VirtualHostMessageStoreTest extends QpidTestCase private void setQueueExclusivity(boolean exclusive) throws MessageSource.ExistingConsumerPreventsExclusive { - AMQQueue<?> queue = getVirtualHost().getQueue(durableExclusiveQueueName); + AMQQueue<?> queue = _virtualHost.getQueue(durableExclusiveQueueName); queue.setAttribute(Queue.EXCLUSIVE, queue.getExclusive(), exclusive ? ExclusivityPolicy.CONTAINER : ExclusivityPolicy.NONE); } private void validateQueueExclusivityProperty(boolean expected) { - AMQQueue<?> queue = getVirtualHost().getQueue(durableExclusiveQueueName); + AMQQueue<?> queue = _virtualHost.getQueue(durableExclusiveQueueName); assertEquals("Queue exclusivity was incorrect", queue.isExclusive(), expected); } @@ -536,12 +515,12 @@ public class VirtualHostMessageStoreTest extends QpidTestCase private void validateDurableQueueProperties() { - validateQueueProperties(getVirtualHost().getQueue(durablePriorityQueueName), true, true, false, false); - validateQueueProperties(getVirtualHost().getQueue(durablePriorityTopicQueueName), true, true, false, false); - validateQueueProperties(getVirtualHost().getQueue(durableQueueName), false, true, false, false); - validateQueueProperties(getVirtualHost().getQueue(durableTopicQueueName), false, true, false, false); - validateQueueProperties(getVirtualHost().getQueue(durableExclusiveQueueName), false, true, true, false); - validateQueueProperties(getVirtualHost().getQueue(durableLastValueQueueName), false, true, true, true); + validateQueueProperties(_virtualHost.getQueue(durablePriorityQueueName), true, true, false, false); + validateQueueProperties(_virtualHost.getQueue(durablePriorityTopicQueueName), true, true, false, false); + validateQueueProperties(_virtualHost.getQueue(durableQueueName), false, true, false, false); + validateQueueProperties(_virtualHost.getQueue(durableTopicQueueName), false, true, false, false); + validateQueueProperties(_virtualHost.getQueue(durableExclusiveQueueName), false, true, true, false); + validateQueueProperties(_virtualHost.getQueue(durableLastValueQueueName), false, true, true, true); } private void validateQueueProperties(AMQQueue<?> queue, boolean usePriority, boolean durable, boolean exclusive, boolean lastValueQueue) @@ -600,13 +579,13 @@ public class VirtualHostMessageStoreTest extends QpidTestCase MessageMetaData mmd = new MessageMetaData(messageInfo, headerBody, System.currentTimeMillis()); - final StoredMessage<MessageMetaData> storedMessage = getVirtualHost().getMessageStore().addMessage(mmd); + final StoredMessage<MessageMetaData> storedMessage = _virtualHost.getMessageStore().addMessage(mmd); storedMessage.flushToStore(); final AMQMessage currentMessage = new AMQMessage(storedMessage); - ServerTransaction trans = new AutoCommitTransaction(getVirtualHost().getMessageStore()); + ServerTransaction trans = new AutoCommitTransaction(_virtualHost.getMessageStore()); exchange.send(currentMessage, routingKey, InstanceProperties.EMPTY, trans, null); } @@ -680,7 +659,7 @@ public class VirtualHostMessageStoreTest extends QpidTestCase AMQQueue<?> queue = null; //Ideally we would be able to use the QueueDeclareHandler here. - queue = getVirtualHost().createQueue(queueArguments); + queue = _virtualHost.createQueue(queueArguments); validateQueueProperties(queue, usePriority, durable, exclusive, lastValueQueue); } @@ -711,27 +690,27 @@ public class VirtualHostMessageStoreTest extends QpidTestCase attributes.put(org.apache.qpid.server.model.Exchange.LIFETIME_POLICY, durable ? LifetimePolicy.DELETE_ON_NO_LINKS : LifetimePolicy.PERMANENT); attributes.put(org.apache.qpid.server.model.Exchange.ALTERNATE_EXCHANGE, null); - exchange = getVirtualHost().createExchange(attributes); + exchange = _virtualHost.createExchange(attributes); return exchange; } private void bindAllQueuesToExchange(ExchangeImpl<?> exchange, String routingKey) { - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(durablePriorityQueueName), false); - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(durableQueueName), false); - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(priorityQueueName), false); - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(queueName), false); - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(durableExclusiveQueueName), false); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(durablePriorityQueueName), false); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(durableQueueName), false); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(priorityQueueName), false); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(queueName), false); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(durableExclusiveQueueName), false); } private void bindAllTopicQueuesToExchange(ExchangeImpl<?> exchange, String routingKey) { - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(durablePriorityTopicQueueName), true); - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(durableTopicQueueName), true); - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(priorityTopicQueueName), true); - bindQueueToExchange(exchange, routingKey, getVirtualHost().getQueue(topicQueueName), true); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(durablePriorityTopicQueueName), true); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(durableTopicQueueName), true); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(priorityTopicQueueName), true); + bindQueueToExchange(exchange, routingKey, _virtualHost.getQueue(topicQueueName), true); } @@ -805,7 +784,7 @@ public class VirtualHostMessageStoreTest extends QpidTestCase private void validateMessageOnQueue(String queueName, long messageCount) { - AMQQueue<?> queue = getVirtualHost().getQueue(queueName); + AMQQueue<?> queue = _virtualHost.getQueue(queueName); assertNotNull("Queue(" + queueName + ") not correctly registered:", queue); diff --git a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java index 6e4ea13cfc..4ea071f3ac 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/StatisticsTest.java @@ -53,8 +53,8 @@ public class StatisticsTest extends QpidBrokerTestCase @Override public void setUp() throws Exception { - createTestVirtualHost(0, TEST_VIRTUALHOST1); - createTestVirtualHost(0, TEST_VIRTUALHOST2); + createTestVirtualHostNode(0, TEST_VIRTUALHOST1); + createTestVirtualHostNode(0, TEST_VIRTUALHOST2); getBrokerConfiguration().addJmxManagementConfiguration(); diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java index 47a25dbbec..87a060766b 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java @@ -65,7 +65,7 @@ public class Asserts ConfiguredObject.CONTEXT, VirtualHost.SUPPORTED_QUEUE_TYPES, VirtualHost.TYPE, - VirtualHost.CONFIGURATION_STORE_SETTINGS, + VirtualHost.MESSAGE_STORE_SETTINGS, VirtualHost.SECURITY_ACL); assertEquals("Unexpected value of attribute " + VirtualHost.NAME, diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java index 6ba8df075b..ee7abd2424 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BindingRestTest.java @@ -48,25 +48,9 @@ public class BindingRestTest extends QpidRestTestCase } } - public void testGetVirtualHostBindings() throws Exception - { - List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test"); - assertNotNull("Bindings cannot be null", bindings); - assertEquals("Unexpected number of bindings", RestTestHelper.EXPECTED_QUEUES.length, bindings.size()); - for (String queueName : RestTestHelper.EXPECTED_QUEUES) - { - Map<String, Object> searchAttributes = new HashMap<String, Object>(); - searchAttributes.put(Binding.NAME, queueName); - searchAttributes.put(Binding.EXCHANGE, "amq.direct"); - - Map<String, Object> binding = getRestTestHelper().find(searchAttributes, bindings); - Asserts.assertBinding(queueName, "amq.direct", binding); - } - } - public void testGetVirtualHostExchangeBindings() throws Exception { - List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/test/amq.direct"); assertNotNull("Bindings cannot be null", bindings); assertEquals("Unexpected number of bindings", RestTestHelper.EXPECTED_QUEUES.length, bindings.size()); for (String queueName : RestTestHelper.EXPECTED_QUEUES) @@ -78,7 +62,7 @@ public class BindingRestTest extends QpidRestTestCase public void testGetVirtualHostExchangeQueueBindings() throws Exception { - List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue"); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/test/amq.direct/queue"); assertNotNull("Bindings cannot be null", bindings); assertEquals("Unexpected number of bindings", 1, bindings.size()); Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); @@ -87,25 +71,24 @@ public class BindingRestTest extends QpidRestTestCase public void testDeleteBinding() throws Exception { - List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + String bindingUrl = "/rest/binding/test/test/amq.direct/queue/queue"; + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList(bindingUrl); assertEquals("Unexpected number of bindings", 1, bindings.size()); Asserts.assertBinding("queue", "amq.direct", bindings.get(0)); - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/queue", "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); + int responseCode = getRestTestHelper().submitRequest(bindingUrl, "DELETE", null); + assertEquals("Unexpected response code", 200, responseCode); - bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue/queue"); + bindings = getRestTestHelper().getJsonAsList(bindingUrl); assertEquals("Binding should be deleted", 0, bindings.size()); } public void testDeleteBindingById() throws Exception { - Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue"); - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE"); - connection.connect(); - assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/queue"); + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/test/amq.direct/queue"); + int responseCode = getRestTestHelper().submitRequest("/rest/binding/test/test/amq.direct?id=" + binding.get(Binding.ID), "DELETE", null); + assertEquals("Unexpected response code", 200, responseCode); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/test/amq.direct/queue"); assertEquals("Binding should be deleted", 0, bindings.size()); } @@ -117,14 +100,12 @@ public class BindingRestTest extends QpidRestTestCase bindingData.put(Binding.QUEUE, "queue"); bindingData.put(Binding.EXCHANGE, "amq.direct"); - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT"); - connection.connect(); - getRestTestHelper().writeJsonRequest(connection, bindingData); - int responseCode = connection.getResponseCode(); - connection.disconnect(); + String bindingUrl = "/rest/binding/test/test/amq.direct/queue/" + bindingName; + + int responseCode = getRestTestHelper().submitRequest(bindingUrl, "PUT", bindingData); assertEquals("Unexpected response code", 201, responseCode); - Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList(bindingUrl); Asserts.assertBinding(bindingName, "queue", "amq.direct", binding); } @@ -136,16 +117,16 @@ public class BindingRestTest extends QpidRestTestCase attributes.put(Binding.QUEUE, "queue"); attributes.put(Binding.EXCHANGE, "amq.direct"); - int responseCode = getRestTestHelper().submitRequest("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT", attributes); + String bindingUrl = "/rest/binding/test/test/amq.direct/queue/" + bindingName; + int responseCode = getRestTestHelper().submitRequest(bindingUrl, "PUT", attributes); assertEquals("Unexpected response code", 201, responseCode); - Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList("/rest/binding/test/amq.direct/queue/" + bindingName); - + Map<String, Object> binding = getRestTestHelper().getJsonAsSingletonList(bindingUrl); Asserts.assertBinding(bindingName, "queue", "amq.direct", binding); - attributes.put(Binding.ARGUMENTS, null); + attributes.put(Binding.ARGUMENTS, "blah"); - responseCode = getRestTestHelper().submitRequest("/rest/binding/test/amq.direct/queue/" + bindingName, "PUT", attributes); + responseCode = getRestTestHelper().submitRequest(bindingUrl, "PUT", attributes); assertEquals("Update should be unsupported", 409, responseCode); } } diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java index 20005d4f47..b68c53739c 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestTest.java @@ -40,6 +40,7 @@ import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.test.client.UnroutableMessageTestExceptionListener; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -49,7 +50,7 @@ public class BrokerRestTest extends QpidRestTestCase { private static final String BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE = "authenticationproviders"; private static final String BROKER_PORTS_ATTRIBUTE = "ports"; - private static final String BROKER_VIRTUALHOSTS_ATTRIBUTE = "virtualhosts"; + private static final String BROKER_VIRTUALHOST_NODES_ATTRIBUTE = "virtualhostnodes"; private static final String BROKER_STATISTICS_ATTRIBUTE = "statistics"; public void testGet() throws Exception @@ -63,12 +64,14 @@ public class BrokerRestTest extends QpidRestTestCase Asserts.assertAttributesPresent(statistics, new String[]{ "bytesIn", "messagesOut", "bytesOut", "messagesIn" }); @SuppressWarnings("unchecked") - List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE); - assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size()); + List<Map<String, Object>> nodes = (List<Map<String, Object>>) brokerDetails.get(BROKER_VIRTUALHOST_NODES_ATTRIBUTE); + assertEquals("Unexpected number of virtual hosts", 3, nodes.size()); - Asserts.assertVirtualHost(TEST3_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST3_VIRTUALHOST, virtualhosts)); - Asserts.assertVirtualHost(TEST2_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST2_VIRTUALHOST, virtualhosts)); - Asserts.assertVirtualHost(TEST1_VIRTUALHOST, getRestTestHelper().find(VirtualHost.NAME, TEST1_VIRTUALHOST, virtualhosts)); + for (String nodeName: EXPECTED_VIRTUALHOSTS) + { + Map<String, Object> nodeAttributes = getRestTestHelper().find(VirtualHostNode.NAME, nodeName, nodes); + assertNotNull("Node attributes are not found for node with name " + nodeName, nodeAttributes); + } @SuppressWarnings("unchecked") List<Map<String, Object>> ports = (List<Map<String, Object>>) brokerDetails.get(BROKER_PORTS_ATTRIBUTE); @@ -227,7 +230,7 @@ public class BrokerRestTest extends QpidRestTestCase assertNotNull("Unexpected value of attribute " + Broker.ID, brokerDetails.get(Broker.ID)); assertNotNull("Unexpected value of attribute statistics", brokerDetails.get(BROKER_STATISTICS_ATTRIBUTE)); - assertNotNull("Unexpected value of attribute virtualhosts", brokerDetails.get(BROKER_VIRTUALHOSTS_ATTRIBUTE)); + assertNotNull("Unexpected value of attribute virtual host nodes", brokerDetails.get(BROKER_VIRTUALHOST_NODES_ATTRIBUTE)); assertNotNull("Unexpected value of attribute ports", brokerDetails.get(BROKER_PORTS_ATTRIBUTE)); assertNotNull("Unexpected value of attribute authenticationproviders", brokerDetails.get(BROKER_AUTHENTICATIONPROVIDERS_ATTRIBUTE)); diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java index f924dae56e..bf11ff9ae0 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/ConnectionRestTest.java @@ -98,7 +98,7 @@ public class ConnectionRestTest extends QpidRestTestCase public void testGetVirtualHostConnections() throws Exception { - List<Map<String, Object>> connections = getRestTestHelper().getJsonAsList("/rest/connection/test"); + List<Map<String, Object>> connections = getRestTestHelper().getJsonAsList("/rest/connection/test/test"); assertEquals("Unexpected number of connections", 1, connections.size()); Asserts.assertConnection(connections.get(0), (AMQConnection) _connection); } @@ -108,7 +108,7 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - Map<String, Object> connectionDetails = getRestTestHelper().getJsonAsSingletonList("/rest/connection/test/" + Map<String, Object> connectionDetails = getRestTestHelper().getJsonAsSingletonList("/rest/connection/test/test/" + URLDecoder.decode(connectionName, "UTF-8")); assertConnection(connectionDetails); } @@ -122,7 +122,7 @@ public class ConnectionRestTest extends QpidRestTestCase public void testGetVirtualHostSessions() throws Exception { - List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test"); + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/test"); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); } @@ -132,7 +132,7 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/" + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/test/" + URLDecoder.decode(connectionName, "UTF-8")); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); @@ -143,7 +143,7 @@ public class ConnectionRestTest extends QpidRestTestCase // get connection name String connectionName = getConnectionName(); - List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/" + List<Map<String, Object>> sessions = getRestTestHelper().getJsonAsList("/rest/session/test/test/" + URLDecoder.decode(connectionName, "UTF-8") + "/" + ((AMQSession<?, ?>) _session).getChannelId()); assertEquals("Unexpected number of sessions", 1, sessions.size()); assertSession(sessions.get(0), (AMQSession<?, ?>) _session); @@ -210,7 +210,7 @@ public class ConnectionRestTest extends QpidRestTestCase private String getConnectionName() throws IOException { - Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test/test"); @SuppressWarnings("unchecked") List<Map<String, Object>> connections = (List<Map<String, Object>>) hostDetails .get(VirtualHostRestTest.VIRTUALHOST_CONNECTIONS_ATTRIBUTE); diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java index 962c71583c..ef674fc95b 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/ExchangeRestTest.java @@ -64,7 +64,7 @@ public class ExchangeRestTest extends QpidRestTestCase { for (String exchangeName : EXPECTED_EXCHANGES) { - Map<String, Object> exchange = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + Map<String, Object> exchange = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/test/" + URLDecoder.decode(exchangeName, "UTF-8")); assertExchange(exchangeName, exchange); } @@ -73,20 +73,22 @@ public class ExchangeRestTest extends QpidRestTestCase public void testSetExchangeAttributesUnsupported() throws Exception { String exchangeName = getTestName(); + String exchangeUrl = "/rest/exchange/test/test/" + exchangeName; Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Exchange.NAME, exchangeName); attributes.put(Exchange.TYPE, "direct"); - int responseCode =getRestTestHelper().submitRequest("/rest/exchange/test/" + exchangeName, "PUT", attributes); + int responseCode = getRestTestHelper().submitRequest(exchangeUrl, "PUT", attributes); + assertEquals("Exchange should be created", 201, responseCode); - Map<String, Object> exchange = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); + Map<String, Object> exchange = getRestTestHelper().getJsonAsSingletonList(exchangeUrl); assertNotNull("Exchange not found", exchange); attributes = new HashMap<String, Object>(); attributes.put(Exchange.NAME, exchangeName); - attributes.put(Exchange.ALTERNATE_EXCHANGE, "my-alternate-exchange"); + attributes.put(Exchange.ALTERNATE_EXCHANGE, "amq.direct"); - responseCode = getRestTestHelper().submitRequest("/rest/exchange/test/" + exchangeName, "PUT", attributes); + responseCode = getRestTestHelper().submitRequest(exchangeUrl, "PUT", attributes); assertEquals("Exchange update should be unsupported", 409, responseCode); } diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java index c0be10931c..1a8fe9d930 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java @@ -29,6 +29,7 @@ import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; @@ -54,12 +55,12 @@ public class QpidRestTestCase extends QpidBrokerTestCase getRestTestHelper().setUsernameAndPassword("webadmin", "webadmin"); //remove the normal 'test' vhost, we will configure the vhosts below - getBrokerConfiguration(0).removeObjectConfiguration(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + getBrokerConfiguration(0).removeObjectConfiguration(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); // Set up virtualhost config with queues and bindings to the amq.direct for (String virtualhost : EXPECTED_VIRTUALHOSTS) { - createTestVirtualHost(0, virtualhost); + createTestVirtualHostNode(0, virtualhost); } customizeConfiguration(); diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java index 8c8db3b358..70cc6414cd 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/QueueRestTest.java @@ -104,7 +104,7 @@ public class QueueRestTest extends QpidRestTestCase public void testGetByName() throws Exception { String queueName = getTestQueueName(); - Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/test/" + queueName); Asserts.assertQueue(queueName, "standard", queueDetails); assertStatistics(queueDetails); @@ -130,9 +130,11 @@ public class QueueRestTest extends QpidRestTestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(Queue.NAME, queueName); - int responseCode = getRestTestHelper().submitRequest("/rest/queue/test/" + queueName, "PUT", attributes); + String queueUrl = "/rest/queue/test/test/" + queueName; + int responseCode = getRestTestHelper().submitRequest(queueUrl, "PUT", attributes); + assertEquals("Queue was not created", 201, responseCode); - Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList(queueUrl); Asserts.assertQueue(queueName, "standard", queueDetails); attributes = new HashMap<String, Object>(); @@ -146,10 +148,10 @@ public class QueueRestTest extends QpidRestTestCase attributes.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, 50000); attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 10); - responseCode = getRestTestHelper().submitRequest("/rest/queue/test/" + queueName, "PUT", attributes); + responseCode = getRestTestHelper().submitRequest(queueUrl, "PUT", attributes); assertEquals("Setting of queue attributes should be allowed", 200, responseCode); - Map<String, Object> queueData = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueData = getRestTestHelper().getJsonAsSingletonList(queueUrl); assertEquals("Unexpected " + Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 100000, queueData.get(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES) ); assertEquals("Unexpected " + Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 80000, queueData.get(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES) ); assertEquals("Unexpected " + Queue.ALERT_REPEAT_GAP, 10000, queueData.get(Queue.ALERT_REPEAT_GAP) ); @@ -170,7 +172,7 @@ public class QueueRestTest extends QpidRestTestCase createBinding(bindingName, exchanges[i], queueName); } - Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/test/" + queueName); Asserts.assertQueue(queueName, "standard", queueDetails); @SuppressWarnings("unchecked") @@ -192,7 +194,7 @@ public class QueueRestTest extends QpidRestTestCase private void createBinding(String bindingName, String exchangeName, String queueName) throws IOException { HttpURLConnection connection = getRestTestHelper().openManagementConnection( - "/rest/binding/test/" + URLDecoder.decode(exchangeName, "UTF-8") + "/" + queueName + "/" + bindingName, + "/rest/binding/test/test/" + URLDecoder.decode(exchangeName, "UTF-8") + "/" + queueName + "/" + bindingName, "PUT"); Map<String, Object> bindingData = new HashMap<String, Object>(); diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java index 4dc4001c4b..9a5d833d01 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java @@ -526,13 +526,15 @@ String dataAsString = new String(data); Map<String, Object> queueData = new HashMap<String, Object>(); queueData.put(Queue.NAME, queueName); queueData.put(Queue.DURABLE, Boolean.FALSE); - submitRequest("/rest/queue/test/" + queueName, "PUT", queueData); + int responseCode = submitRequest("/rest/queue/test/test/" + queueName, "PUT", queueData); + Assert.assertEquals("Unexpected response code creating queue" + queueName, 201, responseCode); Map<String, Object> bindingData = new HashMap<String, Object>(); bindingData.put(Binding.NAME, queueName); bindingData.put(Binding.QUEUE, queueName); bindingData.put(Binding.EXCHANGE, "amq.direct"); - submitRequest("/rest/binding/test/amq.direct/" + queueName + "/" + queueName, "PUT", queueData); + responseCode = submitRequest("/rest/binding/test/test/amq.direct/" + queueName + "/" + queueName, "PUT", queueData); + Assert.assertEquals("Unexpected response code binding queue " + queueName, 201, responseCode); } } } diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java index cf551ae315..adc9790f36 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java @@ -44,8 +44,8 @@ public class StructureRestTest extends QpidRestTestCase assertNode(structure, "Broker"); @SuppressWarnings("unchecked") - List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) structure.get("virtualhosts"); - assertEquals("Unexpected number of virtual hosts", 3, virtualhosts.size()); + List<Map<String, Object>> virtualhostnodes = (List<Map<String, Object>>) structure.get("virtualhostnodes"); + assertEquals("Unexpected number of virtual hosts", 3, virtualhostnodes.size()); @SuppressWarnings("unchecked") List<Map<String, Object>> ports = (List<Map<String, Object>>) structure.get("ports"); @@ -55,16 +55,20 @@ public class StructureRestTest extends QpidRestTestCase List<Map<String, Object>> providers = (List<Map<String, Object>>) structure.get("authenticationproviders"); assertEquals("Unexpected number of authentication providers", 2, providers.size()); - for (String hostName : EXPECTED_VIRTUALHOSTS) + for (String nodeName : EXPECTED_VIRTUALHOSTS) { - Map<String, Object> host = getRestTestHelper().find("name", hostName, virtualhosts); - assertNotNull("Host " + hostName + " is not found ", host); - assertNode(host, hostName); + Map<String, Object> node = getRestTestHelper().find("name", nodeName, virtualhostnodes); + assertNotNull("Node " + nodeName + " is not found ", node); + assertNode(node, nodeName); } String hostName = "test"; - Map<String, Object> host = getRestTestHelper().find("name", hostName, virtualhosts); + Map<String, Object> node = getRestTestHelper().find("name", hostName, virtualhostnodes); + + @SuppressWarnings("unchecked") + List<Map<String, Object>> virtualhosts = (List<Map<String, Object>>) node.get("virtualhosts"); + Map<String, Object> host = getRestTestHelper().find("name", hostName, virtualhosts); @SuppressWarnings("unchecked") List<Map<String, Object>> queues = (List<Map<String, Object>>) host.get("queues"); assertNotNull("Host " + hostName + " queues are not found ", queues); diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java index f336c7fc77..4bd1a19fe2 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java @@ -30,9 +30,6 @@ import java.util.Map; import javax.jms.Session; import javax.servlet.http.HttpServletResponse; -import org.codehaus.jackson.JsonGenerationException; -import org.codehaus.jackson.map.JsonMappingException; - import org.apache.qpid.client.AMQConnection; import org.apache.qpid.server.model.Exchange; import org.apache.qpid.server.model.Queue; @@ -40,10 +37,13 @@ import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.queue.LastValueQueue; import org.apache.qpid.server.queue.PriorityQueue; import org.apache.qpid.server.queue.SortedQueue; -import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.virtualhost.AbstractVirtualHost; -import org.apache.qpid.server.virtualhost.StandardVirtualHost; + +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.util.FileUtils; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.map.JsonMappingException; public class VirtualHostRestTest extends QpidRestTestCase { @@ -55,7 +55,7 @@ public class VirtualHostRestTest extends QpidRestTestCase public void testGet() throws Exception { - List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/"); + List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost"); assertNotNull("Hosts data cannot be null", hosts); assertEquals("Unexpected number of hosts", EXPECTED_VIRTUALHOSTS.length, hosts.size()); for (String hostName : EXPECTED_VIRTUALHOSTS) @@ -108,7 +108,7 @@ public class VirtualHostRestTest extends QpidRestTestCase public void testPutCreateVirtualHostUsingStoreType() throws Exception { String hostName = getTestName(); - String storeType = getTestProfileMessageStoreType(); + String storeType = getTestProfileVirtualHostNodeType(); String storeLocation = createHost(hostName, storeType, null); try { @@ -117,10 +117,6 @@ public class VirtualHostRestTest extends QpidRestTestCase Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostName); Asserts.assertVirtualHost(hostName, hostDetails); - @SuppressWarnings("unchecked") - Map<String, Object> messageStoreSettings = (Map<String, Object>) hostDetails.get(VirtualHost.MESSAGE_STORE_SETTINGS); - assertEquals("Unexpected store type", storeType, messageStoreSettings.get(MessageStore.STORE_TYPE)); - assertNewVirtualHost(hostDetails); } finally @@ -135,13 +131,10 @@ public class VirtualHostRestTest extends QpidRestTestCase public void testDeleteHost() throws Exception { String hostToDelete = TEST3_VIRTUALHOST; - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/virtualhost/" + hostToDelete, "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/virtualhost/" + hostToDelete + "/" + hostToDelete, "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - // make sure that changes are saved in the broker store - restartBroker(); - List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/" + hostToDelete); assertEquals("Host should be deleted", 0, hosts.size()); } @@ -161,32 +154,22 @@ public class VirtualHostRestTest extends QpidRestTestCase public void testUpdateActiveHostFails() throws Exception { String hostToUpdate = TEST3_VIRTUALHOST; - Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate); + String restHostUrl = "/rest/virtualhost/" + hostToUpdate + "/" + hostToUpdate; + Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList(restHostUrl); Asserts.assertVirtualHost(hostToUpdate, hostDetails); - @SuppressWarnings("unchecked") - Map<String, Object> attributes = (Map<String, Object>)hostDetails.get(VirtualHost.MESSAGE_STORE_SETTINGS); - String configPath = (String) attributes.get(MessageStore.STORE_PATH); - - String storeType = getTestProfileMessageStoreType(); - String storeLocation = getStoreLocation(hostToUpdate); - Map<String, Object> newMessageStoreSettings = new HashMap<String, Object>(); - newMessageStoreSettings.put(MessageStore.STORE_TYPE, storeType); - newMessageStoreSettings.put(MessageStore.STORE_PATH, storeLocation); Map<String, Object> newAttributes = new HashMap<String, Object>(); newAttributes.put(VirtualHost.NAME, hostToUpdate); - newAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, newMessageStoreSettings); + newAttributes.put("fakeAttribute", "value"); - int response = getRestTestHelper().submitRequest("/rest/virtualhost/" + hostToUpdate, "PUT", newAttributes); + int response = getRestTestHelper().submitRequest(restHostUrl, "PUT", newAttributes); assertEquals("Unexpected response code", 409, response); restartBroker(); - Map<String, Object> rereadHostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/" + hostToUpdate); + Map<String, Object> rereadHostDetails = getRestTestHelper().getJsonAsSingletonList(restHostUrl); Asserts.assertVirtualHost(hostToUpdate, rereadHostDetails); - @SuppressWarnings("unchecked") - Map<String, Object> rereadMessageStoreSettings = (Map<String,Object>)rereadHostDetails.get(VirtualHost.MESSAGE_STORE_SETTINGS); - assertEquals("Unexpected config path", configPath, rereadMessageStoreSettings.get(MessageStore.STORE_PATH)); + assertFalse(rereadHostDetails.containsKey("fakeAttribute")); } public void testPutCreateQueue() throws Exception @@ -342,10 +325,14 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName(); createQueue(queueName, null, null); - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "DELETE"); + String queueUrl = "/rest/queue/test/test/" + queueName; + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList(queueUrl); + assertEquals("Queue should exist", 1, queues.size()); + + HttpURLConnection connection = getRestTestHelper().openManagementConnection(queueUrl, "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); + queues = getRestTestHelper().getJsonAsList(queueUrl); assertEquals("Queue should be deleted", 0, queues.size()); } @@ -353,12 +340,12 @@ public class VirtualHostRestTest extends QpidRestTestCase { String queueName = getTestQueueName(); createQueue(queueName, null, null); - Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueDetails = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/test/" + queueName); - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test?id=" + queueDetails.get(Queue.ID), "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/test?id=" + queueDetails.get(Queue.ID), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/test/" + queueName); assertEquals("Queue should be deleted", 0, queues.size()); } @@ -367,10 +354,10 @@ public class VirtualHostRestTest extends QpidRestTestCase String exchangeName = getTestName(); createExchange(exchangeName, "direct"); - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/test/" + exchangeName, "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/test/" + exchangeName); assertEquals("Exchange should be deleted", 0, queues.size()); } @@ -378,12 +365,12 @@ public class VirtualHostRestTest extends QpidRestTestCase { String exchangeName = getTestName(); createExchange(exchangeName, "direct"); - Map<String, Object> echangeDetails = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/" + exchangeName); + Map<String, Object> echangeDetails = getRestTestHelper().getJsonAsSingletonList("/rest/exchange/test/test/" + exchangeName); - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/test?id=" + echangeDetails.get(Exchange.ID), "DELETE"); connection.connect(); assertEquals("Unexpected response code", 200, connection.getResponseCode()); - List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/exchange/test/test/" + exchangeName); assertEquals("Exchange should be deleted", 0, queues.size()); } @@ -479,7 +466,7 @@ public class VirtualHostRestTest extends QpidRestTestCase private void createExchange(String exchangeName, String exchangeType) throws IOException { - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/" + exchangeName, "PUT"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/exchange/test/test/" + exchangeName, "PUT"); Map<String, Object> queueData = new HashMap<String, Object>(); queueData.put(Exchange.NAME, exchangeName); @@ -502,7 +489,7 @@ public class VirtualHostRestTest extends QpidRestTestCase private int tryCreateQueue(String queueName, String queueType, Map<String, Object> attributes) throws IOException, JsonGenerationException, JsonMappingException { - HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/" + queueName, "PUT"); + HttpURLConnection connection = getRestTestHelper().openManagementConnection("/rest/queue/test/test/" + queueName, "PUT"); Map<String, Object> queueData = new HashMap<String, Object>(); queueData.put(Queue.NAME, queueName); @@ -536,20 +523,17 @@ public class VirtualHostRestTest extends QpidRestTestCase return new File(TMP_FOLDER, "store-" + hostName + "-" + System.currentTimeMillis()).getAbsolutePath(); } - private int tryCreateVirtualHost(String hostName, String storeType, String storePath, String configPath) throws IOException, + private int tryCreateVirtualHost(String hostName, String virtualHostNodeType, String storePath, String configPath) throws IOException, JsonGenerationException, JsonMappingException { - Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); - messageStoreSettings.put(MessageStore.STORE_PATH, storePath); - messageStoreSettings.put(MessageStore.STORE_TYPE, storeType); - Map<String, Object> hostData = new HashMap<String, Object>(); - hostData.put(VirtualHost.NAME, hostName); - hostData.put(VirtualHost.TYPE, StandardVirtualHost.TYPE); - hostData.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); + hostData.put(VirtualHostNode.NAME, hostName); + hostData.put(VirtualHostNode.TYPE, virtualHostNodeType); + hostData.put(VirtualHostNode.IS_MESSAGE_STORE_PROVIDER, true); + hostData.put(DurableConfigurationStore.STORE_PATH, storePath); - return getRestTestHelper().submitRequest("/rest/virtualhost/" + hostName, "PUT", hostData); + return getRestTestHelper().submitRequest("/rest/virtualhostnode/" + hostName, "PUT", hostData); } private void assertNewVirtualHost(Map<String, Object> hostDetails) diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java index 541160cd80..2575fb7e43 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java @@ -29,7 +29,6 @@ import java.util.Map; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.map.JsonMappingException; - import org.apache.qpid.server.management.plugin.HttpManagement; import org.apache.qpid.server.model.AccessControlProvider; import org.apache.qpid.server.model.AuthenticationProvider; @@ -40,17 +39,16 @@ import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.TrustStore; -import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.adapter.FileBasedGroupProvider; import org.apache.qpid.server.model.adapter.FileBasedGroupProviderImpl; import org.apache.qpid.server.security.FileKeyStore; import org.apache.qpid.server.security.FileTrustStore; +import org.apache.qpid.server.model.VirtualHostNode; import org.apache.qpid.server.security.access.FileAccessControlProviderConstants; import org.apache.qpid.server.security.acl.AbstractACLTestCase; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.virtualhost.StandardVirtualHost; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.systest.rest.QpidRestTestCase; import org.apache.qpid.test.utils.TestBrokerConfiguration; import org.apache.qpid.test.utils.TestFileUtils; @@ -192,56 +190,56 @@ public class BrokerACLTest extends QpidRestTestCase provider.get(PlainPasswordFileAuthenticationManagerFactory.ATTRIBUTE_PATH)); } - /* === VirtualHost === */ + /* === VirtualHostNode === */ - public void testCreateVirtualHostAllowed() throws Exception + public void testCreateVirtualHostNodeAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); String hostName = getTestName(); - int responseCode = createHost(hostName); + int responseCode = createVirtualHostNode(hostName); assertEquals("Host creation should be allowed", 201, responseCode); - assertVirtualHostExists(hostName); + assertVirtualHostNodeExists(hostName); } - public void testCreateVirtualHostDenied() throws Exception + public void testCreateVirtualHostNodeDenied() throws Exception { getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); String hostName = getTestName(); - int responseCode = createHost(hostName); - assertEquals("Host creation should be denied", 403, responseCode); + int responseCode = createVirtualHostNode(hostName); + assertEquals("Virtual host node creation should be denied", 403, responseCode); - assertVirtualHostDoesNotExist(hostName); + assertVirtualHostNodeDoesNotExist(hostName); } - public void testDeleteVirtualHostAllowed() throws Exception + public void testDeleteVirtualHostNodeAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - assertVirtualHostExists(TEST2_VIRTUALHOST); + assertVirtualHostNodeExists(TEST2_VIRTUALHOST); - int responseCode = getRestTestHelper().submitRequest("/rest/virtualhost/" + TEST2_VIRTUALHOST, "DELETE", null); - assertEquals("Host deletion should be allowed", 200, responseCode); + int responseCode = getRestTestHelper().submitRequest("/rest/virtualhostnode/" + TEST2_VIRTUALHOST, "DELETE", null); + assertEquals("Virtual host node deletion should be allowed", 200, responseCode); - assertVirtualHostDoesNotExist(TEST2_VIRTUALHOST); + assertVirtualHostNodeDoesNotExist(TEST2_VIRTUALHOST); } - public void testDeleteVirtualHostDenied() throws Exception + public void testDeleteVirtualHostNodeDenied() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - assertVirtualHostExists(TEST2_VIRTUALHOST); + assertVirtualHostNodeExists(TEST2_VIRTUALHOST); getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); - int responseCode = getRestTestHelper().submitRequest("/rest/virtualhost/" + TEST2_VIRTUALHOST, "DELETE", null); - assertEquals("Host deletion should be denied", 403, responseCode); + int responseCode = getRestTestHelper().submitRequest("/rest/virtualhostnode/" + TEST2_VIRTUALHOST, "DELETE", null); + assertEquals("Virtual host node deletion should be denied", 403, responseCode); - assertVirtualHostExists(TEST2_VIRTUALHOST); + assertVirtualHostNodeExists(TEST2_VIRTUALHOST); } /* === Port === */ @@ -979,34 +977,30 @@ public class BrokerACLTest extends QpidRestTestCase assertEquals("Unexpected result", exists, !trustStores.isEmpty()); } - private int createHost(String hostName) throws Exception + private int createVirtualHostNode(String virtualHostNodeName) throws Exception { - Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); - messageStoreSettings.put(MessageStore.STORE_PATH, getStoreLocation(hostName)); - messageStoreSettings.put(MessageStore.STORE_TYPE, getTestProfileMessageStoreType()); - - Map<String, Object> hostData = new HashMap<String, Object>(); - hostData.put(VirtualHost.NAME, hostName); - hostData.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); - hostData.put(VirtualHost.TYPE, StandardVirtualHost.TYPE); + Map<String, Object> data = new HashMap<String, Object>(); + data.put(VirtualHostNode.NAME, virtualHostNodeName); + data.put(VirtualHostNode.TYPE, getTestProfileVirtualHostNodeType()); + data.put(DurableConfigurationStore.STORE_PATH, getStoreLocation(virtualHostNodeName)); - return getRestTestHelper().submitRequest("/rest/virtualhost/" + hostName, "PUT", hostData); + return getRestTestHelper().submitRequest("/rest/virtualhostnode/" + virtualHostNodeName, "PUT", data); } - private void assertVirtualHostDoesNotExist(String hostName) throws Exception + private void assertVirtualHostNodeDoesNotExist(String name) throws Exception { - assertVirtualHostExistence(hostName, false); + assertVirtualHostNodeExistence(name, false); } - private void assertVirtualHostExists(String hostName) throws Exception + private void assertVirtualHostNodeExists(String name) throws Exception { - assertVirtualHostExistence(hostName, true); + assertVirtualHostNodeExistence(name, true); } - private void assertVirtualHostExistence(String hostName, boolean exists) throws Exception + private void assertVirtualHostNodeExistence(String name, boolean exists) throws Exception { - List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhost/" + hostName); - assertEquals("Unexpected result", exists, !hosts.isEmpty()); + List<Map<String, Object>> hosts = getRestTestHelper().getJsonAsList("/rest/virtualhostnode/" + name); + assertEquals("Node " + name + (exists ? " does not exist" : " exists" ), exists, !hosts.isEmpty()); } private String getStoreLocation(String hostName) diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java index 2eaaf7d988..0854befc0a 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/ExchangeRestACLTest.java @@ -41,6 +41,8 @@ public class ExchangeRestACLTest extends QpidRestTestCase private static final String ALLOWED_USER = "user1"; private static final String DENIED_USER = "user2"; private String _queueName; + private String _exchangeName; + private String _exchangeUrl; @Override protected void customizeConfiguration() throws IOException @@ -75,85 +77,78 @@ public class ExchangeRestACLTest extends QpidRestTestCase Map<String, Object> queueData = new HashMap<String, Object>(); queueData.put(Queue.NAME, _queueName); queueData.put(Queue.DURABLE, Boolean.TRUE); - int status = getRestTestHelper().submitRequest("/rest/queue/test/" + _queueName, "PUT", queueData); + int status = getRestTestHelper().submitRequest("/rest/queue/test/test/" + _queueName, "PUT", queueData); assertEquals("Unexpected status", 201, status); + _exchangeName = getTestName(); + _exchangeUrl = "/rest/exchange/test/test/" + _exchangeName; } public void testCreateExchangeAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String exchangeName = getTestName(); - - int responseCode = createExchange(exchangeName); + int responseCode = createExchange(); assertEquals("Exchange creation should be allowed", 201, responseCode); - assertExchangeExists(exchangeName); + assertExchangeExists(); } public void testCreateExchangeDenied() throws Exception { getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); - String exchangeName = getTestName(); - - int responseCode = createExchange(exchangeName); + int responseCode = createExchange(); assertEquals("Exchange creation should be denied", 403, responseCode); - assertExchangeDoesNotExist(exchangeName); + assertExchangeDoesNotExist(); } public void testDeleteExchangeAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String exchangeName = getTestName(); - - int responseCode = createExchange(exchangeName); + int responseCode = createExchange(); assertEquals("Exchange creation should be allowed", 201, responseCode); - assertExchangeExists(exchangeName); + assertExchangeExists(); + - responseCode = getRestTestHelper().submitRequest("/rest/exchange/test/" + exchangeName, "DELETE", null); + responseCode = getRestTestHelper().submitRequest(_exchangeUrl, "DELETE", null); assertEquals("Exchange deletion should be allowed", 200, responseCode); - assertExchangeDoesNotExist(TEST2_VIRTUALHOST); + assertExchangeDoesNotExist(); } public void testDeleteExchangeDenied() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String exchangeName = getTestName(); - - int responseCode = createExchange(exchangeName); + int responseCode = createExchange(); assertEquals("Exchange creation should be allowed", 201, responseCode); - assertExchangeExists(exchangeName); + assertExchangeExists(); getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); - responseCode = getRestTestHelper().submitRequest("/rest/exchange/test/" + exchangeName, "DELETE", null); + responseCode = getRestTestHelper().submitRequest(_exchangeUrl, "DELETE", null); assertEquals("Exchange deletion should be denied", 403, responseCode); - assertExchangeExists(exchangeName); + assertExchangeExists(); } public void testSetExchangeAttributesAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String exchangeName = getTestName(); - - int responseCode = createExchange(exchangeName); + int responseCode = createExchange(); - assertExchangeExists(exchangeName); + assertExchangeExists(); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(Exchange.NAME, exchangeName); + attributes.put(Exchange.NAME, _exchangeName); attributes.put(Exchange.ALTERNATE_EXCHANGE, "my-alternate-exchange"); - responseCode = getRestTestHelper().submitRequest("/rest/exchange/test/" + exchangeName, "PUT", attributes); + responseCode = getRestTestHelper().submitRequest(_exchangeUrl, "PUT", attributes); assertEquals("Setting of exchange attribites should be allowed but it is currently unsupported", 409, responseCode); } @@ -161,18 +156,16 @@ public class ExchangeRestACLTest extends QpidRestTestCase { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String exchangeName = getTestName(); - - int responseCode = createExchange(exchangeName); - assertExchangeExists(exchangeName); + int responseCode = createExchange(); + assertExchangeExists(); getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(Exchange.NAME, exchangeName); + attributes.put(Exchange.NAME, _exchangeName); attributes.put(Exchange.ALTERNATE_EXCHANGE, "my-alternate-exchange"); - responseCode = getRestTestHelper().submitRequest("/rest/exchange/test/" + exchangeName, "PUT", attributes); + responseCode = getRestTestHelper().submitRequest(_exchangeUrl, "PUT", attributes); assertEquals("Setting of exchange attribites should be allowed", 403, responseCode); } @@ -198,27 +191,27 @@ public class ExchangeRestACLTest extends QpidRestTestCase assertBindingDoesNotExist(bindingName); } - private int createExchange(String exchangeName) throws Exception + private int createExchange() throws Exception { Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(Exchange.NAME, exchangeName); + attributes.put(Exchange.NAME, _exchangeName); attributes.put(Exchange.TYPE, "direct"); - return getRestTestHelper().submitRequest("/rest/exchange/test/" + exchangeName, "PUT", attributes); + return getRestTestHelper().submitRequest(_exchangeUrl, "PUT", attributes); } - private void assertExchangeDoesNotExist(String exchangeName) throws Exception + private void assertExchangeDoesNotExist() throws Exception { - assertExchangeExistence(exchangeName, false); + assertExchangeExistence(false); } - private void assertExchangeExists(String exchangeName) throws Exception + private void assertExchangeExists() throws Exception { - assertExchangeExistence(exchangeName, true); + assertExchangeExistence(true); } - private void assertExchangeExistence(String exchangeName, boolean exists) throws Exception + private void assertExchangeExistence(boolean exists) throws Exception { - List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList("/rest/exchange/test/" + exchangeName); + List<Map<String, Object>> exchanges = getRestTestHelper().getJsonAsList(_exchangeUrl); assertEquals("Unexpected result", exists, !exchanges.isEmpty()); } @@ -229,7 +222,7 @@ public class ExchangeRestACLTest extends QpidRestTestCase attributes.put(Binding.QUEUE, _queueName); attributes.put(Binding.EXCHANGE, "amq.direct"); - int responseCode = getRestTestHelper().submitRequest("/rest/binding/test/amq.direct/" + _queueName + "/" + bindingName, "PUT", attributes); + int responseCode = getRestTestHelper().submitRequest("/rest/binding/test/test/amq.direct/" + _queueName + "/" + bindingName, "PUT", attributes); return responseCode; } @@ -245,7 +238,7 @@ public class ExchangeRestACLTest extends QpidRestTestCase private void assertBindingExistence(String bindingName, boolean exists) throws Exception { - List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/amq.direct/" + _queueName + "/" + bindingName); + List<Map<String, Object>> bindings = getRestTestHelper().getJsonAsList("/rest/binding/test/test/amq.direct/" + _queueName + "/" + bindingName); assertEquals("Unexpected result", exists, !bindings.isEmpty()); } } diff --git a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java index dced81277e..8acf4ee762 100644 --- a/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java +++ b/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/QueueRestACLTest.java @@ -36,6 +36,16 @@ public class QueueRestACLTest extends QpidRestTestCase { private static final String ALLOWED_USER = "user1"; private static final String DENIED_USER = "user2"; + private String _queueUrl; + private String _queueName; + + @Override + public void setUp() throws Exception + { + super.setUp(); + _queueName = getTestName(); + _queueUrl = "/rest/queue/test/test/" + _queueName; + } @Override protected void customizeConfiguration() throws IOException @@ -60,80 +70,72 @@ public class QueueRestACLTest extends QpidRestTestCase { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String queueName = getTestName(); - - int responseCode = createQueue(queueName); + int responseCode = createQueue(); assertEquals("Queue creation should be allowed", 201, responseCode); - assertQueueExists(queueName); + assertQueueExists(); } public void testCreateQueueDenied() throws Exception { getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); - String queueName = getTestName(); - - int responseCode = createQueue(queueName); + int responseCode = createQueue(); assertEquals("Queue creation should be denied", 403, responseCode); - assertQueueDoesNotExist(queueName); + assertQueueDoesNotExist(); } public void testDeleteQueueAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String queueName = getTestName(); - - int responseCode = createQueue(queueName); + int responseCode = createQueue(); assertEquals("Queue creation should be allowed", 201, responseCode); - assertQueueExists(queueName); + assertQueueExists(); - responseCode = getRestTestHelper().submitRequest("/rest/queue/test/" + queueName, "DELETE", null); + responseCode = getRestTestHelper().submitRequest(_queueUrl, "DELETE", null); assertEquals("Queue deletion should be allowed", 200, responseCode); - assertQueueDoesNotExist(TEST2_VIRTUALHOST); + assertQueueDoesNotExist(); } public void testDeleteQueueDenied() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String queueName = getTestName(); - - int responseCode = createQueue(queueName); + int responseCode = createQueue(); assertEquals("Queue creation should be allowed", 201, responseCode); - assertQueueExists(queueName); + assertQueueExists(); getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); - responseCode = getRestTestHelper().submitRequest("/rest/queue/test/" + queueName, "DELETE", null); + responseCode = getRestTestHelper().submitRequest(_queueUrl, "DELETE", null); assertEquals("Queue deletion should be denied", 403, responseCode); - assertQueueExists(queueName); + assertQueueExists(); } + + public void testSetQueueAttributesAllowed() throws Exception { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String queueName = getTestName(); - - int responseCode = createQueue(queueName); + int responseCode = createQueue(); - assertQueueExists(queueName); + assertQueueExists(); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(Queue.NAME, queueName); + attributes.put(Queue.NAME, _queueName); attributes.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 100000); attributes.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 80000); - responseCode = getRestTestHelper().submitRequest("/rest/queue/test/" + queueName, "PUT", attributes); + responseCode = getRestTestHelper().submitRequest(_queueUrl, "PUT", attributes); assertEquals("Setting of queue attribites should be allowed", 200, responseCode); - Map<String, Object> queueData = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueData = getRestTestHelper().getJsonAsSingletonList(_queueUrl); assertEquals("Unexpected " + Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 100000, queueData.get(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES) ); assertEquals("Unexpected " + Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 80000, queueData.get(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES) ); } @@ -142,47 +144,45 @@ public class QueueRestACLTest extends QpidRestTestCase { getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); - String queueName = getTestName(); - - int responseCode = createQueue(queueName); - assertQueueExists(queueName); + int responseCode = createQueue(); + assertQueueExists(); getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(Queue.NAME, queueName); + attributes.put(Queue.NAME, _queueName); attributes.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 100000); attributes.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 80000); - responseCode = getRestTestHelper().submitRequest("/rest/queue/test/" + queueName, "PUT", attributes); + responseCode = getRestTestHelper().submitRequest(_queueUrl, "PUT", attributes); assertEquals("Setting of queue attribites should be allowed", 403, responseCode); - Map<String, Object> queueData = getRestTestHelper().getJsonAsSingletonList("/rest/queue/test/" + queueName); + Map<String, Object> queueData = getRestTestHelper().getJsonAsSingletonList(_queueUrl); assertEquals("Unexpected " + Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, 0, queueData.get(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES) ); assertEquals("Unexpected " + Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, 0, queueData.get(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES) ); } - private int createQueue(String queueName) throws Exception + private int createQueue() throws Exception { Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(Queue.NAME, queueName); + attributes.put(Queue.NAME, _queueName); - return getRestTestHelper().submitRequest("/rest/queue/test/" + queueName, "PUT", attributes); + return getRestTestHelper().submitRequest(_queueUrl, "PUT", attributes); } - private void assertQueueDoesNotExist(String queueName) throws Exception + private void assertQueueDoesNotExist() throws Exception { - assertQueueExistence(queueName, false); + assertQueueExistence(false); } - private void assertQueueExists(String queueName) throws Exception + private void assertQueueExists() throws Exception { - assertQueueExistence(queueName, true); + assertQueueExistence(true); } - private void assertQueueExistence(String queueName, boolean exists) throws Exception + private void assertQueueExistence(boolean exists) throws Exception { - List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList("/rest/queue/test/" + queueName); + List<Map<String, Object>> queues = getRestTestHelper().getJsonAsList(_queueUrl); assertEquals("Unexpected result", exists, !queues.isEmpty()); } } diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java index 8802ccac58..3436b06db0 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java @@ -48,7 +48,6 @@ import javax.naming.InitialContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.apache.qpid.client.AMQAnyDestination; import org.apache.qpid.client.AMQConnection; import org.apache.qpid.client.AMQDestination; @@ -57,9 +56,7 @@ import org.apache.qpid.client.AMQSession_0_10; import org.apache.qpid.client.message.QpidMessageProperties; import org.apache.qpid.jndi.PropertiesFileInitialContextFactory; import org.apache.qpid.messaging.Address; -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.transport.ExecutionErrorCode; public class AddressBasedDestinationTest extends QpidBrokerTestCase @@ -70,10 +67,6 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase @Override public void setUp() throws Exception { - TestBrokerConfiguration config = getBrokerConfiguration(); - config.setObjectAttribute(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.CONTEXT, - Collections.singletonMap("queue.maximumDeliveryAttempts","0")); - super.setUp(); _connection = getConnection() ; _connection.start(); diff --git a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java index 17485c5445..67c3f51d46 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java +++ b/java/systests/src/main/java/org/apache/qpid/test/client/timeouts/SyncWaitDelayTest.java @@ -31,14 +31,12 @@ import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.SlowMessageStore; import org.apache.qpid.test.utils.QpidBrokerTestCase; -import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * This tests that when the commit takes a long time(due to POST_COMMIT_DELAY) that the commit does not timeout @@ -66,8 +64,7 @@ public class SyncWaitDelayTest extends QpidBrokerTestCase messageStoreSettings.put(MessageStore.STORE_TYPE, SlowMessageStore.TYPE); messageStoreSettings.put(SlowMessageStore.DELAYS, slowMessageStoreDelays); - TestBrokerConfiguration config = getBrokerConfiguration(); - config.setObjectAttribute(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); + TestUtils.createStoreWithVirtualHostEntry(messageStoreSettings, getBrokerConfiguration(), getTestProfileVirtualHostNodeType()); super.setUp(); diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index 0e9256e1c6..60877b0cde 100755 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -49,7 +49,6 @@ import javax.naming.NamingException; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; - import org.apache.qpid.AMQException; import org.apache.qpid.client.AMQConnectionFactory; import org.apache.qpid.client.AMQConnectionURL; @@ -66,6 +65,8 @@ import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.virtualhost.StandardVirtualHost; @@ -246,12 +247,7 @@ public class QpidBrokerTestCase extends QpidTestCase configuration.setObjectAttribute(Port.class, TestBrokerConfiguration.ENTRY_NAME_JMX_PORT, Port.PORT, getManagementPort(actualPort) + JMXPORT_CONNECTORSERVER_OFFSET); String workDir = System.getProperty("QPID_WORK") + File.separator + TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST + File.separator + actualPort; - Map<String, Object> virtualHostSettings = configuration.getObjectAttributes(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); - - @SuppressWarnings("unchecked") - Map<String, Object> storeSettings = (Map<String, Object>)virtualHostSettings.get(VirtualHost.MESSAGE_STORE_SETTINGS); - storeSettings.put(MessageStore.STORE_PATH, workDir); - configuration.setObjectAttribute(VirtualHost.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHost.MESSAGE_STORE_SETTINGS, storeSettings); + configuration.setObjectAttribute(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, DurableConfigurationStore.STORE_PATH, workDir); } return configuration; @@ -844,13 +840,13 @@ public class QpidBrokerTestCase extends QpidTestCase } /** - * Creates a new virtual host within the test virtualhost file. + * Creates a new virtual host node in broker configuration for given broker port * @param brokerPort broker port - * @param virtualHostName virtual host name + * @param virtualHostNodeName virtual host node name */ - protected void createTestVirtualHost(int brokerPort, String virtualHostName) + protected void createTestVirtualHostNode(int brokerPort, String virtualHostNodeName) { - String storeType = getTestProfileMessageStoreType(); + String storeType = getTestProfileVirtualHostNodeType(); String storeDir = null; if (System.getProperty("profile", "").startsWith("java-dby-mem")) @@ -859,19 +855,20 @@ public class QpidBrokerTestCase extends QpidTestCase } else if (!MemoryMessageStore.TYPE.equals(storeType)) { - storeDir = "${QPID_WORK}" + File.separator + virtualHostName + File.separator + brokerPort; + storeDir = "${QPID_WORK}" + File.separator + virtualHostNodeName + File.separator + brokerPort; } // add new virtual host configuration to the broker store Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(VirtualHost.NAME, virtualHostName); - attributes.put(VirtualHost.TYPE, StandardVirtualHost.TYPE); - Map<String, Object> messageStoreSettings = new HashMap<String, Object>(); - messageStoreSettings.put(MessageStore.STORE_TYPE, storeType); - messageStoreSettings.put(MessageStore.STORE_PATH, storeDir); - attributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings ); + attributes.put(VirtualHostNode.NAME, virtualHostNodeName); + attributes.put(VirtualHostNode.TYPE, storeType); + attributes.put(VirtualHostNode.IS_MESSAGE_STORE_PROVIDER, true); + if (storeDir != null) + { + attributes.put(DurableConfigurationStore.STORE_PATH, storeDir); + } int port = getPort(brokerPort); - getBrokerConfiguration(port).addObjectConfiguration(VirtualHost.class, attributes); + getBrokerConfiguration(port).addObjectConfiguration(VirtualHostNode.class, attributes); } /** diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java index c93a4c6556..8e3d1262e7 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java @@ -50,6 +50,7 @@ import org.apache.qpid.server.security.access.FileAccessControlProviderConstants import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; import org.apache.qpid.server.store.handler.ConfiguredObjectRecordHandler; +import org.apache.qpid.util.Strings; public class TestBrokerConfiguration { @@ -85,6 +86,34 @@ public class TestBrokerConfiguration intialStoreLocation, null, Collections.<String,String>emptyMap()); + _store.visitConfiguredObjectRecords(new ConfiguredObjectRecordHandler() + { + @Override + public boolean handle(ConfiguredObjectRecord record) + { + Map<String, Object> attributes = record.getAttributes(); + String rawType = (String)attributes.get("type"); + if (rawType != null) + { + String interpolatedType = Strings.expand(rawType, false, Strings.ENV_VARS_RESOLVER, Strings.JAVA_SYS_PROPS_RESOLVER); + if (!interpolatedType.equals(rawType)) + { + setObjectAttribute(record, "type", interpolatedType); + } + } + return true; + } + + @Override + public void end() + { + } + + @Override + public void begin() + { + } + }); } public boolean setBrokerAttribute(String name, Object value) diff --git a/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java b/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java index c651d3ec7f..16f3c3d82c 100644 --- a/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java +++ b/java/systests/src/main/java/org/apache/qpid/test/utils/TestUtils.java @@ -20,9 +20,27 @@ */ package org.apache.qpid.test.utils; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.BrokerModel; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostNode; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.store.ConfiguredObjectRecordImpl; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.JsonFileConfigStore; +import org.apache.qpid.server.store.MemoryMessageStore; +import org.apache.qpid.server.virtualhost.StandardVirtualHost; +import org.apache.qpid.util.Strings; public class TestUtils { @@ -51,4 +69,48 @@ public class TestUtils } return dump.toString(); } + + public static String createStoreWithVirtualHostEntry(Map<String, Object> messageStoreSettings, TestBrokerConfiguration config, String configStoreType) + { + UUID virtualHostId = UUID.randomUUID(); + Map<String, Object> virtualHostAttributes = new HashMap<String, Object>(); + virtualHostAttributes.put(VirtualHost.NAME, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + virtualHostAttributes.put(VirtualHost.ID, virtualHostId); + virtualHostAttributes.put(VirtualHost.TYPE, StandardVirtualHost.TYPE); + virtualHostAttributes.put(VirtualHost.MESSAGE_STORE_SETTINGS, messageStoreSettings); + virtualHostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION); + + config.setObjectAttribute(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHostNode.IS_MESSAGE_STORE_PROVIDER, false); + // If using MMS, switch to split store with JSON config store. + if (MemoryMessageStore.TYPE.equals(configStoreType)) + { + configStoreType = JsonFileConfigStore.TYPE; + } + DurableConfigurationStoreFactory storeFactory = DurableConfigurationStoreFactory.FACTORY_LOADER.get(configStoreType); + DurableConfigurationStore store = storeFactory.createDurableConfigurationStore(); + + config.setObjectAttribute(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST, VirtualHostNode.TYPE, configStoreType); + + Map<String,Object> nodeAttributes = config.getObjectAttributes(VirtualHostNode.class, TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + String storePath = (String)nodeAttributes.get(DurableConfigurationStore.STORE_PATH); + String path = Strings.expand(storePath, false, Strings.JAVA_SYS_PROPS_RESOLVER, Strings.ENV_VARS_RESOLVER); + + Map<String, Object> attributes = new HashMap<String, Object>(nodeAttributes); + attributes.put(DurableConfigurationStore.STORE_PATH, path); + + VirtualHostNode<?> virtualHostNode = mock(VirtualHostNode.class); + when(virtualHostNode.getModel()).thenReturn(BrokerModel.getInstance()); + when(virtualHostNode.getName()).thenReturn(TestBrokerConfiguration.ENTRY_NAME_VIRTUAL_HOST); + + try + { + store.openConfigurationStore(virtualHostNode, attributes); + store.create(new ConfiguredObjectRecordImpl(virtualHostId, VirtualHost.class.getSimpleName(), virtualHostAttributes)); + } + finally + { + store.closeConfigurationStore(); + } + return path; + } } |