diff options
| author | Kim van der Riet <kpvdr@apache.org> | 2013-09-20 18:59:30 +0000 |
|---|---|---|
| committer | Kim van der Riet <kpvdr@apache.org> | 2013-09-20 18:59:30 +0000 |
| commit | c70bf3ea28cdf6bafd8571690d3e5c466a0658a2 (patch) | |
| tree | 68b24940e433f3f9c278b054d9ea1622389bd332 /qpid/java | |
| parent | fcdf1723c7b5cdf0772054a93edb6e7d97c4bb1e (diff) | |
| download | qpid-python-c70bf3ea28cdf6bafd8571690d3e5c466a0658a2.tar.gz | |
QPID-4984: WIP - Merge from trunk r.1525056
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/linearstore@1525101 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java')
531 files changed, 18410 insertions, 5467 deletions
diff --git a/qpid/java/bdbstore/build.xml b/qpid/java/bdbstore/build.xml index 1a749fab39..a74457d9ad 100644 --- a/qpid/java/bdbstore/build.xml +++ b/qpid/java/bdbstore/build.xml @@ -17,10 +17,12 @@ - under the License. --> <project name="bdbstore" xmlns:ivy="antlib:org.apache.ivy.ant" default="build"> - <property name="module.depends" value="common broker" /> - <property name="module.test.depends" value="client common/tests broker/tests management/common systests broker-plugins/management-jmx" /> + <property name="module.depends" value="common broker broker-plugins/amqp-0-8-protocol broker-plugins/amqp-0-10-protocol" /> + <property name="module.test.depends" value="client common/tests broker/tests management/common systests broker-plugins/management-jmx broker-plugins/memory-store broker-plugins/amqp-0-8-protocol broker-plugins/amqp-0-10-protocol broker-plugins/amqp-msg-conv-0-8-to-0-10" /> <property name="module.genpom" value="true"/> - <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided -Sje=provided"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided -Sqpid-broker-plugins-amqp-0-8-protocol=provided -Sje=provided"/> + + <property name="broker.plugin" value="true"/> <import file="../module.xml" /> @@ -79,4 +81,9 @@ http://www.oracle.com/technetwork/database/berkeleydb/downloads/jeoslicense-0868 <target name="build" depends="check-request-props, bdb-jar-required, module.build" /> + <!-- Overrides, target in module.xml --> + <target name="copy-broker-plugin-jars-deps" if="broker.plugin" description="copy broker plugins dependencies for use in release packaging"> + <!-- NO-OP, we explicitly do not want to copy the dependencies for this optional functionality as we can't distribute them --> + </target> + </project> diff --git a/qpid/java/bdbstore/jmx/build.xml b/qpid/java/bdbstore/jmx/build.xml index d3e9f63b46..898eac9070 100644 --- a/qpid/java/bdbstore/jmx/build.xml +++ b/qpid/java/bdbstore/jmx/build.xml @@ -18,7 +18,7 @@ --> <project name="bdbstore-jmx" default="build"> <property name="module.depends" value="common broker broker-plugins/management-jmx management/common bdbstore" /> - <property name="module.test.depends" value="broker/tests common/tests management/common client systests bdbstore/tests" /> + <property name="module.test.depends" value="broker/tests common/tests management/common client systests bdbstore/tests broker-plugins/memory-store" /> <property name="module.genpom" value="true"/> <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided -Sqpid-broker-plugins-management-jmx=provided -Sqpid-management-common=provided -Sqpid-bdbstore=provided -Sje=provided"/> @@ -28,4 +28,9 @@ <import file="../../module.xml" /> <target name="bundle" depends="bundle-tasks" /> + + <!-- Overrides target in module.xml --> + <target name="copy-broker-plugin-jars-deps" if="broker.plugin" description="copy broker plugins dependencies for use in release packaging"> + <!-- NO-OP, we explicitly do not want to copy the dependencies for this optional functionality as we can't distribute them --> + </target> </project> diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java index f6b7e1790f..e772498ee9 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/AbstractBDBMessageStore.java @@ -21,24 +21,15 @@ package org.apache.qpid.server.store.berkeleydb; import com.sleepycat.bind.tuple.ByteBinding; +import com.sleepycat.bind.tuple.IntegerBinding; import com.sleepycat.bind.tuple.LongBinding; -import com.sleepycat.je.CheckpointConfig; -import com.sleepycat.je.Cursor; -import com.sleepycat.je.Database; -import com.sleepycat.je.DatabaseConfig; -import com.sleepycat.je.DatabaseEntry; -import com.sleepycat.je.DatabaseException; -import com.sleepycat.je.Environment; -import com.sleepycat.je.EnvironmentConfig; -import com.sleepycat.je.ExceptionEvent; -import com.sleepycat.je.ExceptionListener; -import com.sleepycat.je.LockConflictException; -import com.sleepycat.je.LockMode; -import com.sleepycat.je.OperationStatus; +import com.sleepycat.je.*; +import com.sleepycat.je.Transaction; import java.io.File; import java.lang.ref.SoftReference; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; @@ -76,24 +67,27 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo private static final int LOCK_RETRY_ATTEMPTS = 5; - public static final int VERSION = 6; + public static final int VERSION = 7; private static final Map<String, String> ENVCONFIG_DEFAULTS = Collections.unmodifiableMap(new HashMap<String, String>() {{ put(EnvironmentConfig.LOCK_N_LOCK_TABLES, "7"); + put(EnvironmentConfig.STATS_COLLECT, "false"); // Turn off stats generation - feature introduced (and on by default) from BDB JE 5.0.84 }}); private Environment _environment; - private String CONFIGURED_OBJECTS = "CONFIGURED_OBJECTS"; - private String MESSAGEMETADATADB_NAME = "MESSAGE_METADATA"; - private String MESSAGECONTENTDB_NAME = "MESSAGE_CONTENT"; - private String DELIVERYDB_NAME = "QUEUE_ENTRIES"; - private String BRIDGEDB_NAME = "BRIDGES"; - private String LINKDB_NAME = "LINKS"; - private String XIDDB_NAME = "XIDS"; + private static String CONFIGURED_OBJECTS = "CONFIGURED_OBJECTS"; + private static String MESSAGEMETADATADB_NAME = "MESSAGE_METADATA"; + private static String MESSAGECONTENTDB_NAME = "MESSAGE_CONTENT"; + private static String DELIVERYDB_NAME = "QUEUE_ENTRIES"; + private static String BRIDGEDB_NAME = "BRIDGES"; + private static String LINKDB_NAME = "LINKS"; + private static String XIDDB_NAME = "XIDS"; + private static String CONFIG_VERSION_DB = "CONFIG_VERSION"; private Database _configuredObjectsDb; + private Database _configVersionDb; private Database _messageMetaDataDb; private Database _messageContentDb; private Database _deliveryDb; @@ -145,6 +139,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo private String _storeLocation; private Map<String, String> _envConfigMap; + private VirtualHost _virtualHost; public AbstractBDBMessageStore() { @@ -157,34 +152,58 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo _eventManager.addEventListener(eventListener, events); } - public void configureConfigStore(String name, - ConfigurationRecoveryHandler recoveryHandler, - VirtualHost virtualHost) throws Exception + public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) throws Exception { _stateManager.attainState(State.INITIALISING); _configRecoveryHandler = recoveryHandler; - - configure(name, virtualHost); + _virtualHost = virtualHost; } - public void configureMessageStore(String name, - MessageStoreRecoveryHandler messageRecoveryHandler, + public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) throws Exception { + if(_stateManager.isInState(State.INITIAL)) + { + // Is acting as a message store, but not a durable config store + _stateManager.attainState(State.INITIALISING); + } + _messageRecoveryHandler = messageRecoveryHandler; _tlogRecoveryHandler = tlogRecoveryHandler; + _virtualHost = virtualHost; + + completeInitialisation(); + } + + private void completeInitialisation() throws Exception + { + configure(_virtualHost); _stateManager.attainState(State.INITIALISED); } public synchronized void activate() throws Exception { + // check if acting as a durable config store, but not a message store + if(_stateManager.isInState(State.INITIALISING)) + { + completeInitialisation(); + } _stateManager.attainState(State.ACTIVATING); - recoverConfig(_configRecoveryHandler); - recoverMessages(_messageRecoveryHandler); - recoverQueueEntries(_tlogRecoveryHandler); + if(_configRecoveryHandler != null) + { + recoverConfig(_configRecoveryHandler); + } + if(_messageRecoveryHandler != null) + { + recoverMessages(_messageRecoveryHandler); + } + if(_tlogRecoveryHandler != null) + { + recoverQueueEntries(_tlogRecoveryHandler); + } _stateManager.attainState(State.ACTIVE); } @@ -198,23 +217,38 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo * Called after instantiation in order to configure the message store. * * - * @param name The name of the virtual host using this store - * @param virtualHost + * + * @param virtualHost The virtual host using this store * @return whether a new store environment was created or not (to indicate whether recovery is necessary) * * @throws Exception If any error occurs that means the store is unable to configure itself. */ - public void configure(String name, VirtualHost virtualHost) throws Exception + public void configure(VirtualHost virtualHost) throws Exception { + configure(virtualHost, _messageRecoveryHandler != null); + } - + public void configure(VirtualHost virtualHost, boolean isMessageStore) throws Exception + { + String name = virtualHost.getName(); final String defaultPath = System.getProperty("QPID_WORK") + File.separator + "bdbstore" + File.separator + name; - - String storeLocation = (String) virtualHost.getAttribute(VirtualHost.STORE_PATH); - if(storeLocation == null) + String storeLocation; + if(isMessageStore) { - storeLocation = defaultPath; + storeLocation = (String) virtualHost.getAttribute(VirtualHost.STORE_PATH); + if(storeLocation == null) + { + storeLocation = defaultPath; + } + } + else // we are acting only as the durable config store + { + storeLocation = (String) virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH); + if(storeLocation == null) + { + storeLocation = defaultPath; + } } Object overfullAttr = virtualHost.getAttribute(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE); @@ -326,6 +360,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo dbConfig.setReadOnly(false); _configuredObjectsDb = openDatabase(CONFIGURED_OBJECTS, dbConfig); + _configVersionDb = openDatabase(CONFIG_VERSION_DB, dbConfig); _messageMetaDataDb = openDatabase(MESSAGEMETADATADB_NAME, dbConfig); _messageContentDb = openDatabase(MESSAGECONTENTDB_NAME, dbConfig); _deliveryDb = openDatabase(DELIVERYDB_NAME, dbConfig); @@ -399,6 +434,13 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo _xidDb.close(); } + + if (_configVersionDb != null) + { + LOGGER.info("Close config version database"); + _configVersionDb.close(); + } + closeEnvironment(); } @@ -426,10 +468,15 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo { try { - recoveryHandler.beginConfigurationRecovery(this); + final int configVersion = getConfigVersion(); + recoveryHandler.beginConfigurationRecovery(this, configVersion); loadConfiguredObjects(recoveryHandler); - recoveryHandler.completeConfigurationRecovery(); + final int newConfigVersion = recoveryHandler.completeConfigurationRecovery(); + if(newConfigVersion != configVersion) + { + updateConfigVersion(newConfigVersion); + } } catch (DatabaseException e) { @@ -438,6 +485,66 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo } + private void updateConfigVersion(int newConfigVersion) throws AMQStoreException + { + Cursor cursor = null; + try + { + Transaction txn = _environment.beginTransaction(null, null); + cursor = _configVersionDb.openCursor(txn, null); + DatabaseEntry key = new DatabaseEntry(); + ByteBinding.byteToEntry((byte) 0,key); + DatabaseEntry value = new DatabaseEntry(); + + while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) + { + IntegerBinding.intToEntry(newConfigVersion, value); + OperationStatus status = cursor.put(key, value); + if (status != OperationStatus.SUCCESS) + { + throw new AMQStoreException("Error setting config version: " + status); + } + } + cursor.close(); + cursor = null; + txn.commit(); + } + finally + { + closeCursorSafely(cursor); + } + + } + + private int getConfigVersion() throws AMQStoreException + { + Cursor cursor = null; + try + { + cursor = _configVersionDb.openCursor(null, null); + DatabaseEntry key = new DatabaseEntry(); + DatabaseEntry value = new DatabaseEntry(); + while (cursor.getNext(key, value, LockMode.RMW) == OperationStatus.SUCCESS) + { + return IntegerBinding.entryToInt(value); + } + + // Insert 0 as the default config version + IntegerBinding.intToEntry(0,value); + ByteBinding.byteToEntry((byte) 0,key); + OperationStatus status = _configVersionDb.put(null, key, value); + if (status != OperationStatus.SUCCESS) + { + throw new AMQStoreException("Error initialising config version: " + status); + } + return 0; + } + finally + { + closeCursorSafely(cursor); + } + } + private void loadConfiguredObjects(ConfigurationRecoveryHandler crh) throws DatabaseException { Cursor cursor = null; @@ -743,7 +850,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo { LOGGER.debug("public void remove(id = " + id + ", type="+type+"): called"); } - OperationStatus status = removeConfiguredObject(id); + OperationStatus status = removeConfiguredObject(null, id); if (status == OperationStatus.NOTFOUND) { throw new AMQStoreException("Configured object of type " + type + " with id " + id + " not found"); @@ -751,8 +858,45 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo } @Override + public UUID[] removeConfiguredObjects(final UUID... objects) throws AMQStoreException + { + com.sleepycat.je.Transaction txn = _environment.beginTransaction(null, null); + Collection<UUID> removed = new ArrayList<UUID>(objects.length); + for(UUID id : objects) + { + if(removeConfiguredObject(txn, id) == OperationStatus.SUCCESS) + { + removed.add(id); + } + } + + txn.commit(); + return removed.toArray(new UUID[removed.size()]); + } + + @Override public void update(UUID id, String type, Map<String, Object> attributes) throws AMQStoreException { + update(false, id, type, attributes, null); + } + + public void update(ConfiguredObjectRecord... records) throws AMQStoreException + { + update(false, records); + } + + public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws AMQStoreException + { + com.sleepycat.je.Transaction txn = _environment.beginTransaction(null, null); + for(ConfiguredObjectRecord record : records) + { + update(createIfNecessary, record.getId(), record.getType(), record.getAttributes(), txn); + } + txn.commit(); + } + + private void update(boolean createIfNecessary, UUID id, String type, Map<String, Object> attributes, com.sleepycat.je.Transaction txn) throws AMQStoreException + { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Updating " +type + ", id: " + id); @@ -768,14 +912,14 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo DatabaseEntry newValue = new DatabaseEntry(); ConfiguredObjectBinding configuredObjectBinding = ConfiguredObjectBinding.getInstance(); - OperationStatus status = _configuredObjectsDb.get(null, key, value, LockMode.DEFAULT); - if (status == OperationStatus.SUCCESS) + OperationStatus status = _configuredObjectsDb.get(txn, key, value, LockMode.DEFAULT); + if (status == OperationStatus.SUCCESS || (createIfNecessary && status == OperationStatus.NOTFOUND)) { ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(id, type, attributes); // write the updated entry to the store configuredObjectBinding.objectToEntry(newQueueRecord, newValue); - status = _configuredObjectsDb.put(null, key, newValue); + status = _configuredObjectsDb.put(txn, key, newValue); if (status != OperationStatus.SUCCESS) { throw new AMQStoreException("Error updating queue details within the store: " + status); @@ -1299,6 +1443,7 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo { if (_stateManager.isInState(State.ACTIVE)) { + LOGGER.debug("Storing configured object: " + configuredObject); DatabaseEntry key = new DatabaseEntry(); UUIDTupleBinding keyBinding = UUIDTupleBinding.getInstance(); keyBinding.objectToEntry(configuredObject.getId(), key); @@ -1324,14 +1469,16 @@ public abstract class AbstractBDBMessageStore implements MessageStore, DurableCo } } - private OperationStatus removeConfiguredObject(UUID id) throws AMQStoreException + private OperationStatus removeConfiguredObject(Transaction tx, UUID id) throws AMQStoreException { + + LOGGER.debug("Removing configured object: " + id); DatabaseEntry key = new DatabaseEntry(); UUIDTupleBinding uuidBinding = UUIDTupleBinding.getInstance(); uuidBinding.objectToEntry(id, key); try { - return _configuredObjectsDb.delete(null, key); + return _configuredObjectsDb.delete(tx, key); } catch (DatabaseException e) { diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java index 561e4fa660..fb1dc1f1d3 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStore.java @@ -122,14 +122,14 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess private Map<String, String> _repConfig; @Override - public void configure(String name, VirtualHost virtualHost) throws Exception + public void configure(VirtualHost virtualHost) throws Exception { //Mandatory configuration _groupName = getValidatedStringAttribute(virtualHost, "haGroupName"); _nodeName = getValidatedStringAttribute(virtualHost, "haNodeName"); _nodeHostPort = getValidatedStringAttribute(virtualHost, "haNodeAddress"); _helperHostPort = getValidatedStringAttribute(virtualHost, "haHelperAddress"); - _name = name; + _name = virtualHost.getName(); //Optional configuration String durabilitySetting = getStringAttribute(virtualHost,"haDurability",null); @@ -157,7 +157,7 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess + "! Please set highAvailability.coalescingSync to false in store configuration."); } - super.configure(name, virtualHost); + super.configure(virtualHost); } @@ -260,10 +260,10 @@ public class BDBHAMessageStore extends AbstractBDBMessageStore implements HAMess } @Override - public void configureMessageStore(String name, MessageStoreRecoveryHandler messageRecoveryHandler, + public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) throws Exception { - super.configureMessageStore(name, messageRecoveryHandler, tlogRecoveryHandler); + super.configureMessageStore(virtualHost, messageRecoveryHandler, tlogRecoveryHandler); final ReplicatedEnvironment replicatedEnvironment = getReplicatedEnvironment(); diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java index be91e4a484..bb3c7b108d 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBHAVirtualHost.java @@ -25,12 +25,14 @@ import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.DurableConfigurationRecoverer; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.Event; import org.apache.qpid.server.store.EventListener; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.OperationalLoggingListener; import org.apache.qpid.server.virtualhost.AbstractVirtualHost; +import org.apache.qpid.server.virtualhost.DefaultUpgraderProvider; import org.apache.qpid.server.virtualhost.State; import org.apache.qpid.server.virtualhost.VirtualHostConfigRecoveryHandler; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; @@ -58,7 +60,7 @@ public class BDBHAVirtualHost extends AbstractVirtualHost _messageStore = new BDBHAMessageStore(); final MessageStoreLogSubject storeLogSubject = - new MessageStoreLogSubject(this, _messageStore.getClass().getSimpleName()); + new MessageStoreLogSubject(getName(), _messageStore.getClass().getSimpleName()); OperationalLoggingListener.listen(_messageStore, storeLogSubject); _messageStore.addEventListener(new BeforeActivationListener(), Event.BEFORE_ACTIVATE); @@ -71,13 +73,16 @@ public class BDBHAVirtualHost extends AbstractVirtualHost _messageStore.addEventListener(new BeforePassivationListener(), Event.BEFORE_PASSIVATE); VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this, getExchangeRegistry(), getExchangeFactory()); + DurableConfigurationRecoverer configRecoverer = + new DurableConfigurationRecoverer(getName(), getDurableConfigurationRecoverers(), + new DefaultUpgraderProvider(this, getExchangeRegistry())); - _messageStore.configureConfigStore(getName(), - recoveryHandler, - virtualHost); + _messageStore.configureConfigStore( + virtualHost, configRecoverer + ); - _messageStore.configureMessageStore(getName(), - recoveryHandler, + _messageStore.configureMessageStore( + virtualHost, recoveryHandler, recoveryHandler ); } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java index 4eac54dd6f..d7c8b23d39 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreFactory.java @@ -26,10 +26,12 @@ import java.util.List; import java.util.Map; import org.apache.commons.configuration.Configuration; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; import org.apache.qpid.server.plugin.MessageStoreFactory; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; -public class BDBMessageStoreFactory implements MessageStoreFactory +public class BDBMessageStoreFactory implements MessageStoreFactory, DurableConfigurationStoreFactory { @Override @@ -39,6 +41,12 @@ public class BDBMessageStoreFactory implements MessageStoreFactory } @Override + public DurableConfigurationStore createDurableConfigurationStore() + { + return new BDBMessageStore(); + } + + @Override public MessageStore createMessageStore() { return new BDBMessageStore(); @@ -76,12 +84,25 @@ public class BDBMessageStoreFactory implements MessageStoreFactory @Override public void validateAttributes(Map<String, Object> attributes) { - Object storePath = attributes.get(VirtualHost.STORE_PATH); - if(!(storePath instanceof String)) + if(getType().equals(attributes.get(VirtualHost.STORE_TYPE))) + { + Object storePath = attributes.get(VirtualHost.STORE_PATH); + if(!(storePath instanceof String)) + { + throw new IllegalArgumentException("Attribute '"+ VirtualHost.STORE_PATH + +"' is required and must be of type String."); + + } + } + if(getType().equals(attributes.get(VirtualHost.CONFIG_STORE_TYPE))) { - throw new IllegalArgumentException("Attribute '"+ VirtualHost.STORE_PATH - +"' is required and must be of type String."); + Object storePath = attributes.get(VirtualHost.CONFIG_STORE_PATH); + if(!(storePath instanceof String)) + { + throw new IllegalArgumentException("Attribute '"+ VirtualHost.CONFIG_STORE_PATH + +"' is required and must be of type String."); + } } } } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java index 2e6c8d5666..6925c9ee2b 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/tuple/MessageMetaDataBinding.java @@ -26,7 +26,8 @@ import com.sleepycat.bind.tuple.TupleBinding; import com.sleepycat.bind.tuple.TupleInput; import com.sleepycat.bind.tuple.TupleOutput; -import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.server.plugin.MessageMetaDataType; +import org.apache.qpid.server.store.MessageMetaDataTypeRegistry; import org.apache.qpid.server.store.StorableMessageMetaData; /** @@ -54,10 +55,8 @@ public class MessageMetaDataBinding extends TupleBinding<StorableMessageMetaData ByteBuffer buf = ByteBuffer.wrap(dataAsBytes); buf.position(1); buf = buf.slice(); - MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]]; - StorableMessageMetaData metaData = type.getFactory().createMetaData(buf); - - return metaData; + MessageMetaDataType type = MessageMetaDataTypeRegistry.fromOrdinal(dataAsBytes[0]); + return type.createMetaData(buf); } @Override diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java index 49e5e700c4..4c9eae6f3e 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom4To5.java @@ -40,7 +40,7 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding; import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding; @@ -148,7 +148,7 @@ public class UpgradeFrom4To5 extends AbstractStoreUpgrade // if the queue name is in the gathered list then inspect its binding arguments // only topic exchange should have a JMS selector key in binding if (potentialDurableSubs.contains(queueName) - && exchangeName.equals(ExchangeDefaults.TOPIC_EXCHANGE_NAME)) + && exchangeName.equals(AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_NAME))) { if (arguments == null) { @@ -342,11 +342,11 @@ public class UpgradeFrom4To5 extends AbstractStoreUpgrade FieldTable emptyArguments = new FieldTable(); addBindingToDatabase(bindingTuple, newBindingsDatabase, transaction, queueNameAMQ, - ExchangeDefaults.DIRECT_EXCHANGE_NAME, queueNameAMQ, emptyArguments); + AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_NAME), queueNameAMQ, emptyArguments); // TODO QPID-3490 we should not persist a default exchange binding addBindingToDatabase(bindingTuple, newBindingsDatabase, transaction, queueNameAMQ, - ExchangeDefaults.DEFAULT_EXCHANGE_NAME, queueNameAMQ, emptyArguments); + AMQShortString.valueOf(ExchangeDefaults.DEFAULT_EXCHANGE_NAME), queueNameAMQ, emptyArguments); } }; new DatabaseTemplate(environment, NEW_QUEUE_DB_NAME, NEW_BINDINGS_DB_NAME, transaction).run(queueCreateOperation); @@ -364,7 +364,7 @@ public class UpgradeFrom4To5 extends AbstractStoreUpgrade DatabaseEntry key, DatabaseEntry value) { ExchangeRecord record = binding.entryToObject(value); - if (ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(record.getType())) + if (AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS).equals(record.getType())) { topicExchanges.add(record.getName()); } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java index 464608ff59..a478872ad0 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6.java @@ -46,6 +46,7 @@ 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.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.store.berkeleydb.AMQShortStringEncoding; import org.apache.qpid.server.store.berkeleydb.FieldTableEncoding; import org.apache.qpid.server.util.MapJsonSerializer; @@ -86,11 +87,15 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade static final String OLD_BRIDGES_DB_NAME = "bridges_v5"; static final String OLD_LINKS_DB_NAME = "links_v5"; - static final String[] DEFAULT_EXCHANGES = { ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(), - ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(), ExchangeDefaults.FANOUT_EXCHANGE_NAME.asString(), - ExchangeDefaults.HEADERS_EXCHANGE_NAME.asString(), ExchangeDefaults.TOPIC_EXCHANGE_NAME.asString(), - ExchangeDefaults.DIRECT_EXCHANGE_NAME.asString() }; - private static final Set<String> DEFAULT_EXCHANGES_SET = new HashSet<String>(Arrays.asList(DEFAULT_EXCHANGES)); + private static final Set<String> DEFAULT_EXCHANGES_SET = + new HashSet<String>(Arrays.asList( + ExchangeDefaults.DEFAULT_EXCHANGE_NAME, + ExchangeDefaults.FANOUT_EXCHANGE_NAME, + ExchangeDefaults.HEADERS_EXCHANGE_NAME, + ExchangeDefaults.TOPIC_EXCHANGE_NAME, + ExchangeDefaults.DIRECT_EXCHANGE_NAME)); + + private static final String ARGUMENTS = "arguments"; private MapJsonSerializer _serializer = new MapJsonSerializer(); @@ -452,8 +457,7 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade { // TODO: check and remove orphaned bindings BindingRecord bindingRecord = binding.entryToObject(key); - String exchangeName = bindingRecord.getExchangeName() == null ? ExchangeDefaults.DEFAULT_EXCHANGE_NAME - .asString() : bindingRecord.getExchangeName().asString(); + String exchangeName = bindingRecord.getExchangeName() == null ? ExchangeDefaults.DEFAULT_EXCHANGE_NAME : bindingRecord.getExchangeName().asString(); String queueName = bindingRecord.getQueueName().asString(); String routingKey = bindingRecord.getRoutingKey().asString(); FieldTable arguments = bindingRecord.getArguments(); @@ -580,10 +584,10 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade if (moveNonExclusiveOwnerToDescription(owner, exclusive)) { - _logger.info("Non-exclusive owner " + owner + " for queue " + queueName + " moved to " + AMQQueueFactory.X_QPID_DESCRIPTION); + _logger.info("Non-exclusive owner " + owner + " for queue " + queueName + " moved to " + QueueArgumentsConverter.X_QPID_DESCRIPTION); attributesMap.put(Queue.OWNER, null); - argumentsCopy.put(AMQShortString.valueOf(AMQQueueFactory.X_QPID_DESCRIPTION), owner); + argumentsCopy.put(AMQShortString.valueOf(QueueArgumentsConverter.X_QPID_DESCRIPTION), owner); } else { @@ -591,7 +595,7 @@ public class UpgradeFrom5To6 extends AbstractStoreUpgrade } if (!argumentsCopy.isEmpty()) { - attributesMap.put(Queue.ARGUMENTS, FieldTable.convertToMap(argumentsCopy)); + attributesMap.put(ARGUMENTS, FieldTable.convertToMap(argumentsCopy)); } return attributesMap; } diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java new file mode 100644 index 0000000000..e318c3586e --- /dev/null +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom6To7.java @@ -0,0 +1,66 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store.berkeleydb.upgrade; + +import com.sleepycat.bind.tuple.ByteBinding; +import com.sleepycat.bind.tuple.IntegerBinding; +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseConfig; +import com.sleepycat.je.DatabaseEntry; +import com.sleepycat.je.DatabaseException; +import com.sleepycat.je.Environment; +import com.sleepycat.je.OperationStatus; +import org.apache.qpid.AMQStoreException; + +public class UpgradeFrom6To7 extends AbstractStoreUpgrade +{ + + private static final int DEFAULT_CONFIG_VERSION = 0; + + @Override + public void performUpgrade(Environment environment, UpgradeInteractionHandler handler, String virtualHostName) + throws DatabaseException, AMQStoreException + { + reportStarting(environment, 6); + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); + + Database versionDb = environment.openDatabase(null, "CONFIG_VERSION", dbConfig); + + if(versionDb.count() == 0L) + { + DatabaseEntry key = new DatabaseEntry(); + DatabaseEntry value = new DatabaseEntry(); + IntegerBinding.intToEntry(DEFAULT_CONFIG_VERSION, value); + ByteBinding.byteToEntry((byte) 0, key); + OperationStatus status = versionDb.put(null, key, value); + if (status != OperationStatus.SUCCESS) + { + throw new AMQStoreException("Error initialising config version: " + status); + } + } + + versionDb.close(); + + reportFinished(environment, 7); + } +} diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java index f1ab012efc..e769bfae81 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/upgrade/Upgrader.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.store.berkeleydb.upgrade; +import com.sleepycat.je.Cursor; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; @@ -73,7 +74,12 @@ public class Upgrader } int version = getSourceVersion(versionDb); - + if(version > AbstractBDBMessageStore.VERSION) + { + throw new AMQStoreException("Database version " + version + + " is higher than the most recent known version: " + + AbstractBDBMessageStore.VERSION); + } performUpgradeFromVersion(version, versionDb); } finally @@ -87,19 +93,34 @@ public class Upgrader int getSourceVersion(Database versionDb) { - int version = AbstractBDBMessageStore.VERSION + 1; - OperationStatus result; + int version = -1; - do + Cursor cursor = null; + try { - version--; + cursor = versionDb.openCursor(null, null); + DatabaseEntry key = new DatabaseEntry(); - IntegerBinding.intToEntry(version, key); DatabaseEntry value = new DatabaseEntry(); - result = versionDb.get(null, key, value, LockMode.READ_COMMITTED); + while(cursor.getNext(key, value, null) == OperationStatus.SUCCESS) + { + int ver = IntegerBinding.entryToInt(key); + if(ver > version) + { + version = ver; + } + } + } + finally + { + if(cursor != null) + { + cursor.close(); + } } - while(result == OperationStatus.NOTFOUND); + + return version; } diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html b/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html index 1727264d41..17ffb1686f 100644 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html +++ b/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html @@ -31,7 +31,44 @@ <td class="tableContainer-labelCell" style="width: 300px;"><strong>Helper Address*: </strong></td> <td class="tableContainer-valueCell"> <input dojoType="dijit/form/ValidationTextBox" id="formAddVirtualHost.specific.helperAddress" - required="true" name="haHelperAddress" placeholder="host:port"/> + required="true" name="haHelperAddress" data-dojo-props="regExp:'([0-9a-zA-Z.-_]|::)+:[0-9]{1,5}', invalidMessage:'Must be of the form host:port'" placeholder="host:port"/> + </td> + </tr> + <tr> + <td class="tableContainer-labelCell" style="width: 300px;"><strong>Durability: </strong></td> + <td class="tableContainer-valueCell"> + <input dojoType="dijit/form/ValidationTextBox" id="formAddVirtualHost.specific.haDurability" + name="haDurability" placeholder="NO_SYNC,NO_SYNC,SIMPLE_MAJORITY"/> + </td> + </tr> + + <tr> + <td class="tableContainer-labelCell" style="width: 300px;"><strong>Coalesce local sync: </strong></td> + <td class="tableContainer-valueCell"> + <input dojoType="dijit/form/CheckBox" id="formAddVirtualHost.specific.haCoalescingSync" + checked="true" onchange="require(['dijit/registry', 'dojo/domReady!'], + function(registry){ + var checkbox = registry.byId('formAddVirtualHost.specific.haCoalescingSync'); + var hidden = registry.byId('formAddVirtualHost.specific.haCoalescingSyncHidden'); + hidden.set('value', checkbox.get('checked')); + })"/> + + <input dojoType="dijit/form/TextBox" id="formAddVirtualHost.specific.haCoalescingSyncHidden" type="hidden" name="haCoalescingSync" value="true"/> + </td> + + </tr> + + <tr> + <td class="tableContainer-labelCell" style="width: 300px;"><strong>Designated Primary: </strong></td> + <td class="tableContainer-valueCell"> + <input dojoType="dijit/form/CheckBox" id="formAddVirtualHost.specific.haDesignatedPrimary" + onchange="require(['dijit/registry', 'dojo/domReady!'], + function(registry){ + var checkbox = registry.byId('formAddVirtualHost.specific.haDesignatedPrimary'); + var hidden = registry.byId('formAddVirtualHost.specific.haDesignatedPrimaryHidden'); + hidden.set('value', checkbox.get('checked')); + })"/> + <input dojoType="dijit/form/TextBox" id="formAddVirtualHost.specific.haDesignatedPrimaryHidden" type="hidden" name="haDesignatedPrimary" value="false"/> </td> </tr> </table> diff --git a/qpid/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory b/qpid/java/bdbstore/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory new file mode 100644 index 0000000000..a822405565 --- /dev/null +++ b/qpid/java/bdbstore/src/main/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.berkeleydb.BDBMessageStoreFactory diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java index 0bbd399b9f..d7acf27f75 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBHAMessageStoreTest.java @@ -77,11 +77,11 @@ public class BDBHAMessageStoreTest extends QpidTestCase { try { - FileUtils.delete(new File(_workDir), true); if (_virtualHost != null) { _virtualHost.close(); } + FileUtils.delete(new File(_workDir), true); } finally { diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java index da1038284e..bfe41773eb 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreConfigurationTest.java @@ -25,22 +25,35 @@ import org.apache.qpid.server.store.DurableConfigurationStore; public class BDBMessageStoreConfigurationTest extends AbstractDurableConfigurationStoreTestCase { - private BDBMessageStore _bdbMessageStore; @Override - protected void onReopenStore() + protected BDBMessageStore createMessageStore() throws Exception { - _bdbMessageStore = null; + createStoreIfNecessary(); + return _bdbMessageStore; } @Override - protected BDBMessageStore createMessageStore() throws Exception + protected void closeMessageStore() throws Exception + { + closeStoreIfNecessary(); + } + + @Override + protected DurableConfigurationStore createConfigStore() throws Exception { createStoreIfNecessary(); + return _bdbMessageStore; } + @Override + protected void closeConfigStore() throws Exception + { + closeStoreIfNecessary(); + } + private void createStoreIfNecessary() { if(_bdbMessageStore == null) @@ -49,11 +62,12 @@ public class BDBMessageStoreConfigurationTest extends AbstractDurableConfigurati } } - @Override - protected DurableConfigurationStore createConfigStore() throws Exception + private void closeStoreIfNecessary() throws Exception { - createStoreIfNecessary(); - - return _bdbMessageStore; + if (_bdbMessageStore != null) + { + _bdbMessageStore.close(); + _bdbMessageStore = null; + } } } diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java index 8ba0d41e03..4684358190 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreQuotaEventsTest.java @@ -21,9 +21,7 @@ package org.apache.qpid.server.store.berkeleydb; import java.util.Collections; -import java.util.HashMap; import java.util.Map; -import org.apache.commons.configuration.XMLConfiguration; import org.apache.log4j.Logger; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.store.MessageStore; diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java index e77119b140..76b990038d 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStoreTest.java @@ -34,13 +34,14 @@ import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.EnqueableMessage; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.message.MessageMetaData_0_10; +import org.apache.qpid.server.protocol.v0_10.MessageMetaDataType_0_10; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; +import org.apache.qpid.server.protocol.v0_10.MessageMetaData_0_10; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.model.VirtualHost; -import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.server.protocol.v0_8.MessageMetaDataType_0_8; +import org.apache.qpid.server.store.MessageStoreTest; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.store.StoredMessage; @@ -55,15 +56,11 @@ import org.apache.qpid.transport.MessageDeliveryPriority; import org.apache.qpid.transport.MessageProperties; import org.apache.qpid.transport.MessageTransfer; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - /** * Subclass of MessageStoreTest which runs the standard tests from the superclass against * the BDB Store as well as additional tests specific to the BDB store-implementation. */ -public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageStoreTest +public class BDBMessageStoreTest extends MessageStoreTest { private static byte[] CONTENT_BYTES = new byte[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; @@ -129,14 +126,14 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto /* * reload the store only (read-only) */ - bdbStore = reloadStore(bdbStore); + AbstractBDBMessageStore readOnlyStore = reloadStore(bdbStore); /* * Read back and validate the 0-8 message metadata and content */ - StorableMessageMetaData storeableMMD_0_8 = bdbStore.getMessageMetaData(messageid_0_8); + StorableMessageMetaData storeableMMD_0_8 = readOnlyStore.getMessageMetaData(messageid_0_8); - assertEquals("Unexpected message type",MessageMetaDataType.META_DATA_0_8, storeableMMD_0_8.getType()); + assertEquals("Unexpected message type", MessageMetaDataType_0_8.TYPE, storeableMMD_0_8.getType().ordinal()); assertTrue("Unexpected instance type", storeableMMD_0_8 instanceof MessageMetaData); MessageMetaData returnedMMD_0_8 = (MessageMetaData) storeableMMD_0_8; @@ -158,7 +155,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto assertEquals("Property MessageID has changed", props_0_8.getMessageIdAsString(), returnedProperties_0_8.getMessageIdAsString()); ByteBuffer recoveredContent_0_8 = ByteBuffer.allocate((int) chb_0_8.getBodySize()) ; - long recoveredCount_0_8 = bdbStore.getContent(messageid_0_8, 0, recoveredContent_0_8); + long recoveredCount_0_8 = readOnlyStore.getContent(messageid_0_8, 0, recoveredContent_0_8); assertEquals("Incorrect amount of payload data recovered", chb_0_8.getBodySize(), recoveredCount_0_8); String returnedPayloadString_0_8 = new String(recoveredContent_0_8.array()); assertEquals("Message Payload has changed", bodyText, returnedPayloadString_0_8); @@ -166,9 +163,9 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto /* * Read back and validate the 0-10 message metadata and content */ - StorableMessageMetaData storeableMMD_0_10 = bdbStore.getMessageMetaData(messageid_0_10); + StorableMessageMetaData storeableMMD_0_10 = readOnlyStore.getMessageMetaData(messageid_0_10); - assertEquals("Unexpected message type",MessageMetaDataType.META_DATA_0_10, storeableMMD_0_10.getType()); + assertEquals("Unexpected message type", MessageMetaDataType_0_10.TYPE, storeableMMD_0_10.getType().ordinal()); assertTrue("Unexpected instance type", storeableMMD_0_10 instanceof MessageMetaData_0_10); MessageMetaData_0_10 returnedMMD_0_10 = (MessageMetaData_0_10) storeableMMD_0_10; @@ -189,11 +186,13 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto assertEquals("Message content type has changed", msgProps_0_10.getContentType(), returnedMsgProps.getContentType()); ByteBuffer recoveredContent = ByteBuffer.allocate((int) msgProps_0_10.getContentLength()) ; - long recoveredCount = bdbStore.getContent(messageid_0_10, 0, recoveredContent); + long recoveredCount = readOnlyStore.getContent(messageid_0_10, 0, recoveredContent); assertEquals("Incorrect amount of payload data recovered", msgProps_0_10.getContentLength(), recoveredCount); String returnedPayloadString_0_10 = new String(recoveredContent.array()); assertEquals("Message Payload has changed", bodyText, returnedPayloadString_0_10); + + readOnlyStore.close(); } private DeliveryProperties createDeliveryProperties_0_10() @@ -231,7 +230,7 @@ public class BDBMessageStoreTest extends org.apache.qpid.server.store.MessageSto messageStore.close(); AbstractBDBMessageStore newStore = new BDBMessageStore(); - newStore.configure("", getVirtualHostModel()); + newStore.configure(getVirtualHostModel(),true); newStore.startWithNoRecover(); diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java index 390d667db0..63af8d3840 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/BDBStoreUpgradeTestPreparer.java @@ -48,6 +48,7 @@ import org.apache.qpid.client.AMQConnectionFactory; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQSession; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.url.URLSyntaxException; /** @@ -159,7 +160,7 @@ public class BDBStoreUpgradeTestPreparer session = connection.createSession(true, Session.SESSION_TRANSACTED); // Create a priority queue on broker final Map<String,Object> priorityQueueArguments = new HashMap<String, Object>(); - priorityQueueArguments.put("x-qpid-priorities",10); + priorityQueueArguments.put(QueueArgumentsConverter.X_QPID_PRIORITIES,10); createAndBindQueueOnBroker(session, PRIORITY_QUEUE_NAME, priorityQueueArguments); // Create a queue that has a DLQ @@ -342,4 +343,4 @@ public class BDBStoreUpgradeTestPreparer BDBStoreUpgradeTestPreparer producer = new BDBStoreUpgradeTestPreparer(); producer.prepareBroker(); } -}
\ No newline at end of file +} diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java index 5ad49462ac..3f32df4b0c 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/HAMessageStoreSmokeTest.java @@ -20,7 +20,6 @@ package org.apache.qpid.server.store.berkeleydb; import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; @@ -34,7 +33,7 @@ public class HAMessageStoreSmokeTest extends QpidTestCase { try { - _store.configure("test", mock(VirtualHost.class)); + _store.configure(mock(VirtualHost.class)); fail("Expected an exception to be thrown"); } catch (ConfigurationException ce) diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java index c33d427868..44f0861275 100644 --- a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgradeFrom5To6Test.java @@ -48,6 +48,7 @@ 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.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.store.berkeleydb.entry.Xid; import org.apache.qpid.server.store.berkeleydb.tuple.XidBinding; import org.apache.qpid.server.store.berkeleydb.upgrade.UpgradeFrom5To6.CompoundKey; @@ -76,6 +77,7 @@ import com.sleepycat.je.Transaction; public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase { private static final Logger _logger = Logger.getLogger(UpgradeFrom5To6Test.class); + private static final String ARGUMENTS = "arguments"; @Override protected String getStoreDirectoryName() @@ -287,12 +289,12 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase expected.add(createExpectedQueueMap("clientid:myDurSubName", Boolean.TRUE, "clientid", null)); final Map<String, Object> queueWithOwnerArguments = new HashMap<String, Object>(); - queueWithOwnerArguments.put("x-qpid-priorities", 10); - queueWithOwnerArguments.put(AMQQueueFactory.X_QPID_DESCRIPTION, "misused-owner-as-description"); + queueWithOwnerArguments.put(QueueArgumentsConverter.X_QPID_PRIORITIES, 10); + queueWithOwnerArguments.put(QueueArgumentsConverter.X_QPID_DESCRIPTION, "misused-owner-as-description"); expected.add(createExpectedQueueMap("nonexclusive-with-erroneous-owner", Boolean.FALSE, null,queueWithOwnerArguments)); final Map<String, Object> priorityQueueArguments = new HashMap<String, Object>(); - priorityQueueArguments.put("x-qpid-priorities", 10); + priorityQueueArguments.put(QueueArgumentsConverter.X_QPID_PRIORITIES, 10); expected.add(createExpectedQueueMap(PRIORITY_QUEUE_NAME, Boolean.FALSE, null, priorityQueueArguments)); final Map<String, Object> queueWithDLQArguments = new HashMap<String, Object>(); @@ -388,7 +390,7 @@ public class UpgradeFrom5To6Test extends AbstractUpgradeTestCase expectedQueueEntry.put(Queue.OWNER, owner); if (argumentMap != null) { - expectedQueueEntry.put(Queue.ARGUMENTS, argumentMap); + expectedQueueEntry.put(ARGUMENTS, argumentMap); } return expectedQueueEntry; } diff --git a/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java new file mode 100644 index 0000000000..75717120b3 --- /dev/null +++ b/qpid/java/bdbstore/src/test/java/org/apache/qpid/server/store/berkeleydb/upgrade/UpgraderFailOnNewerVersionTest.java @@ -0,0 +1,109 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store.berkeleydb.upgrade; + +import com.sleepycat.bind.tuple.IntegerBinding; +import com.sleepycat.bind.tuple.LongBinding; +import com.sleepycat.je.Cursor; +import com.sleepycat.je.Database; +import com.sleepycat.je.DatabaseConfig; +import com.sleepycat.je.DatabaseEntry; +import com.sleepycat.je.Environment; +import com.sleepycat.je.EnvironmentConfig; +import com.sleepycat.je.OperationStatus; +import com.sleepycat.je.Transaction; +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.server.store.berkeleydb.AbstractBDBMessageStore; +import org.apache.qpid.server.store.berkeleydb.tuple.ContentBinding; + +public class UpgraderFailOnNewerVersionTest extends AbstractUpgradeTestCase +{ + private Upgrader _upgrader; + + @Override + protected String getStoreDirectoryName() + { + return "bdbstore-v999"; + } + + @Override + public void setUp() throws Exception + { + super.setUp(); + _upgrader = new Upgrader(_environment, getVirtualHostName()); + } + + private int getStoreVersion() + { + DatabaseConfig dbConfig = new DatabaseConfig(); + dbConfig.setTransactional(true); + dbConfig.setAllowCreate(true); + int storeVersion = -1; + Database versionDb = null; + Cursor cursor = null; + try + { + versionDb = _environment.openDatabase(null, Upgrader.VERSION_DB_NAME, dbConfig); + cursor = versionDb.openCursor(null, null); + DatabaseEntry key = new DatabaseEntry(); + DatabaseEntry value = new DatabaseEntry(); + while (cursor.getNext(key, value, null) == OperationStatus.SUCCESS) + { + int version = IntegerBinding.entryToInt(key); + if (storeVersion < version) + { + storeVersion = version; + } + } + } + finally + { + if (cursor != null) + { + cursor.close(); + } + if (versionDb != null) + { + versionDb.close(); + } + } + return storeVersion; + } + + public void testUpgrade() throws Exception + { + assertEquals("Unexpected store version", 999, getStoreVersion()); + try + { + _upgrader.upgradeIfNecessary(); + fail("Store should not be able to be upgraded"); + } + catch(AMQStoreException ex) + { + assertEquals("Incorrect exception thrown", "Database version 999 is higher than the most recent known version: " + + AbstractBDBMessageStore.VERSION, ex.getMessage()); + } + } + +} diff --git a/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v999/test-store/00000000.jdb b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v999/test-store/00000000.jdb Binary files differnew file mode 100644 index 0000000000..991367019f --- /dev/null +++ b/qpid/java/bdbstore/src/test/resources/upgrade/bdbstore-v999/test-store/00000000.jdb diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java index 181d693614..cc93c540df 100644 --- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java +++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java @@ -42,7 +42,7 @@ import org.apache.qpid.test.utils.QpidTestCase; * The ruleset is configured directly rather than using an external file by adding rules individually, calling the * {@link RuleSet#grant(Integer, String, Permission, Operation, ObjectType, ObjectProperties)} method. Then, the * access control mechanism is validated by checking whether operations would be authorised by calling the - * {@link RuleSet#check(Principal, Operation, ObjectType, ObjectProperties)} method. + * {@link RuleSet#check(Subject, Operation, ObjectType, ObjectProperties)} method. * * It ensure that permissions can be granted correctly on users directly and on groups. */ @@ -53,9 +53,9 @@ public class RuleSetTest extends QpidTestCase private static final String TEST_USER = "user"; // Common things that are passed to frame constructors - private AMQShortString _queueName = new AMQShortString(this.getClass().getName() + "queue"); - private AMQShortString _exchangeName = new AMQShortString("amq.direct"); - private AMQShortString _exchangeType = new AMQShortString("direct"); + private String _queueName = this.getClass().getName() + "queue"; + private String _exchangeName = "amq.direct"; + private String _exchangeType = "direct"; private Subject _testSubject = TestPrincipalUtils.createTestSubject(TEST_USER); @Override @@ -116,7 +116,7 @@ public class RuleSetTest extends QpidTestCase public void testExchangeCreate() { ObjectProperties properties = new ObjectProperties(_exchangeName); - properties.put(ObjectProperties.Property.TYPE, _exchangeType.asString()); + properties.put(ObjectProperties.Property.TYPE, _exchangeType); assertDenyGrantAllow(_testSubject, Operation.CREATE, ObjectType.EXCHANGE, properties); } diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/build.xml b/qpid/java/broker-plugins/amqp-0-10-protocol/build.xml new file mode 100644 index 0000000000..e3e6fabc87 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/build.xml @@ -0,0 +1,33 @@ +<!-- + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + --> +<project name="Qpid Broker-Plugins AMQP 0-10 Protocol" default="build"> + <property name="module.depends" value="common broker" /> + <property name="module.test.depends" value="common/tests broker/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/> + <property name="broker-plugins-amqp-0-10-protocol.libs" value="" /> + + <property name="broker.plugin" value="true"/> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> + +</project> diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java index 09fe44338c..cee1a04b17 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/CreditCreditManager.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java @@ -18,10 +18,10 @@ * under the License. * */ -package org.apache.qpid.server.flow; +package org.apache.qpid.server.protocol.v0_10; -public class CreditCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10 +import org.apache.qpid.server.flow.AbstractFlowCreditManager;public class CreditCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10 { private volatile long _bytesCredit; private volatile long _messageCredit; @@ -63,7 +63,7 @@ public class CreditCreditManager extends AbstractFlowCreditManager implements Fl { } - + public synchronized void addCredit(final long messageCredit, final long bytesCredit) { boolean notifyIncrease = true; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java index 8f3822be6c..4b38b8a1a3 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ExplicitAcceptDispositionChangeListener.java @@ -18,12 +18,11 @@ * under the License. * */ -package org.apache.qpid.server.subscription; +package org.apache.qpid.server.protocol.v0_10; import org.apache.log4j.Logger; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.transport.ServerSession; class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/FlowCreditManager_0_10.java index fea6eaf744..7f092814da 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/FlowCreditManager_0_10.java @@ -18,7 +18,9 @@ * under the License. * */ -package org.apache.qpid.server.flow; +package org.apache.qpid.server.protocol.v0_10; + +import org.apache.qpid.server.flow.FlowCreditManager; public interface FlowCreditManager_0_10 extends FlowCreditManager { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java index 826082cc65..ce0155b789 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ImplicitAcceptDispositionChangeListener.java @@ -18,12 +18,11 @@ * under the License. * */ -package org.apache.qpid.server.subscription; +package org.apache.qpid.server.protocol.v0_10; import org.apache.log4j.Logger; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.transport.ServerSession; class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDispositionChangeListener { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java index 8a2a370236..f5f2a8d43f 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/MessageAcceptCompletionListener.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageAcceptCompletionListener.java @@ -19,10 +19,9 @@ * */ -package org.apache.qpid.server.subscription; +package org.apache.qpid.server.protocol.v0_10; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.transport.ServerSession; import org.apache.qpid.transport.Method; public class MessageAcceptCompletionListener implements Method.CompletionListener diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java new file mode 100644 index 0000000000..c6ae0c6e47 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java @@ -0,0 +1,138 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_10; + +import java.nio.ByteBuffer; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageDeliveryPriority; +import org.apache.qpid.transport.MessageProperties; + +public class MessageConverter_v0_10 implements MessageConverter<ServerMessage, MessageTransferMessage> +{ + @Override + public Class<ServerMessage> getInputClass() + { + return ServerMessage.class; + } + + @Override + public Class<MessageTransferMessage> getOutputClass() + { + return MessageTransferMessage.class; + } + + @Override + public MessageTransferMessage convert(ServerMessage serverMsg, VirtualHost vhost) + { + return new MessageTransferMessage(convertToStoredMessage(serverMsg), null); + } + + private StoredMessage<MessageMetaData_0_10> convertToStoredMessage(final ServerMessage serverMsg) + { + final MessageMetaData_0_10 messageMetaData_0_10 = convertMetaData(serverMsg); + + return new StoredMessage<MessageMetaData_0_10>() + { + @Override + public MessageMetaData_0_10 getMetaData() + { + return messageMetaData_0_10; + } + + @Override + public long getMessageNumber() + { + return serverMsg.getMessageNumber(); + } + + @Override + public void addContent(int offsetInMessage, ByteBuffer src) + { + throw new UnsupportedOperationException(); + } + + @Override + public int getContent(int offsetInMessage, ByteBuffer dst) + { + return serverMsg.getContent(dst, offsetInMessage); + } + + @Override + public ByteBuffer getContent(int offsetInMessage, int size) + { + return serverMsg.getContent(offsetInMessage, size); + } + + @Override + public StoreFuture flushToStore() + { + return StoreFuture.IMMEDIATE_FUTURE; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } + + private MessageMetaData_0_10 convertMetaData(ServerMessage serverMsg) + { + DeliveryProperties deliveryProps = new DeliveryProperties(); + MessageProperties messageProps = new MessageProperties(); + + int size = (int) serverMsg.getSize(); + ByteBuffer body = ByteBuffer.allocate(size); + serverMsg.getContent(body, 0); + body.flip(); + + + deliveryProps.setExpiration(serverMsg.getExpiration()); + deliveryProps.setImmediate(serverMsg.isImmediate()); + deliveryProps.setPriority(MessageDeliveryPriority.get(serverMsg.getMessageHeader().getPriority())); + deliveryProps.setRoutingKey(serverMsg.getRoutingKey()); + deliveryProps.setTimestamp(serverMsg.getMessageHeader().getTimestamp()); + + messageProps.setContentEncoding(serverMsg.getMessageHeader().getEncoding()); + messageProps.setContentLength(size); + messageProps.setContentType(serverMsg.getMessageHeader().getMimeType()); + if(serverMsg.getMessageHeader().getCorrelationId() != null) + { + messageProps.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId().getBytes()); + } + + Header header = new Header(deliveryProps, messageProps, null); + return new MessageMetaData_0_10(header, size, serverMsg.getArrivalTime()); + } + + @Override + public String getType() + { + return "Unknown to v0-10"; + } +} diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaDataType_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaDataType_0_10.java new file mode 100644 index 0000000000..90fb443f5b --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaDataType_0_10.java @@ -0,0 +1,67 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_10; + +import java.nio.ByteBuffer; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.plugin.MessageMetaDataType; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.store.StoredMessage; + +public class MessageMetaDataType_0_10 implements MessageMetaDataType<MessageMetaData_0_10> +{ + + public static final int TYPE = 1; + + @Override + public int ordinal() + { + return TYPE; + } + + @Override + public MessageMetaData_0_10 createMetaData(ByteBuffer buf) + { + return MessageMetaData_0_10.FACTORY.createMetaData(buf); + } + + @Override + public ServerMessage<MessageMetaData_0_10> createMessage(StoredMessage<MessageMetaData_0_10> msg) + { + return new MessageTransferMessage(msg, null); + } + + public int hashCode() + { + return ordinal(); + } + + public boolean equals(Object o) + { + return o != null && o.getClass() == getClass(); + } + + @Override + public String getType() + { + return AmqpProtocolVersion.v0_10.toString(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java index 88b0f60346..092ea7c3c9 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java @@ -18,10 +18,12 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v0_10; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.plugin.MessageMetaDataType; import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.transport.DeliveryProperties; import org.apache.qpid.transport.Header; @@ -49,6 +51,8 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes public static final MessageMetaDataType.Factory<MessageMetaData_0_10> FACTORY = new MetaDataFactory(); + private static final MessageMetaDataType_0_10 TYPE = new MessageMetaDataType_0_10(); + private volatile ByteBuffer _encoded; private Object _connectionReference; @@ -58,7 +62,7 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes this(xfr.getHeader(), xfr.getBodySize(), System.currentTimeMillis()); } - private MessageMetaData_0_10(Header header, int bodySize, long arrivalTime) + public MessageMetaData_0_10(Header header, int bodySize, long arrivalTime) { _header = header; if(_header != null) @@ -81,7 +85,7 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes public MessageMetaDataType getType() { - return MessageMetaDataType.META_DATA_0_10; + return TYPE; } public int getStorableSize() @@ -178,11 +182,6 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMes return _deliveryProps == null ? null : _deliveryProps.getRoutingKey(); } - public AMQShortString getRoutingKeyShortString() - { - return AMQShortString.valueOf(getRoutingKey()); - } - public AMQMessageHeader getMessageHeader() { return _messageHeader; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferHeader.java index 91384f7c22..1b506d9bf8 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferHeader.java @@ -18,9 +18,10 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v0_10; import java.util.*; +import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.transport.DeliveryProperties; import org.apache.qpid.transport.MessageDeliveryPriority; import org.apache.qpid.transport.MessageProperties; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java index 8350eccec1..e5914d1d4e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferMessage.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java @@ -18,9 +18,13 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v0_10; import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.AbstractServerMessageImpl; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.transport.Header; @@ -48,11 +52,6 @@ public class MessageTransferMessage extends AbstractServerMessageImpl<MessageMet return getMetaData().getRoutingKey(); } - public AMQShortString getRoutingKeyShortString() - { - return AMQShortString.valueOf(getRoutingKey()); - } - public AMQMessageHeader getMessageHeader() { return getMetaData().getMessageHeader(); diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngineCreator_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngineCreator_0_10.java new file mode 100644 index 0000000000..ab50a33b9b --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngineCreator_0_10.java @@ -0,0 +1,100 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_10; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.plugin.ProtocolEngineCreator; +import org.apache.qpid.transport.ConnectionDelegate; +import org.apache.qpid.transport.network.NetworkConnection; + +public class ProtocolEngineCreator_0_10 implements ProtocolEngineCreator +{ + + private static final byte[] AMQP_0_10_HEADER = + new byte[] { (byte) 'A', + (byte) 'M', + (byte) 'Q', + (byte) 'P', + (byte) 1, + (byte) 1, + (byte) 0, + (byte) 10 + }; + + + public ProtocolEngineCreator_0_10() + { + } + + public AmqpProtocolVersion getVersion() + { + return AmqpProtocolVersion.v0_10; + } + + + public byte[] getHeaderIdentifier() + { + return AMQP_0_10_HEADER; + } + + public ServerProtocolEngine newProtocolEngine(Broker broker, + NetworkConnection network, + Port port, + Transport transport, + long id) + { + String fqdn = null; + SocketAddress address = network.getLocalAddress(); + if (address instanceof InetSocketAddress) + { + fqdn = ((InetSocketAddress) address).getHostName(); + } + final ConnectionDelegate connDelegate = new ServerConnectionDelegate(broker, + fqdn, broker.getSubjectCreator(address)); + + ServerConnection conn = new ServerConnection(id,broker); + + conn.setConnectionDelegate(connDelegate); + conn.setRemoteAddress(network.getRemoteAddress()); + conn.setLocalAddress(network.getLocalAddress()); + return new ProtocolEngine_0_10( conn, network, port, transport); + } + + + private static ProtocolEngineCreator INSTANCE = new ProtocolEngineCreator_0_10(); + + public static ProtocolEngineCreator getInstance() + { + return INSTANCE; + } + + @Override + public String getType() + { + return getVersion().toString(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java index 8275ab690c..73708d9841 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java @@ -18,13 +18,13 @@ * under the License. * */ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.protocol.v0_10; import org.apache.qpid.protocol.ServerProtocolEngine; import org.apache.qpid.server.logging.messages.ConnectionMessages; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.transport.ServerConnection; +import org.apache.qpid.server.protocol.v0_10.ServerConnection; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.Assembler; import org.apache.qpid.transport.network.Disassembler; @@ -49,7 +49,9 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol private long _lastWriteTime; public ProtocolEngine_0_10(ServerConnection conn, - NetworkConnection network, Port port, Transport transport) + NetworkConnection network, + Port port, + Transport transport) { super(new Assembler(conn)); _connection = conn; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java index 3a2cb7556d..0015988ab7 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.transport; +package org.apache.qpid.server.protocol.v0_10; import java.net.SocketAddress; import java.security.Principal; @@ -32,9 +32,11 @@ import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.AMQPConnectionActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.logging.messages.ConnectionMessages; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.protocol.AMQConnectionModel; @@ -60,7 +62,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, { private Runnable _onOpenTask; private AtomicBoolean _logClosed = new AtomicBoolean(false); - private LogActor _actor = GenericActor.getInstance(this); + private LogActor _actor; private Subject _authorizedSubject = null; private Principal _authorizedPrincipal = null; @@ -76,9 +78,10 @@ public class ServerConnection extends Connection implements AMQConnectionModel, private Transport _transport; private volatile boolean _stopped; - public ServerConnection(final long connectionId) + public ServerConnection(final long connectionId, Broker broker) { _connectionId = connectionId; + _actor = new AMQPConnectionActor(this, broker.getRootMessageLogger()); } public Object getReference() @@ -154,6 +157,12 @@ public class ServerConnection extends Connection implements AMQConnectionModel, } @Override + public String getVirtualHostName() + { + return _virtualHost == null ? null : _virtualHost.getName(); + } + + @Override public Port getPort() { return _port; @@ -503,7 +512,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, public String getPrincipalAsString() { - return getAuthorizedPrincipal().getName(); + return getAuthorizedPrincipal() == null ? null : getAuthorizedPrincipal().getName(); } public long getSessionCountLimit() diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java index 4170f36771..6634627805 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.transport; +package org.apache.qpid.server.protocol.v0_10; import java.util.ArrayList; import java.util.Collection; @@ -40,7 +40,6 @@ import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; -import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.virtualhost.State; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.*; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java index 3449cc5237..abe784cefa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSession.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.transport; +package org.apache.qpid.server.protocol.v0_10; import java.security.Principal; import java.text.MessageFormat; @@ -54,9 +54,7 @@ import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.logging.messages.ChannelMessages; import org.apache.qpid.server.logging.subjects.ChannelLogSubject; import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageMetaData_0_10; import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; @@ -66,7 +64,6 @@ import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.security.AuthorizationHolder; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StoreFuture; -import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.txn.AlreadyKnownDtxException; import org.apache.qpid.server.txn.AsyncAutoCommitTransaction; import org.apache.qpid.server.txn.DistributedTransaction; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java index b7ac86795d..46626e3e92 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java @@ -18,41 +18,32 @@ * under the License. * */ -package org.apache.qpid.server.transport; +package org.apache.qpid.server.protocol.v0_10; +import java.util.LinkedHashMap; +import java.util.UUID; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.AMQStoreException; import org.apache.qpid.AMQUnknownExchangeType; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeInUseException; -import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.exchange.HeadersExchange; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.FilterManagerFactory; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.flow.WindowCreditManager; import org.apache.qpid.server.logging.messages.ExchangeMessages; -import org.apache.qpid.server.message.MessageMetaData_0_10; -import org.apache.qpid.server.message.MessageTransferMessage; +import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.store.DurableConfigurationStoreHelper; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StoreFuture; import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.txn.AlreadyKnownDtxException; import org.apache.qpid.server.txn.DtxNotSelectedException; import org.apache.qpid.server.txn.IncorrectDtxStateException; @@ -69,6 +60,7 @@ import org.apache.qpid.server.virtualhost.RequiredExchangeException; import org.apache.qpid.server.virtualhost.ReservedExchangeNameException; import org.apache.qpid.server.virtualhost.UnknownExchangeException; import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.server.virtualhost.plugins.QueueExistsException; import org.apache.qpid.transport.*; import java.nio.ByteBuffer; @@ -80,11 +72,6 @@ public class ServerSessionDelegate extends SessionDelegate { private static final Logger LOGGER = Logger.getLogger(ServerSessionDelegate.class); - /** - * No-local queue argument is used to support the no-local feature of Durable Subscribers. - */ - private static final String QUEUE_ARGUMENT_NO_LOCAL = "no-local"; - public ServerSessionDelegate() { @@ -203,10 +190,9 @@ public class ServerSessionDelegate extends SessionDelegate else { String queueName = method.getQueue(); - QueueRegistry queueRegistry = getQueueRegistry(session); + VirtualHost vhost = getVirtualHost(session); - - final AMQQueue queue = queueRegistry.getQueue(queueName); + final AMQQueue queue = vhost.getQueue(queueName); if(queue == null) { @@ -257,7 +243,7 @@ public class ServerSessionDelegate extends SessionDelegate return; } - Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session, + Subscription_0_10 sub = new Subscription_0_10((ServerSession)session, destination, method.getAcceptMode(), method.getAcquireMode(), @@ -712,11 +698,11 @@ public class ServerSessionDelegate extends SessionDelegate } else { - if (!exchange.getTypeShortString().toString().equals(method.getType()) + if (!exchange.getTypeName().equals(method.getType()) && (method.getType() != null && method.getType().length() > 0)) { exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to redeclare exchange: " - + exchangeName + " of type " + exchange.getTypeShortString() + " to " + method.getType() + "."); + + exchangeName + " of type " + exchange.getTypeName() + " to " + method.getType() + "."); } } } @@ -749,11 +735,11 @@ public class ServerSessionDelegate extends SessionDelegate catch(ExchangeExistsException e) { Exchange exchange = e.getExistingExchange(); - if(!exchange.getTypeShortString().toString().equals(method.getType())) + if(!exchange.getTypeName().equals(method.getType())) { exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Attempt to redeclare exchange: " + exchangeName - + " of type " + exchange.getTypeShortString() + + " of type " + exchange.getTypeName() + " to " + method.getType() +"."); } else if(method.hasAlternateExchange() @@ -902,7 +888,7 @@ public class ServerSessionDelegate extends SessionDelegate { for(ExchangeType type : registeredTypes) { - if(type.getDefaultExchangeName().toString().equals( exchange.getName() )) + if(type.getDefaultExchangeName().equals( exchange.getName() )) { return true; } @@ -921,7 +907,7 @@ public class ServerSessionDelegate extends SessionDelegate if(exchange != null) { result.setDurable(exchange.isDurable()); - result.setType(exchange.getTypeShortString().toString()); + result.setType(exchange.getTypeName()); result.setNotFound(false); } else @@ -937,7 +923,6 @@ public class ServerSessionDelegate extends SessionDelegate { VirtualHost virtualHost = getVirtualHost(session); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); if (!method.hasQueue()) { @@ -955,7 +940,7 @@ public class ServerSessionDelegate extends SessionDelegate { method.setBindingKey(method.getQueue()); } - AMQQueue queue = queueRegistry.getQueue(method.getQueue()); + AMQQueue queue = virtualHost.getQueue(method.getQueue()); Exchange exchange = virtualHost.getExchange(method.getExchange()); if(queue == null) { @@ -965,9 +950,9 @@ public class ServerSessionDelegate extends SessionDelegate { exception(session, method, ExecutionErrorCode.NOT_FOUND, "Exchange: '" + method.getExchange() + "' not found"); } - else if(exchange.getTypeShortString().equals(HeadersExchange.TYPE.getName()) && (!method.hasArguments() || method.getArguments() == null || !method.getArguments().containsKey("x-match"))) + else if(exchange.getType().equals(HeadersExchange.TYPE) && (!method.hasArguments() || method.getArguments() == null || !method.getArguments().containsKey("x-match"))) { - exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Bindings to an exchange of type " + HeadersExchange.TYPE.getName() + " require an x-match header"); + exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Bindings to an exchange of type " + HeadersExchange.TYPE.getType() + " require an x-match header"); } else { @@ -999,7 +984,6 @@ public class ServerSessionDelegate extends SessionDelegate public void exchangeUnbind(Session session, ExchangeUnbind method) { VirtualHost virtualHost = getVirtualHost(session); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); if (!method.hasQueue()) { @@ -1015,7 +999,7 @@ public class ServerSessionDelegate extends SessionDelegate } else { - AMQQueue queue = queueRegistry.getQueue(method.getQueue()); + AMQQueue queue = virtualHost.getQueue(method.getQueue()); Exchange exchange = virtualHost.getExchange(method.getExchange()); if(queue == null) { @@ -1182,158 +1166,137 @@ public class ServerSessionDelegate extends SessionDelegate private AMQQueue getQueue(Session session, String queue) { - QueueRegistry queueRegistry = getQueueRegistry(session); - return queueRegistry.getQueue(queue); - } - - private QueueRegistry getQueueRegistry(Session session) - { - return getVirtualHost(session).getQueueRegistry(); + return getVirtualHost(session).getQueue(queue); } @Override public void queueDeclare(Session session, final QueueDeclare method) { - VirtualHost virtualHost = getVirtualHost(session); + final VirtualHost virtualHost = getVirtualHost(session); DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); String queueName = method.getQueue(); AMQQueue queue; - QueueRegistry queueRegistry = getQueueRegistry(session); //TODO: do we need to check that the queue already exists with exactly the same "configuration"? - synchronized (queueRegistry) + final boolean exclusive = method.getExclusive(); + final boolean autoDelete = method.getAutoDelete(); + + if(method.getPassive()) { + queue = virtualHost.getQueue(queueName); - if (((queue = queueRegistry.getQueue(queueName)) == null)) + if (queue == null) { + String description = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ")."; + ExecutionErrorCode errorCode = ExecutionErrorCode.NOT_FOUND; - if (method.getPassive()) - { - String description = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ")."; - ExecutionErrorCode errorCode = ExecutionErrorCode.NOT_FOUND; + exception(session, method, errorCode, description); - exception(session, method, errorCode, description); + } + else if (exclusive && (queue.getExclusiveOwningSession() != null && !queue.getExclusiveOwningSession().equals(session))) + { + String description = "Cannot declare queue('" + queueName + "')," + + " as exclusive queue with same name " + + "declared on another session"; + ExecutionErrorCode errorCode = ExecutionErrorCode.RESOURCE_LOCKED; - return; - } - else + exception(session, method, errorCode, description); + + } + } + else + { + + try + { + + String owner = method.getExclusive() ? ((ServerSession)session).getClientID() : null; + final String alternateExchangeName = method.getAlternateExchange(); + + + final Map<String, Object> arguments = QueueArgumentsConverter.convertWireArgsToModel(method.getArguments()); + + if(alternateExchangeName != null && alternateExchangeName.length() != 0) { - try - { - queue = createQueue(queueName, method, virtualHost, (ServerSession)session); - if(!method.getExclusive() && method.getAutoDelete()) - { - queue.setDeleteOnNoConsumers(true); - } + arguments.put(Queue.ALTERNATE_EXCHANGE, alternateExchangeName); + } - final String alternateExchangeName = method.getAlternateExchange(); - if(alternateExchangeName != null && alternateExchangeName.length() != 0) - { - Exchange alternate = getExchange(session, alternateExchangeName); - queue.setAlternateExchange(alternate); - } + final UUID id = UUIDGenerator.generateQueueUUID(queueName, virtualHost.getName()); - if(method.hasArguments() && method.getArguments() != null) - { - if(method.getArguments().containsKey(QUEUE_ARGUMENT_NO_LOCAL)) - { - Object noLocal = method.getArguments().get(QUEUE_ARGUMENT_NO_LOCAL); - queue.setNoLocal(convertBooleanValue(noLocal)); - } - } + final boolean deleteOnNoConsumer = !exclusive && autoDelete; + queue = virtualHost.createQueue(id, queueName, method.getDurable(), owner, + autoDelete, exclusive, deleteOnNoConsumer, + arguments); - if (queue.isDurable() && !queue.isAutoDelete()) + if (autoDelete && exclusive) + { + final AMQQueue q = queue; + final ServerSession.Task deleteQueueTask = new ServerSession.Task() { - if(method.hasArguments() && method.getArguments() != null) + public void doTask(ServerSession session) { - Map<String,Object> args = method.getArguments(); - FieldTable ftArgs = new FieldTable(); - for(Map.Entry<String, Object> entry : args.entrySet()) + try + { + virtualHost.removeQueue(q); + } + catch (AMQException e) { - ftArgs.put(new AMQShortString(entry.getKey()), entry.getValue()); + exception(session, method, e, "Cannot delete '" + method.getQueue()); } - DurableConfigurationStoreHelper.createQueue(store, queue, ftArgs); } - else + }; + final ServerSession s = (ServerSession) session; + s.addSessionCloseTask(deleteQueueTask); + queue.addQueueDeleteTask(new AMQQueue.Task() + { + public void doTask(AMQQueue queue) throws AMQException { - DurableConfigurationStoreHelper.createQueue(store, queue, null); + s.removeSessionCloseTask(deleteQueueTask); } - } - queueRegistry.registerQueue(queue); - - if (method.hasAutoDelete() - && method.getAutoDelete() - && method.hasExclusive() - && method.getExclusive()) + }); + } + if (exclusive) + { + final AMQQueue q = queue; + final ServerSession.Task removeExclusive = new ServerSession.Task() + { + public void doTask(ServerSession session) { - final AMQQueue q = queue; - final ServerSession.Task deleteQueueTask = new ServerSession.Task() - { - public void doTask(ServerSession session) - { - try - { - q.delete(); - } - catch (AMQException e) - { - exception(session, method, e, "Cannot delete '" + method.getQueue()); - } - } - }; - final ServerSession s = (ServerSession) session; - s.addSessionCloseTask(deleteQueueTask); - queue.addQueueDeleteTask(new AMQQueue.Task() - { - public void doTask(AMQQueue queue) throws AMQException - { - s.removeSessionCloseTask(deleteQueueTask); - } - }); + q.setAuthorizationHolder(null); + q.setExclusiveOwningSession(null); } - if (method.hasExclusive() - && method.getExclusive()) + }; + final ServerSession s = (ServerSession) session; + q.setExclusiveOwningSession(s); + s.addSessionCloseTask(removeExclusive); + queue.addQueueDeleteTask(new AMQQueue.Task() + { + public void doTask(AMQQueue queue) throws AMQException { - final AMQQueue q = queue; - final ServerSession.Task removeExclusive = new ServerSession.Task() - { - public void doTask(ServerSession session) - { - q.setAuthorizationHolder(null); - q.setExclusiveOwningSession(null); - } - }; - final ServerSession s = (ServerSession) session; - q.setExclusiveOwningSession(s); - s.addSessionCloseTask(removeExclusive); - queue.addQueueDeleteTask(new AMQQueue.Task() - { - public void doTask(AMQQueue queue) throws AMQException - { - s.removeSessionCloseTask(removeExclusive); - } - }); + s.removeSessionCloseTask(removeExclusive); } - } - catch (AMQException e) - { - exception(session, method, e, "Cannot declare queue '" + queueName); - } + }); } } - else if (method.getExclusive() && (queue.getExclusiveOwningSession() != null && !queue.getExclusiveOwningSession().equals(session))) + catch(QueueExistsException qe) { + queue = qe.getExistingQueue(); + if (exclusive && (queue.getExclusiveOwningSession() != null && !queue.getExclusiveOwningSession().equals(session))) + { String description = "Cannot declare queue('" + queueName + "')," + " as exclusive queue with same name " + "declared on another session"; ExecutionErrorCode errorCode = ExecutionErrorCode.RESOURCE_LOCKED; exception(session, method, errorCode, description); - - return; + } + } + catch (AMQException e) + { + exception(session, method, e, "Cannot declare queue '" + queueName); } } } @@ -1362,20 +1325,6 @@ public class ServerSessionDelegate extends SessionDelegate return false; } - protected AMQQueue createQueue(final String queueName, - final QueueDeclare body, - VirtualHost virtualHost, - final ServerSession session) - throws AMQException - { - String owner = body.getExclusive() ? session.getClientID() : null; - - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueName, virtualHost.getName()), queueName, body.getDurable(), owner, - body.getAutoDelete(), body.getExclusive(), virtualHost, body.getArguments()); - - return queue; - } - @Override public void queueDelete(Session session, QueueDelete method) { @@ -1420,12 +1369,7 @@ public class ServerSessionDelegate extends SessionDelegate try { - queue.delete(); - if (queue.isDurable() && !queue.isAutoDelete()) - { - DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); - DurableConfigurationStoreHelper.removeQueue(store,queue); - } + virtualHost.removeQueue(queue); } catch (AMQException e) { @@ -1475,11 +1419,18 @@ public class ServerSessionDelegate extends SessionDelegate if(queue != null) { - result.setQueue(queue.getNameShortString().toString()); + result.setQueue(queue.getName()); result.setDurable(queue.isDurable()); result.setExclusive(queue.isExclusive()); result.setAutoDelete(queue.isAutoDelete()); - result.setArguments(queue.getArguments()); + Map<String, Object> arguments = new LinkedHashMap<String, Object>(); + Collection<String> availableAttrs = queue.getAvailableAttributes(); + + for(String attrName : availableAttrs) + { + arguments.put(attrName, queue.getAttribute(attrName)); + } + result.setArguments(QueueArgumentsConverter.convertModelArgsToWire(arguments)); result.setMessageCount(queue.getMessageCount()); result.setSubscriberCount(queue.getConsumerCount()); @@ -1499,7 +1450,7 @@ public class ServerSessionDelegate extends SessionDelegate if(sub == null) { - exception(session, sfm, ExecutionErrorCode.NOT_FOUND, "not-found: destination '"+destination+"'"); + exception(session, sfm, ExecutionErrorCode.NOT_FOUND, "not-found: destination '" + destination + "'"); } else if(sub.isStopped()) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java index 2f237f0f3a..77b63906cc 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/Subscription_0_10.java @@ -18,33 +18,29 @@ * under the License. * */ -package org.apache.qpid.server.subscription; +package org.apache.qpid.server.protocol.v0_10; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.filter.FilterManager; -import org.apache.qpid.server.flow.CreditCreditManager; import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.flow.WindowCreditManager; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.logging.messages.ChannelMessages; import org.apache.qpid.server.logging.messages.SubscriptionMessages; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.protocol.MessageConverterRegistry; import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.InboundMessageAdapter; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.transport.DeliveryProperties; @@ -52,28 +48,22 @@ import org.apache.qpid.transport.Header; import org.apache.qpid.transport.MessageAcceptMode; import org.apache.qpid.transport.MessageAcquireMode; import org.apache.qpid.transport.MessageCreditUnit; -import org.apache.qpid.transport.MessageDeliveryPriority; import org.apache.qpid.transport.MessageFlowMode; import org.apache.qpid.transport.MessageProperties; import org.apache.qpid.transport.MessageTransfer; import org.apache.qpid.transport.Method; import org.apache.qpid.transport.Option; -import org.apache.qpid.transport.ReplyTo; import org.apache.qpid.transport.Struct; -import org.apache.qpid.url.AMQBindingURL; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.QUEUE_FORMAT; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SUBSCRIPTION_FORMAT; -import java.net.URISyntaxException; -import java.nio.ByteBuffer; import java.text.MessageFormat; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -136,9 +126,9 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr MessageAcquireMode acquireMode, MessageFlowMode flowMode, FlowCreditManager_0_10 creditManager, - FilterManager filters,Map<String, Object> arguments, long subscriptionId) + FilterManager filters,Map<String, Object> arguments) { - _subscriptionID = subscriptionId; + _subscriptionID = SUB_ID_GENERATOR.getAndIncrement(); _session = session; _postIdSettingAction = new AddMessageDispositionListenerAction(session); _destination = destination; @@ -177,9 +167,8 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } _queue = queue; - Map<String, Object> arguments = queue.getArguments(); - _traceExclude = (String) arguments.get("qpid.trace.exclude"); - _trace = (String) arguments.get("qpid.trace.id"); + _traceExclude = (String) queue.getAttribute(Queue.FEDERATION_EXCLUDES); + _trace = (String) queue.getAttribute(Queue.FEDERATION_ID); String filterLogString = null; _logActor = GenericActor.getInstance(this); @@ -213,10 +202,21 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return false; } - if (_noLocal && entry.getMessage() instanceof MessageTransferMessage) + if (entry.getMessage() instanceof MessageTransferMessage) { - Object connectionRef = ((MessageTransferMessage)entry.getMessage()).getConnectionReference(); - if (connectionRef != null && connectionRef == _session.getReference()) + if(_noLocal) + { + Object connectionRef = ((MessageTransferMessage)entry.getMessage()).getConnectionReference(); + if (connectionRef != null && connectionRef == _session.getReference()) + { + return false; + } + } + } + else + { + // no interest in messages we can't convert + if(MessageConverterRegistry.getConverter(entry.getMessage().getClass(), MessageTransferMessage.class)==null) { return false; } @@ -352,200 +352,72 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr DeliveryProperties deliveryProps; MessageProperties messageProps = null; + MessageTransferMessage msg; + if(serverMsg instanceof MessageTransferMessage) { - MessageTransferMessage msg = (MessageTransferMessage) serverMsg; - DeliveryProperties origDeliveryProps = msg.getHeader() == null ? null : msg.getHeader().getDeliveryProperties(); - messageProps = msg.getHeader() == null ? null : msg.getHeader().getMessageProperties(); - - deliveryProps = new DeliveryProperties(); - if(origDeliveryProps != null) - { - if(origDeliveryProps.hasDeliveryMode()) - { - deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode()); - } - if(origDeliveryProps.hasExchange()) - { - deliveryProps.setExchange(origDeliveryProps.getExchange()); - } - if(origDeliveryProps.hasExpiration()) - { - deliveryProps.setExpiration(origDeliveryProps.getExpiration()); - } - if(origDeliveryProps.hasPriority()) - { - deliveryProps.setPriority(origDeliveryProps.getPriority()); - } - if(origDeliveryProps.hasRoutingKey()) - { - deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey()); - } - if(origDeliveryProps.hasTimestamp()) - { - deliveryProps.setTimestamp(origDeliveryProps.getTimestamp()); - } - if(origDeliveryProps.hasTtl()) - { - deliveryProps.setTtl(origDeliveryProps.getTtl()); - } - + msg = (MessageTransferMessage) serverMsg; - } - - deliveryProps.setRedelivered(entry.isRedelivered()); - - if(_trace != null && messageProps == null) - { - messageProps = new MessageProperties(); - } - - Header header = new Header(deliveryProps, messageProps, msg.getHeader() == null ? null : msg.getHeader().getNonStandardProperties()); - - - xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody(), BATCHED) - : new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); } - else if(serverMsg instanceof AMQMessage) + else { - AMQMessage message_0_8 = (AMQMessage) serverMsg; - deliveryProps = new DeliveryProperties(); - messageProps = new MessageProperties(); + MessageConverter converter = + MessageConverterRegistry.getConverter(serverMsg.getClass(), MessageTransferMessage.class); + - int size = (int) message_0_8.getSize(); - ByteBuffer body = ByteBuffer.allocate(size); - message_0_8.getContent(body, 0); - body.flip(); + msg = (MessageTransferMessage) converter.convert(serverMsg, getQueue().getVirtualHost()); + } + DeliveryProperties origDeliveryProps = msg.getHeader() == null ? null : msg.getHeader().getDeliveryProperties(); + messageProps = msg.getHeader() == null ? null : msg.getHeader().getMessageProperties(); - BasicContentHeaderProperties properties = - (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().getProperties(); - final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange(); - if(exchange != null) + deliveryProps = new DeliveryProperties(); + if(origDeliveryProps != null) + { + if(origDeliveryProps.hasDeliveryMode()) { - deliveryProps.setExchange(exchange.toString()); + deliveryProps.setDeliveryMode(origDeliveryProps.getDeliveryMode()); } - deliveryProps.setExpiration(message_0_8.getExpiration()); - deliveryProps.setImmediate(message_0_8.isImmediate()); - deliveryProps.setPriority(MessageDeliveryPriority.get(properties.getPriority())); - deliveryProps.setRedelivered(entry.isRedelivered()); - deliveryProps.setRoutingKey(message_0_8.getRoutingKey()); - deliveryProps.setTimestamp(properties.getTimestamp()); - - messageProps.setContentEncoding(properties.getEncodingAsString()); - messageProps.setContentLength(size); - if(properties.getAppId() != null) + if(origDeliveryProps.hasExchange()) { - messageProps.setAppId(properties.getAppId().getBytes()); + deliveryProps.setExchange(origDeliveryProps.getExchange()); } - messageProps.setContentType(properties.getContentTypeAsString()); - if(properties.getCorrelationId() != null) + if(origDeliveryProps.hasExpiration()) { - messageProps.setCorrelationId(properties.getCorrelationId().getBytes()); + deliveryProps.setExpiration(origDeliveryProps.getExpiration()); } - - if(properties.getReplyTo() != null && properties.getReplyTo().length() != 0) + if(origDeliveryProps.hasPriority()) { - String origReplyToString = properties.getReplyTo().asString(); - ReplyTo replyTo = new ReplyTo(); - // if the string looks like a binding URL, then attempt to parse it... - try - { - AMQBindingURL burl = new AMQBindingURL(origReplyToString); - AMQShortString routingKey = burl.getRoutingKey(); - if(routingKey != null) - { - replyTo.setRoutingKey(routingKey.asString()); - } - - AMQShortString exchangeName = burl.getExchangeName(); - if(exchangeName != null) - { - replyTo.setExchange(exchangeName.asString()); - } - } - catch (URISyntaxException e) - { - replyTo.setRoutingKey(origReplyToString); - } - messageProps.setReplyTo(replyTo); - + deliveryProps.setPriority(origDeliveryProps.getPriority()); } - - if(properties.getMessageId() != null) + if(origDeliveryProps.hasRoutingKey()) { - try - { - String messageIdAsString = properties.getMessageIdAsString(); - if(messageIdAsString.startsWith("ID:")) - { - messageIdAsString = messageIdAsString.substring(3); - } - UUID uuid = UUID.fromString(messageIdAsString); - messageProps.setMessageId(uuid); - } - catch(IllegalArgumentException e) - { - // ignore - can't parse - } + deliveryProps.setRoutingKey(origDeliveryProps.getRoutingKey()); } - - - - if(properties.getUserId() != null) + if(origDeliveryProps.hasTimestamp()) { - messageProps.setUserId(properties.getUserId().getBytes()); + deliveryProps.setTimestamp(origDeliveryProps.getTimestamp()); } - - FieldTable fieldTable = properties.getHeaders(); - - Map<String, Object> appHeaders = FieldTable.convertToMap(fieldTable); - - if(properties.getType() != null) + if(origDeliveryProps.hasTtl()) { - appHeaders.put("x-jms-type", properties.getTypeAsString()); + deliveryProps.setTtl(origDeliveryProps.getTtl()); } - messageProps.setApplicationHeaders(appHeaders); - - Header header = new Header(deliveryProps, messageProps, null); - xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body, BATCHED) - : new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); } - else - { - - deliveryProps = new DeliveryProperties(); - messageProps = new MessageProperties(); - - int size = (int) serverMsg.getSize(); - ByteBuffer body = ByteBuffer.allocate(size); - serverMsg.getContent(body, 0); - body.flip(); + deliveryProps.setRedelivered(entry.isRedelivered()); - deliveryProps.setExpiration(serverMsg.getExpiration()); - deliveryProps.setImmediate(serverMsg.isImmediate()); - deliveryProps.setPriority(MessageDeliveryPriority.get(serverMsg.getMessageHeader().getPriority())); - deliveryProps.setRedelivered(entry.isRedelivered()); - deliveryProps.setRoutingKey(serverMsg.getRoutingKey()); - deliveryProps.setTimestamp(serverMsg.getMessageHeader().getTimestamp()); + if(_trace != null && messageProps == null) + { + messageProps = new MessageProperties(); + } - messageProps.setContentEncoding(serverMsg.getMessageHeader().getEncoding()); - messageProps.setContentLength(size); - messageProps.setContentType(serverMsg.getMessageHeader().getMimeType()); - if(serverMsg.getMessageHeader().getCorrelationId() != null) - { - messageProps.setCorrelationId(serverMsg.getMessageHeader().getCorrelationId().getBytes()); - } + Header header = new Header(deliveryProps, messageProps, msg.getHeader() == null ? null : msg.getHeader().getNonStandardProperties()); - // TODO - ReplyTo - Header header = new Header(deliveryProps, messageProps, null); - xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body, BATCHED) - : new MessageTransfer(_destination,_acceptMode,_acquireMode,header, body); - } + xfr = batch ? new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody(), BATCHED) + : new MessageTransfer(_destination,_acceptMode,_acquireMode,header,msg.getBody()); boolean excludeDueToFederation = false; @@ -728,7 +600,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr //output operational logging for each delivery post commit for (final BaseQueue destinationQueue : destinationQueues) { - logActor.message( ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(), destinationQueue.getNameShortString().asString())); + logActor.message( ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(), destinationQueue.getName())); } } } @@ -1003,7 +875,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr public String toLogString() { String queueInfo = MessageFormat.format(QUEUE_FORMAT, _queue.getVirtualHost().getName(), - _queue.getNameShortString()); + _queue.getName()); String result = "[" + MessageFormat.format(SUBSCRIPTION_FORMAT, getSubscriptionID()) + "(" // queueString is "vh(/{0})/qu({1}) " so need to trim + queueInfo.substring(0, queueInfo.length() - 1) + ")" + "] "; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/TransferMessageReference.java index cb44f80b91..0c04f22232 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/TransferMessageReference.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/TransferMessageReference.java @@ -18,7 +18,9 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v0_10; + +import org.apache.qpid.server.message.MessageReference; public class TransferMessageReference extends MessageReference<MessageTransferMessage> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java index 2215c7bb3d..8e48741b91 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/flow/WindowCreditManager.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManager.java @@ -18,9 +18,10 @@ * under the License. * */ -package org.apache.qpid.server.flow; +package org.apache.qpid.server.protocol.v0_10; import org.apache.log4j.Logger; +import org.apache.qpid.server.flow.AbstractFlowCreditManager; public class WindowCreditManager extends AbstractFlowCreditManager implements FlowCreditManager_0_10 { diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter new file mode 100644 index 0000000000..995b0fabdc --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter @@ -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.protocol.v0_10.MessageConverter_v0_10 diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType new file mode 100644 index 0000000000..36118fe053 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.protocol.v0_10.MessageMetaDataType_0_10 diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator new file mode 100644 index 0000000000..3d94e26671 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator @@ -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.protocol.v0_10.ProtocolEngineCreator_0_10 diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/test/java/org/apache/qpid/server/protocol/v0_10/ServerSessionTest.java index 3389773ff8..421adb33a8 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/transport/ServerSessionTest.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/test/java/org/apache/qpid/server/protocol/v0_10/ServerSessionTest.java @@ -16,15 +16,20 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.qpid.server.transport; +package org.apache.qpid.server.protocol.v0_10; +import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.GenericActor; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.transport.Binary; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class ServerSessionTest extends QpidTestCase { @@ -58,13 +63,15 @@ public class ServerSessionTest extends QpidTestCase public void testCompareTo() throws Exception { - ServerConnection connection = new ServerConnection(1); + final Broker broker = mock(Broker.class); + when(broker.getRootMessageLogger()).thenReturn(mock(RootMessageLogger.class)); + ServerConnection connection = new ServerConnection(1, broker); connection.setVirtualHost(_virtualHost); ServerSession session1 = new ServerSession(connection, new ServerSessionDelegate(), new Binary(getName().getBytes()), 0); // create a session with the same name but on a different connection - ServerConnection connection2 = new ServerConnection(2); + ServerConnection connection2 = new ServerConnection(2, broker); connection2.setVirtualHost(_virtualHost); ServerSession session2 = new ServerSession(connection2, new ServerSessionDelegate(), new Binary(getName().getBytes()), 0); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/flow/WindowCreditManagerTest.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java index bc651c9748..1c4a694be6 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/flow/WindowCreditManagerTest.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/test/java/org/apache/qpid/server/protocol/v0_10/WindowCreditManagerTest.java @@ -18,8 +18,9 @@ * under the License. * */ -package org.apache.qpid.server.flow; +package org.apache.qpid.server.protocol.v0_10; +import org.apache.qpid.server.protocol.v0_10.WindowCreditManager; import org.apache.qpid.test.utils.QpidTestCase; public class WindowCreditManagerTest extends QpidTestCase diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/build.xml b/qpid/java/broker-plugins/amqp-0-8-protocol/build.xml new file mode 100644 index 0000000000..45086b6242 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/build.xml @@ -0,0 +1,33 @@ +<!-- + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + --> +<project name="Qpid Broker-Plugins AMQP 0-8 Protocol" default="build"> + <property name="module.depends" value="common broker" /> + <property name="module.test.depends" value="common/tests broker/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/> + <property name="broker-plugins-amqp-0-8-protocol.libs" value="" /> + + <property name="broker.plugin" value="true"/> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> + +</project> diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java index 4df40585d9..a603807f87 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server; +package org.apache.qpid.server.protocol.v0_8; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -52,9 +52,8 @@ import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.abstraction.ContentChunk; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.TransactionTimeoutHelper; import org.apache.qpid.server.TransactionTimeoutHelper.CloseAction; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; -import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.flow.FlowCreditManager; @@ -67,21 +66,16 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ChannelMessages; import org.apache.qpid.server.logging.messages.ExchangeMessages; import org.apache.qpid.server.logging.subjects.ChannelLogSubject; -import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.InboundMessageAdapter; -import org.apache.qpid.server.queue.IncomingMessage; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.security.*; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.StoreFuture; @@ -89,7 +83,6 @@ import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.subscription.RecordDeliveryMethod; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.txn.AsyncAutoCommitTransaction; import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.txn.LocalTransaction.ActivityTimeAccessor; @@ -1403,7 +1396,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F _message, _channelId, _errorCode.getCode(), - AMQShortString.valueOf(_description, true, true)); + AMQShortString.validValueOf(_description)); } catch (AMQException e) { @@ -1456,7 +1449,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F if(_blocking.compareAndSet(false,true)) { - _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(queue.getNameShortString().toString())); + _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(queue.getName())); flow(false); } } @@ -1575,7 +1568,7 @@ public class AMQChannel implements AMQSessionModel, AsyncAutoCommitTransaction.F //output operational logging for each delivery post commit for (final BaseQueue destinationQueue : destinationQueues) { - _actor.message(_logSubject, ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(), destinationQueue.getNameShortString().asString())); + _actor.message(_logSubject, ChannelMessages.DEADLETTERMSG(msg.getMessageNumber(), destinationQueue.getName())); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessage.java index 439d7aa928..416a4da183 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessage.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessage.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v0_8; import org.apache.log4j.Logger; @@ -26,7 +26,9 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.AbstractServerMessageImpl; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.store.StoredMessage; @@ -150,7 +152,7 @@ public class AMQMessage extends AbstractServerMessageImpl<MessageMetaData> } - public MessagePublishInfo getMessagePublishInfo() throws AMQException + public MessagePublishInfo getMessagePublishInfo() { return getMessageMetaData().getMessagePublishInfo(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessageReference.java index 62cfa8431c..3adc9f70cd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageReference.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQMessageReference.java @@ -18,7 +18,9 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v0_8; + +import org.apache.qpid.server.message.MessageReference; public class AMQMessageReference extends MessageReference<AMQMessage> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQNoMethodHandlerException.java index a7599a3e0d..8faf1a7c65 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQNoMethodHandlerException.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQNoMethodHandlerException.java @@ -18,7 +18,7 @@ * under the License.
*
*/
-package org.apache.qpid.server.protocol;
+package org.apache.qpid.server.protocol.v0_8;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQMethodBody;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java index ef3fc97ab8..dcf8d1fd47 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.protocol.v0_8; import java.io.IOException; import java.net.InetSocketAddress; @@ -73,9 +73,9 @@ import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; import org.apache.qpid.protocol.ServerProtocolEngine; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.configuration.BrokerProperties; -import org.apache.qpid.server.handler.ServerMethodDispatcherImpl; +import org.apache.qpid.server.protocol.v0_8.handler.ServerMethodDispatcherImpl; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.AMQPConnectionActor; @@ -86,16 +86,15 @@ import org.apache.qpid.server.logging.subjects.ConnectionLogSubject; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.output.ProtocolOutputConverter; -import org.apache.qpid.server.output.ProtocolOutputConverterRegistry; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverterRegistry; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionImpl; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.TransportException; @@ -184,7 +183,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi private long _lastReceivedTime; private boolean _blocking; - private final Lock _receivedLock; + private final ReentrantLock _receivedLock; private AtomicLong _lastWriteTime = new AtomicLong(System.currentTimeMillis()); private final Broker _broker; private final Transport _transport; @@ -973,16 +972,30 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi { synchronized(this) { + + boolean lockHeld = _receivedLock.isHeldByCurrentThread(); + while(!_closed) { try { + if(lockHeld) + { + _receivedLock.unlock(); + } wait(1000); } catch (InterruptedException e) { } + finally + { + if(lockHeld) + { + _receivedLock.lock(); + } + } } } } @@ -1322,6 +1335,12 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi return _stopped; } + @Override + public String getVirtualHostName() + { + return _virtualHost == null ? null : _virtualHost.getName(); + } + public long getLastReceivedTime() { return _lastReceivedTime; @@ -1359,7 +1378,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi public String getAuthId() { - return getAuthorizedPrincipal().getName(); + return getAuthorizedPrincipal() == null ? null : getAuthorizedPrincipal().getName(); } public Integer getRemotePID() diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolSession.java index 6fa497c853..559ab3468e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolSession.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.protocol.v0_8; import java.net.SocketAddress; import java.security.Principal; @@ -35,9 +35,9 @@ import org.apache.qpid.framing.MethodDispatcher; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; -import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; import org.apache.qpid.server.security.AuthorizationHolder; import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ContentHeaderBodyAdapter.java index 01c1021070..f5c43003a4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ContentHeaderBodyAdapter.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v0_8; import java.util.Collection; import org.apache.qpid.framing.BasicContentHeaderProperties; @@ -26,6 +26,7 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import java.util.Set; +import org.apache.qpid.server.message.AMQMessageHeader; public class ContentHeaderBodyAdapter implements AMQMessageHeader { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java index 0c0b1cf548..5e416b52ca 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ExtractResendAndRequeue.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeue.java @@ -18,12 +18,11 @@ * under the License. * */ -package org.apache.qpid.server; +package org.apache.qpid.server.protocol.v0_8; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.subscription.Subscription; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/IncomingMessage.java index 18affc7161..5267651a66 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/IncomingMessage.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.queue; +package org.apache.qpid.server.protocol.v0_8; import org.apache.log4j.Logger; @@ -33,7 +33,8 @@ import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.MessageContentSource; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.queue.Filterable; import org.apache.qpid.server.store.StoredMessage; import java.nio.ByteBuffer; @@ -128,11 +129,6 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes return _messagePublishInfo.getExchange(); } - public AMQShortString getRoutingKeyShortString() - { - return _messagePublishInfo.getRoutingKey(); - } - public String getRoutingKey() { return _messagePublishInfo.getRoutingKey() == null ? null : _messagePublishInfo.getRoutingKey().toString(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java index e890bf5ef8..4cc590d8cc 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaData.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v0_8; import java.util.Collection; import org.apache.qpid.AMQException; @@ -28,7 +28,8 @@ import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.EncodingUtils; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.plugin.MessageMetaDataType; import org.apache.qpid.server.store.StorableMessageMetaData; import org.apache.qpid.server.util.ByteBufferOutputStream; import org.apache.qpid.util.ByteBufferInputStream; @@ -55,6 +56,7 @@ public class MessageMetaData implements StorableMessageMetaData private static final byte MANDATORY_FLAG = 1; private static final byte IMMEDIATE_FLAG = 2; public static final MessageMetaDataType.Factory<MessageMetaData> FACTORY = new MetaDataFactory(); + private static final MessageMetaDataType_0_8 TYPE = new MessageMetaDataType_0_8(); public MessageMetaData(MessagePublishInfo publishBody, ContentHeaderBody contentHeaderBody, int contentChunkCount) { @@ -111,7 +113,7 @@ public class MessageMetaData implements StorableMessageMetaData public MessageMetaDataType getType() { - return MessageMetaDataType.META_DATA_0_8; + return TYPE; } public int getStorableSize() diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaDataType_0_8.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaDataType_0_8.java new file mode 100644 index 0000000000..9b50127ec7 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageMetaDataType_0_8.java @@ -0,0 +1,67 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import java.nio.ByteBuffer; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.plugin.MessageMetaDataType; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.store.StoredMessage; + +public class MessageMetaDataType_0_8 implements MessageMetaDataType<MessageMetaData> +{ + + public static final int TYPE = 0; + + @Override + public int ordinal() + { + return TYPE; + } + + @Override + public MessageMetaData createMetaData(ByteBuffer buf) + { + return MessageMetaData.FACTORY.createMetaData(buf); + } + + @Override + public ServerMessage<MessageMetaData> createMessage(StoredMessage<MessageMetaData> msg) + { + return new AMQMessage(msg); + } + + public int hashCode() + { + return ordinal(); + } + + public boolean equals(Object o) + { + return o != null && o.getClass() == getClass(); + } + + @Override + public String getType() + { + return AmqpProtocolVersion.v0_8.toString(); + } +} diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_8.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_8.java new file mode 100644 index 0000000000..5ee56508d7 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_8.java @@ -0,0 +1,80 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.plugin.ProtocolEngineCreator; +import org.apache.qpid.transport.network.NetworkConnection; + +public class ProtocolEngineCreator_0_8 implements ProtocolEngineCreator +{ + private static final byte[] AMQP_0_8_HEADER = + new byte[] { (byte) 'A', + (byte) 'M', + (byte) 'Q', + (byte) 'P', + (byte) 1, + (byte) 1, + (byte) 8, + (byte) 0 + }; + + + public ProtocolEngineCreator_0_8() + { + } + + public AmqpProtocolVersion getVersion() + { + return AmqpProtocolVersion.v0_8; + } + + public byte[] getHeaderIdentifier() + { + return AMQP_0_8_HEADER; + } + + public ServerProtocolEngine newProtocolEngine(Broker broker, + NetworkConnection network, + Port port, + Transport transport, + long id) + { + return new AMQProtocolEngine(broker, network, id, port, transport); + } + + private static ProtocolEngineCreator INSTANCE = new ProtocolEngineCreator_0_8(); + + public static ProtocolEngineCreator getInstance() + { + return INSTANCE; + } + + @Override + public String getType() + { + return getVersion().toString(); + } +} diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9.java new file mode 100644 index 0000000000..2a29348261 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9.java @@ -0,0 +1,80 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.plugin.ProtocolEngineCreator; +import org.apache.qpid.transport.network.NetworkConnection; + +public class ProtocolEngineCreator_0_9 implements ProtocolEngineCreator +{ + private static final byte[] AMQP_0_9_HEADER = + new byte[] { (byte) 'A', + (byte) 'M', + (byte) 'Q', + (byte) 'P', + (byte) 1, + (byte) 1, + (byte) 0, + (byte) 9 + }; + + public ProtocolEngineCreator_0_9() + { + } + + public AmqpProtocolVersion getVersion() + { + return AmqpProtocolVersion.v0_9; + } + + + public byte[] getHeaderIdentifier() + { + return AMQP_0_9_HEADER; + } + + public ServerProtocolEngine newProtocolEngine(Broker broker, + NetworkConnection network, + Port port, + Transport transport, + long id) + { + return new AMQProtocolEngine(broker, network, id, port, transport); + } + + private static ProtocolEngineCreator INSTANCE = new ProtocolEngineCreator_0_9(); + + public static ProtocolEngineCreator getInstance() + { + return INSTANCE; + } + + @Override + public String getType() + { + return getVersion().toString(); + } +} diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9_1.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9_1.java new file mode 100644 index 0000000000..dad6bef032 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/ProtocolEngineCreator_0_9_1.java @@ -0,0 +1,82 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.plugin.ProtocolEngineCreator; +import org.apache.qpid.transport.network.NetworkConnection; + +public class ProtocolEngineCreator_0_9_1 implements ProtocolEngineCreator +{ + + private static final byte[] AMQP_0_9_1_HEADER = + new byte[] { (byte) 'A', + (byte) 'M', + (byte) 'Q', + (byte) 'P', + (byte) 0, + (byte) 0, + (byte) 9, + (byte) 1 + }; + + public ProtocolEngineCreator_0_9_1() + { + } + + public AmqpProtocolVersion getVersion() + { + return AmqpProtocolVersion.v0_9_1; + } + + + public byte[] getHeaderIdentifier() + { + return AMQP_0_9_1_HEADER; + } + + public ServerProtocolEngine newProtocolEngine(Broker broker, + NetworkConnection network, + Port port, + Transport transport, + long id) + { + return new AMQProtocolEngine(broker, network, id, port, transport); + } + + + private static ProtocolEngineCreator INSTANCE = new ProtocolEngineCreator_0_9_1(); + + public static ProtocolEngineCreator getInstance() + { + return INSTANCE; + } + + @Override + public String getType() + { + return getVersion().toString(); + } +} diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java new file mode 100644 index 0000000000..6646dc0cc2 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactory.java @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.flow.FlowCreditManager; +import org.apache.qpid.server.subscription.ClientDeliveryMethod; +import org.apache.qpid.server.subscription.RecordDeliveryMethod; +import org.apache.qpid.server.subscription.Subscription; + +/** + * Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory + * primarily assists testing although in future more sophisticated subscribers may need a different subscription + * implementation. + * + * @see org.apache.qpid.server.queue.AMQQueue + */ +public interface SubscriptionFactory +{ + Subscription createSubscription(int channel, + AMQProtocolSession protocolSession, + AMQShortString consumerTag, + boolean acks, + FieldTable filters, + boolean noLocal, FlowCreditManager creditManager) throws AMQException; + + + Subscription createSubscription(AMQChannel channel, + AMQProtocolSession protocolSession, + AMQShortString consumerTag, + boolean acks, + FieldTable filters, + boolean noLocal, + FlowCreditManager creditManager, + ClientDeliveryMethod clientMethod, + RecordDeliveryMethod recordMethod) throws AMQException; + + + Subscription createBasicGetNoAckSubscription(AMQChannel channel, + AMQProtocolSession session, + AMQShortString consumerTag, + FieldTable filters, + boolean noLocal, + FlowCreditManager creditManager, + ClientDeliveryMethod deliveryMethod, + RecordDeliveryMethod recordMethod) throws AMQException; + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java index a2e30b6ae7..93b51a0567 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImpl.java @@ -18,29 +18,20 @@ * under the License. * */ -package org.apache.qpid.server.subscription; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageFlowMode; - -import java.util.Map; -import java.util.concurrent.atomic.AtomicLong; +import org.apache.qpid.server.subscription.ClientDeliveryMethod; +import org.apache.qpid.server.subscription.RecordDeliveryMethod; +import org.apache.qpid.server.subscription.Subscription; public class SubscriptionFactoryImpl implements SubscriptionFactory { - private static final AtomicLong SUB_ID_GENERATOR = new AtomicLong(0); public Subscription createSubscription(int channelId, AMQProtocolSession protocolSession, AMQShortString consumerTag, boolean acks, FieldTable filters, @@ -89,15 +80,15 @@ public class SubscriptionFactoryImpl implements SubscriptionFactory if(isBrowser) { - return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId()); + return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod); } else if(acks) { - return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId()); + return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod); } else { - return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId()); + return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod); } } @@ -110,26 +101,9 @@ public class SubscriptionFactoryImpl implements SubscriptionFactory final ClientDeliveryMethod deliveryMethod, final RecordDeliveryMethod recordMethod) throws AMQException { - return new SubscriptionImpl.GetNoAckSubscription(channel, session, null, null, false, creditManager, deliveryMethod, recordMethod, getNextSubscriptionId()); - } - - public Subscription_0_10 createSubscription(final ServerSession session, - final String destination, - final MessageAcceptMode acceptMode, - final MessageAcquireMode acquireMode, - final MessageFlowMode flowMode, - final FlowCreditManager_0_10 creditManager, - final FilterManager filterManager, - final Map<String,Object> arguments) - { - return new Subscription_0_10(session, destination, acceptMode, acquireMode, - flowMode, creditManager, filterManager, arguments, getNextSubscriptionId()); + return new SubscriptionImpl.GetNoAckSubscription(channel, session, null, null, false, creditManager, deliveryMethod, recordMethod); } public static final SubscriptionFactoryImpl INSTANCE = new SubscriptionFactoryImpl(); - private static long getNextSubscriptionId() - { - return SUB_ID_GENERATOR.getAndIncrement(); - } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java index 29a8f4e27e..d1d86fe478 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/SubscriptionImpl.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.subscription; +package org.apache.qpid.server.protocol.v0_8; import org.apache.log4j.Logger; @@ -26,7 +26,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.FilterManagerFactory; import org.apache.qpid.server.flow.FlowCreditManager; @@ -36,17 +35,18 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.SubscriptionActor; import org.apache.qpid.server.logging.messages.SubscriptionMessages; import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.output.ProtocolOutputConverter; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.MessageConverterRegistry; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.subscription.ClientDeliveryMethod; +import org.apache.qpid.server.subscription.RecordDeliveryMethod; +import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import java.util.Map; -import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; @@ -101,11 +101,10 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage AMQShortString consumerTag, FieldTable filters, boolean noLocal, FlowCreditManager creditManager, ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod, - long subscriptionID) + RecordDeliveryMethod recordMethod) throws AMQException { - super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); + super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod); } @@ -152,12 +151,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage public NoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession, AMQShortString consumerTag, FieldTable filters, boolean noLocal, FlowCreditManager creditManager, - ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod, - long subscriptionID) + ClientDeliveryMethod deliveryMethod, + RecordDeliveryMethod recordMethod) throws AMQException { - super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); + super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod); } @@ -241,14 +239,13 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage public static final class GetNoAckSubscription extends SubscriptionImpl.NoAckSubscription { public GetNoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession, - AMQShortString consumerTag, FieldTable filters, - boolean noLocal, FlowCreditManager creditManager, - ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod, - long subscriptionID) + AMQShortString consumerTag, FieldTable filters, + boolean noLocal, FlowCreditManager creditManager, + ClientDeliveryMethod deliveryMethod, + RecordDeliveryMethod recordMethod) throws AMQException { - super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); + super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod); } public boolean isTransient() @@ -268,12 +265,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage public AckSubscription(AMQChannel channel, AMQProtocolSession protocolSession, AMQShortString consumerTag, FieldTable filters, boolean noLocal, FlowCreditManager creditManager, - ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod, - long subscriptionID) + ClientDeliveryMethod deliveryMethod, + RecordDeliveryMethod recordMethod) throws AMQException { - super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID); + super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod); } @@ -336,15 +332,14 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage - public SubscriptionImpl(AMQChannel channel , AMQProtocolSession protocolSession, + public SubscriptionImpl(AMQChannel channel, AMQProtocolSession protocolSession, AMQShortString consumerTag, FieldTable arguments, boolean noLocal, FlowCreditManager creditManager, ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod, - long subscriptionID) + RecordDeliveryMethod recordMethod) throws AMQException { - _subscriptionID = subscriptionID; + _subscriptionID = SUB_ID_GENERATOR.getAndIncrement(); _channel = channel; _consumerTag = consumerTag; @@ -354,7 +349,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage _noLocal = noLocal; - _filters = FilterManagerFactory.createManager(arguments); + _filters = FilterManagerFactory.createManager(FieldTable.convertToMap(arguments)); _deliveryMethod = deliveryMethod; _recordMethod = recordMethod; @@ -487,16 +482,27 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage } } - if (_noLocal) + if(entry.getMessage() instanceof AMQMessage) { - AMQMessage message = (AMQMessage) entry.getMessage(); + if (_noLocal) + { + AMQMessage message = (AMQMessage) entry.getMessage(); - final Object publisherReference = message.getConnectionIdentifier(); + final Object publisherReference = message.getConnectionIdentifier(); - // We don't want local messages so check to see if message is one we sent - Object localReference = getProtocolSession().getReference(); + // We don't want local messages so check to see if message is one we sent + Object localReference = getProtocolSession().getReference(); - if(publisherReference != null && publisherReference.equals(localReference)) + if(publisherReference != null && publisherReference.equals(localReference)) + { + return false; + } + } + } + else + { + // No interest in messages we can't convert to AMQMessage + if(MessageConverterRegistry.getConverter(entry.getMessage().getClass(), AMQMessage.class)==null) { return false; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java index 842b36cf75..1d41bcdcf4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMap.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMap.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.ack; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.server.queue.QueueEntry; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java index b8b15c8c28..17b2c7b985 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/ack/UnacknowledgedMessageMapImpl.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/UnacknowledgedMessageMapImpl.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.ack; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.server.queue.QueueEntry; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/AccessRequestHandler.java index 84812485fd..ae07d60c4e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/AccessRequestHandler.java @@ -1,5 +1,5 @@ /*
- *
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -7,18 +7,18 @@ * 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.handler; +package org.apache.qpid.server.protocol.v0_8.handler;
import org.apache.qpid.AMQException;
@@ -28,10 +28,10 @@ import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9;
import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.protocol.v0_8.AMQChannel;
+import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession;
+import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
+import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener;
/**
* @author Apache Software Foundation
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicAckMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicAckMethodHandler.java index 398a3ff58a..f623d27e87 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicAckMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicAckMethodHandler.java @@ -18,16 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.BasicAckBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class BasicAckMethodHandler implements StateAwareMethodListener<BasicAckBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicCancelMethodHandler.java index 0741385d42..5a6a7bdc18 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicCancelMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicCancelMethodHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -26,10 +26,10 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.BasicCancelBody; import org.apache.qpid.framing.BasicCancelOkBody; import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class BasicCancelMethodHandler implements StateAwareMethodListener<BasicCancelBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java index 514829625d..836de44f4e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicConsumeMethodHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -28,12 +28,12 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicConsumeBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; public class BasicConsumeMethodHandler implements StateAwareMethodListener<BasicConsumeBody> @@ -73,7 +73,7 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic " args:" + body.getArguments()); } - AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueueRegistry().getQueue(body.getQueue().intern()); + AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueue(body.getQueue().intern().toString()); if (queue == null) { @@ -102,13 +102,13 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic if (session == null || session.getConnectionModel() != protocolConnection) { throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); + "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); } } if (body.getConsumerTag() != null) { - consumerTagName = body.getConsumerTag().intern(); + consumerTagName = body.getConsumerTag().intern(false); } else { @@ -160,14 +160,14 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic { throw body.getChannelException(AMQConstant.ACCESS_REFUSED, "Cannot subscribe to queue " - + queue.getNameShortString() + + queue.getName() + " as it already has an existing exclusive consumer"); } catch (AMQQueue.ExistingSubscriptionPreventsExclusive e) { throw body.getChannelException(AMQConstant.ACCESS_REFUSED, "Cannot subscribe to queue " - + queue.getNameShortString() + + queue.getName() + " exclusively as it already has a consumer"); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java index 191643493e..5238a41e49 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicGetMethodHandler.java @@ -19,7 +19,7 @@ * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -28,20 +28,20 @@ import org.apache.qpid.framing.BasicGetBody; import org.apache.qpid.framing.BasicGetEmptyBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.flow.FlowCreditManager; import org.apache.qpid.server.flow.MessageOnlyCreditManager; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.subscription.RecordDeliveryMethod; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; +import org.apache.qpid.server.protocol.v0_8.SubscriptionFactoryImpl; import org.apache.qpid.server.virtualhost.VirtualHost; public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetBody> @@ -74,7 +74,7 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB else { channel.sync(); - AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueueRegistry().getQueue(body.getQueue()); + AMQQueue queue = body.getQueue() == null ? channel.getDefaultQueue() : vHost.getQueue(body.getQueue().toString()); if (queue == null) { _log.info("No queue for '" + body.getQueue() + "'"); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java index 85fee94143..497e97db3e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicPublishMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicPublishMethodHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -28,11 +28,11 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicPublishBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; public class BasicPublishMethodHandler implements StateAwareMethodListener<BasicPublishBody> @@ -63,7 +63,7 @@ public class BasicPublishMethodHandler implements StateAwareMethodListener<Basic // TODO: check the delivery tag field details - is it unique across the broker or per subscriber? if (exchangeName == null) { - exchangeName = ExchangeDefaults.DEFAULT_EXCHANGE_NAME; + exchangeName = AMQShortString.valueOf(ExchangeDefaults.DEFAULT_EXCHANGE_NAME); } VirtualHost vHost = session.getVirtualHost(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicQosHandler.java index 87a3d1c210..e4a6636a74 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicQosHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicQosHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,16 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.BasicQosBody; import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class BasicQosHandler implements StateAwareMethodListener<BasicQosBody> { @@ -53,6 +53,6 @@ public class BasicQosHandler implements StateAwareMethodListener<BasicQosBody> MethodRegistry methodRegistry = session.getMethodRegistry(); AMQMethodBody responseBody = methodRegistry.createBasicQosOkBody(); session.writeFrame(responseBody.generateFrame(channelId)); - + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java index 0c4c9cac47..0a79466b35 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverMethodHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -27,10 +27,10 @@ import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.BasicRecoverBody; import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class BasicRecoverMethodHandler implements StateAwareMethodListener<BasicRecoverBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java index 43ee8da64f..b54e1c7dcf 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRecoverSyncMethodHandler.java @@ -1,5 +1,5 @@ /*
- *
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -7,18 +7,18 @@ * 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.handler; +package org.apache.qpid.server.protocol.v0_8.handler;
import org.apache.log4j.Logger;
@@ -29,10 +29,10 @@ import org.apache.qpid.framing.BasicRecoverSyncBody; import org.apache.qpid.framing.ProtocolVersion;
import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9;
import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91;
-import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
-import org.apache.qpid.server.state.AMQStateManager;
-import org.apache.qpid.server.state.StateAwareMethodListener;
+import org.apache.qpid.server.protocol.v0_8.AMQChannel;
+import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession;
+import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
+import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener;
public class BasicRecoverSyncMethodHandler implements StateAwareMethodListener<BasicRecoverSyncBody>
{
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java index de76050898..0cfdff3338 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRejectMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/BasicRejectMethodHandler.java @@ -18,17 +18,17 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.BasicRejectBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicRejectBody> { @@ -70,7 +70,7 @@ public class BasicRejectMethodHandler implements StateAwareMethodListener<BasicR if (message == null) { _logger.warn("Dropping reject request as message is null for tag:" + deliveryTag); - } + } else { if (message.isQueueDeleted()) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseHandler.java index 0c8ab318b2..e96d098618 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -27,10 +27,10 @@ import org.apache.qpid.framing.ChannelCloseBody; import org.apache.qpid.framing.ChannelCloseOkBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class ChannelCloseHandler implements StateAwareMethodListener<ChannelCloseBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseOkHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseOkHandler.java index 54b3f813af..2a220ff78d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelCloseOkHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelCloseOkHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,14 +18,14 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.ChannelCloseOkBody; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class ChannelCloseOkHandler implements StateAwareMethodListener<ChannelCloseOkBody> { @@ -46,7 +46,7 @@ public class ChannelCloseOkHandler implements StateAwareMethodListener<ChannelCl { _logger.info("Received channel-close-ok for channel-id " + channelId); - + // Let the Protocol Session know the channel is now closed. stateManager.getProtocolSession().closeChannelOk(channelId); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelFlowHandler.java index a736ad5fb0..cc1677c93e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelFlowHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelFlowHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -26,10 +26,10 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.ChannelFlowBody; import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class ChannelFlowHandler implements StateAwareMethodListener<ChannelFlowBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelOpenHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelOpenHandler.java index 81734d7825..442c912032 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ChannelOpenHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ChannelOpenHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -31,10 +31,10 @@ import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9; import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91; import org.apache.qpid.framing.amqp_8_0.MethodRegistry_8_0; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; import java.io.ByteArrayOutputStream; @@ -45,7 +45,7 @@ import java.util.UUID; public class ChannelOpenHandler implements StateAwareMethodListener<ChannelOpenBody> { private static final Logger _logger = Logger.getLogger(ChannelOpenHandler.class); - + private static ChannelOpenHandler _instance = new ChannelOpenHandler(); public static ChannelOpenHandler getInstance() @@ -61,7 +61,7 @@ public class ChannelOpenHandler implements StateAwareMethodListener<ChannelOpenB { AMQProtocolSession session = stateManager.getProtocolSession(); VirtualHost virtualHost = session.getVirtualHost(); - + // Protect the broker against out of order frame request. if (virtualHost == null) { @@ -70,7 +70,7 @@ public class ChannelOpenHandler implements StateAwareMethodListener<ChannelOpenB _logger.info("Connecting to: " + virtualHost.getName()); final AMQChannel channel = new AMQChannel(session,channelId, virtualHost.getMessageStore()); - + session.addChannel(channel); ChannelOpenOkBody response; @@ -104,7 +104,7 @@ public class ChannelOpenHandler implements StateAwareMethodListener<ChannelOpenB // should really associate this channelId to the session byte[] channelName = output.toByteArray(); - + response = methodRegistry.createChannelOpenOkBody(channelName); } else if(pv.equals(ProtocolVersion.v0_91)) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseMethodHandler.java index 7f0c0d2974..60f9c1d495 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseMethodHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -26,9 +26,9 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.ConnectionCloseBody; import org.apache.qpid.framing.ConnectionCloseOkBody; import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class ConnectionCloseMethodHandler implements StateAwareMethodListener<ConnectionCloseBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseOkMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseOkMethodHandler.java index bd86c2d3f1..fe46b6c0cd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseOkMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionCloseOkMethodHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,16 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.ConnectionCloseOkBody; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class ConnectionCloseOkMethodHandler implements StateAwareMethodListener<ConnectionCloseOkBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java index eab28ac9d4..62b13baac2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionOpenMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionOpenMethodHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -28,10 +28,10 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ConnectionOpenBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.State; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionSecureOkMethodHandler.java index 8927cfa94d..d319f080d2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionSecureOkMethodHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -32,12 +32,12 @@ import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionStartOkMethodHandler.java index 5bfa080848..9350327346 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionStartOkMethodHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -31,12 +31,12 @@ import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionTuneOkMethodHandler.java index 299aad0fe7..5fddab6576 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionTuneOkMethodHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ConnectionTuneOkMethodHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,16 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.ConnectionTuneOkBody; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQState; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQState; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class ConnectionTuneOkMethodHandler implements StateAwareMethodListener<ConnectionTuneOkBody> { @@ -51,7 +51,7 @@ public class ConnectionTuneOkMethodHandler implements StateAwareMethodListener<C stateManager.changeState(AMQState.CONNECTION_NOT_OPENED); session.initHeartbeats(body.getHeartbeat()); session.setMaxFrameSize(body.getFrameMax()); - + long maxChannelNumber = body.getChannelMax(); //0 means no implied limit, except that forced by protocol limitations (0xFFFF) session.setMaximumNumberOfChannels( maxChannelNumber == 0 ? 0xFFFFL : maxChannelNumber); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java index 8493e97215..0535236f94 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java @@ -18,20 +18,20 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ExchangeBoundBody; import org.apache.qpid.framing.ExchangeBoundOkBody; import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; /** @@ -70,7 +70,6 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo { AMQProtocolSession session = stateManager.getProtocolSession(); VirtualHost virtualHost = session.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); MethodRegistry methodRegistry = session.getMethodRegistry(); final AMQChannel channel = session.getChannel(channelId); @@ -115,7 +114,7 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo else { - AMQQueue queue = queueRegistry.getQueue(queueName); + AMQQueue queue = virtualHost.getQueue(queueName.toString()); if (queue == null) { @@ -141,7 +140,7 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo } else if (queueName != null) { - AMQQueue queue = queueRegistry.getQueue(queueName); + AMQQueue queue = virtualHost.getQueue(queueName.toString()); if (queue == null) { @@ -150,7 +149,8 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo } else { - if (exchange.isBound(body.getRoutingKey(), queue)) + String bindingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().asString(); + if (exchange.isBound(bindingKey, queue)) { response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode @@ -173,7 +173,7 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo } else { - if (exchange.isBound(body.getRoutingKey())) + if (exchange.isBound(body.getRoutingKey() == null ? "" : body.getRoutingKey().asString())) { response = methodRegistry.createExchangeBoundOkBody(OK, // replyCode diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeclareHandler.java index 437869ab01..154c38a4bf 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeclareHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeclareHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -30,11 +30,11 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ExchangeDeclareBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.ExchangeExistsException; import org.apache.qpid.server.virtualhost.ReservedExchangeNameException; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -79,11 +79,11 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange { throw body.getChannelException(AMQConstant.NOT_FOUND, "Unknown exchange: " + exchangeName); } - else if (!exchange.getTypeShortString().equals(body.getType()) && !(body.getType() == null || body.getType().length() ==0)) + else if (!(body.getType() == null || body.getType().length() ==0) && !exchange.getTypeName().equals(body.getType().asString())) { throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + - exchangeName + " of type " + exchange.getTypeShortString() + exchangeName + " of type " + exchange.getTypeName() + " to " + body.getType() +".",body.getClazz(), body.getMethod(),body.getMajor(),body.getMinor(),null); } @@ -110,11 +110,11 @@ public class ExchangeDeclareHandler implements StateAwareMethodListener<Exchange catch(ExchangeExistsException e) { exchange = e.getExistingExchange(); - if(!exchange.getTypeShortString().equals(body.getType())) + if(!new AMQShortString(exchange.getTypeName()).equals(body.getType())) { throw new AMQConnectionException(AMQConstant.NOT_ALLOWED, "Attempt to redeclare exchange: " + exchangeName + " of type " - + exchange.getTypeShortString() + + exchange.getTypeName() + " to " + body.getType() +".", body.getClazz(), body.getMethod(), body.getMajor(), body.getMinor(),null); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeleteHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeleteHandler.java index 25d0182202..75f749fe9a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeDeleteHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeDeleteHandler.java @@ -18,24 +18,21 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ExchangeDeleteBody; import org.apache.qpid.framing.ExchangeDeleteOkBody; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeInUseException; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException; import org.apache.qpid.server.virtualhost.RequiredExchangeException; import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.ExecutionErrorCode; public class ExchangeDeleteHandler implements StateAwareMethodListener<ExchangeDeleteBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/OnCurrentThreadExecutor.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/OnCurrentThreadExecutor.java index ac516b6133..6ff511ea30 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/OnCurrentThreadExecutor.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/OnCurrentThreadExecutor.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import java.util.concurrent.Executor; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueBindHandler.java index 63b8bf3136..d95d59f75f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueBindHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueBindHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -30,15 +30,17 @@ import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.QueueBindBody; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.exchange.TopicExchange; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Map; @@ -62,7 +64,6 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody> { AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); VirtualHost virtualHost = protocolConnection.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); AMQChannel channel = protocolConnection.getChannel(channelId); if (channel == null) @@ -73,7 +74,9 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody> final AMQQueue queue; final AMQShortString routingKey; - if (body.getQueue() == null) + final AMQShortString queueName = body.getQueue(); + + if (queueName == null) { queue = channel.getDefaultQueue(); @@ -85,7 +88,7 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody> if (body.getRoutingKey() == null) { - routingKey = queue.getNameShortString(); + routingKey = AMQShortString.valueOf(queue.getName()); } else { @@ -94,13 +97,13 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody> } else { - queue = queueRegistry.getQueue(body.getQueue()); + queue = virtualHost.getQueue(queueName.toString()); routingKey = body.getRoutingKey() == null ? AMQShortString.EMPTY_STRING : body.getRoutingKey().intern(); } if (queue == null) { - throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + body.getQueue() + " does not exist."); + throw body.getChannelException(AMQConstant.NOT_FOUND, "Queue " + queueName + " does not exist."); } final String exchangeName = body.getExchange() == null ? null : body.getExchange().toString(); final Exchange exch = virtualHost.getExchange(exchangeName); @@ -118,16 +121,17 @@ public class QueueBindHandler implements StateAwareMethodListener<QueueBindBody> if (session == null || session.getConnectionModel() != protocolConnection) { throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); + "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); } } - if (!exch.isBound(routingKey, body.getArguments(), queue)) + Map<String,Object> arguments = FieldTable.convertToMap(body.getArguments()); + String bindingKey = String.valueOf(routingKey); + + if (!exch.isBound(bindingKey, arguments, queue)) { - String bindingKey = String.valueOf(routingKey); - Map<String,Object> arguments = FieldTable.convertToMap(body.getArguments()); - if(!exch.addBinding(bindingKey, queue, arguments)) + if(!exch.addBinding(bindingKey, queue, arguments) && TopicExchange.TYPE.equals(exch.getType())) { Binding oldBinding = exch.getBinding(bindingKey, queue, arguments); diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java new file mode 100644 index 0000000000..3fdce83c2a --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeclareHandler.java @@ -0,0 +1,259 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8.handler; + +import org.apache.log4j.Logger; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.QueueDeclareBody; +import org.apache.qpid.framing.QueueDeclareOkBody; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueArgumentsConverter; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; +import org.apache.qpid.server.store.DurableConfigurationStoreHelper; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import java.util.Map; +import java.util.UUID; +import org.apache.qpid.server.virtualhost.plugins.QueueExistsException; + +public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclareBody> +{ + private static final Logger _logger = Logger.getLogger(QueueDeclareHandler.class); + + private static final QueueDeclareHandler _instance = new QueueDeclareHandler(); + + public static QueueDeclareHandler getInstance() + { + return _instance; + } + + public void methodReceived(AMQStateManager stateManager, QueueDeclareBody body, int channelId) throws AMQException + { + final AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); + final AMQSessionModel session = protocolConnection.getChannel(channelId); + VirtualHost virtualHost = protocolConnection.getVirtualHost(); + + final AMQShortString queueName; + + // if we aren't given a queue name, we create one which we return to the client + if ((body.getQueue() == null) || (body.getQueue().length() == 0)) + { + queueName = createName(); + } + else + { + queueName = body.getQueue().intern(); + } + + AMQQueue queue; + + //TODO: do we need to check that the queue already exists with exactly the same "configuration"? + + AMQChannel channel = protocolConnection.getChannel(channelId); + + if (channel == null) + { + throw body.getChannelNotFoundException(channelId); + } + + if(body.getPassive()) + { + queue = virtualHost.getQueue(queueName.toString()); + if (queue == null) + { + String msg = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ")."; + throw body.getChannelException(AMQConstant.NOT_FOUND, msg); + } + else + { + AMQSessionModel owningSession = queue.getExclusiveOwningSession(); + if (queue.isExclusive() && !queue.isDurable() + && (owningSession == null || owningSession.getConnectionModel() != protocolConnection)) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); + } + + //set this as the default queue on the channel: + channel.setDefaultQueue(queue); + } + } + else + { + + try + { + + queue = createQueue(queueName, body, virtualHost, protocolConnection); + queue.setAuthorizationHolder(protocolConnection); + + if (body.getExclusive()) + { + queue.setExclusiveOwningSession(protocolConnection.getChannel(channelId)); + queue.setAuthorizationHolder(protocolConnection); + + if(!body.getDurable()) + { + final AMQQueue q = queue; + final AMQProtocolSession.Task sessionCloseTask = new AMQProtocolSession.Task() + { + public void doTask(AMQProtocolSession session) throws AMQException + { + q.setExclusiveOwningSession(null); + } + }; + protocolConnection.addSessionCloseTask(sessionCloseTask); + queue.addQueueDeleteTask(new AMQQueue.Task() { + public void doTask(AMQQueue queue) throws AMQException + { + protocolConnection.removeSessionCloseTask(sessionCloseTask); + } + }); + } + } + + } + catch(QueueExistsException qe) + { + + queue = qe.getExistingQueue(); + AMQSessionModel owningSession = queue.getExclusiveOwningSession(); + + if (queue.isExclusive() && !queue.isDurable() && (owningSession == null || owningSession.getConnectionModel() != protocolConnection)) + { + throw body.getConnectionException(AMQConstant.NOT_ALLOWED, + "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); + } + else if(queue.isExclusive() != body.getExclusive()) + { + + throw body.getChannelException(AMQConstant.ALREADY_EXISTS, + "Cannot re-declare queue '" + queue.getName() + "' with different exclusivity (was: " + + queue.isExclusive() + " requested " + body.getExclusive() + ")"); + } + else if (body.getExclusive() && !(queue.isDurable() ? String.valueOf(queue.getOwner()).equals(session.getClientID()) : (owningSession == null || owningSession.getConnectionModel() == protocolConnection))) + { + throw body.getChannelException(AMQConstant.ALREADY_EXISTS, "Cannot declare queue('" + queueName + "'), " + + "as exclusive queue with same name " + + "declared on another client ID('" + + queue.getOwner() + "') your clientID('" + session.getClientID() + "')"); + + } + else if(queue.isAutoDelete() != body.getAutoDelete()) + { + throw body.getChannelException(AMQConstant.ALREADY_EXISTS, + "Cannot re-declare queue '" + queue.getName() + "' with different auto-delete (was: " + + queue.isAutoDelete() + " requested " + body.getAutoDelete() + ")"); + } + else if(queue.isDurable() != body.getDurable()) + { + throw body.getChannelException(AMQConstant.ALREADY_EXISTS, + "Cannot re-declare queue '" + queue.getName() + "' with different durability (was: " + + queue.isDurable() + " requested " + body.getDurable() + ")"); + } + + } + + //set this as the default queue on the channel: + channel.setDefaultQueue(queue); + } + + if (!body.getNowait()) + { + channel.sync(); + MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); + QueueDeclareOkBody responseBody = + methodRegistry.createQueueDeclareOkBody(queueName, + queue.getMessageCount(), + queue.getConsumerCount()); + protocolConnection.writeFrame(responseBody.generateFrame(channelId)); + + _logger.info("Queue " + queueName + " declared successfully"); + } + } + + protected AMQShortString createName() + { + return new AMQShortString("tmp_" + UUID.randomUUID()); + } + + protected AMQQueue createQueue(final AMQShortString queueName, + QueueDeclareBody body, + final VirtualHost virtualHost, + final AMQProtocolSession session) + throws AMQException + { + + final boolean durable = body.getDurable(); + final boolean autoDelete = body.getAutoDelete(); + final boolean exclusive = body.getExclusive(); + + String owner = exclusive ? AMQShortString.toString(session.getContextKey()) : null; + + Map<String, Object> arguments = + QueueArgumentsConverter.convertWireArgsToModel(FieldTable.convertToMap(body.getArguments())); + String queueNameString = AMQShortString.toString(queueName); + final UUID id = UUIDGenerator.generateQueueUUID(queueNameString, virtualHost.getName()); + + final AMQQueue queue = virtualHost.createQueue(id, queueNameString, durable, owner, autoDelete, + exclusive, autoDelete, arguments); + + if (exclusive && !durable) + { + final AMQProtocolSession.Task deleteQueueTask = + new AMQProtocolSession.Task() + { + public void doTask(AMQProtocolSession session) throws AMQException + { + if (virtualHost.getQueue(queueName.toString()) == queue) + { + virtualHost.removeQueue(queue); + } + } + }; + + session.addSessionCloseTask(deleteQueueTask); + + queue.addQueueDeleteTask(new AMQQueue.Task() + { + public void doTask(AMQQueue queue) + { + session.removeSessionCloseTask(deleteQueueTask); + } + }); + } + + return queue; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeleteHandler.java index 4b00c1a09b..d3c196a789 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeleteHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueDeleteHandler.java @@ -18,20 +18,20 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.qpid.AMQException; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.QueueDeleteBody; import org.apache.qpid.framing.QueueDeleteOkBody; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.DurableConfigurationStoreHelper; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -62,7 +62,6 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB { AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); VirtualHost virtualHost = protocolConnection.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); @@ -82,7 +81,7 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB } else { - queue = queueRegistry.getQueue(body.getQueue()); + queue = virtualHost.getQueue(body.getQueue().toString()); } if (queue == null) @@ -109,15 +108,10 @@ public class QueueDeleteHandler implements StateAwareMethodListener<QueueDeleteB if (queue.isExclusive() && !queue.isDurable() && (session == null || session.getConnectionModel() != protocolConnection)) { throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); + "Queue " + queue.getName() + " is exclusive, but not created on this Connection."); } - int purged = queue.delete(); - - if (queue.isDurable()) - { - DurableConfigurationStoreHelper.removeQueue(store, queue); - } + int purged = virtualHost.removeQueue(queue); MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); QueueDeleteOkBody responseBody = methodRegistry.createQueueDeleteOkBody(purged); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueuePurgeHandler.java index 217a264793..ff845d3c16 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueuePurgeHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueuePurgeHandler.java @@ -19,20 +19,20 @@ * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.QueuePurgeBody; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBody> @@ -60,7 +60,6 @@ public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBod { AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); VirtualHost virtualHost = protocolConnection.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); AMQChannel channel = protocolConnection.getChannel(channelId); if (channel == null) @@ -73,7 +72,7 @@ public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBod //get the default queue on the channel: queue = channel.getDefaultQueue(); - + if(queue == null) { if(_failIfNotFound) @@ -84,7 +83,7 @@ public class QueuePurgeHandler implements StateAwareMethodListener<QueuePurgeBod } else { - queue = queueRegistry.getQueue(body.getQueue()); + queue = virtualHost.getQueue(body.getQueue().toString()); } if(queue == null) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueUnbindHandler.java index e0e814537a..d568e0f581 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/QueueUnbindHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -31,14 +31,13 @@ import org.apache.qpid.framing.QueueUnbindBody; import org.apache.qpid.framing.amqp_0_9.MethodRegistry_0_9; import org.apache.qpid.framing.amqp_0_91.MethodRegistry_0_91; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; public class QueueUnbindHandler implements StateAwareMethodListener<QueueUnbindBody> @@ -60,8 +59,6 @@ public class QueueUnbindHandler implements StateAwareMethodListener<QueueUnbindB { AMQProtocolSession session = stateManager.getProtocolSession(); VirtualHost virtualHost = session.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - final AMQQueue queue; final AMQShortString routingKey; @@ -83,13 +80,13 @@ public class QueueUnbindHandler implements StateAwareMethodListener<QueueUnbindB throw body.getChannelException(AMQConstant.NOT_FOUND, "No default queue defined on channel and queue was null"); } - routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(); + routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false); } else { - queue = queueRegistry.getQueue(body.getQueue()); - routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(); + queue = virtualHost.getQueue(body.getQueue().toString()); + routingKey = body.getRoutingKey() == null ? null : body.getRoutingKey().intern(false); } if (queue == null) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl.java index 3b6dc3f3f5..43e97c0cb6 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl.java @@ -18,11 +18,11 @@ * under the License.
*
*/
-package org.apache.qpid.server.handler;
+package org.apache.qpid.server.protocol.v0_8.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.*;
-import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
import java.util.HashMap;
import java.util.Map;
@@ -119,7 +119,7 @@ public class ServerMethodDispatcherImpl implements MethodDispatcher {
return _stateManager;
}
-
+
public boolean dispatchAccessRequest(AccessRequestBody body, int channelId) throws AMQException
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_9.java index 7ce8664d37..1ee6d732c2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_9.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_9.java @@ -18,13 +18,13 @@ * under the License.
*
*/
-package org.apache.qpid.server.handler;
+package org.apache.qpid.server.protocol.v0_8.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.amqp_0_9.MethodDispatcher_0_9;
-import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_91.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_91.java index 126e1484b6..b11b9cff2b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_0_91.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_0_91.java @@ -18,13 +18,13 @@ * under the License.
*
*/
-package org.apache.qpid.server.handler;
+package org.apache.qpid.server.protocol.v0_8.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.amqp_0_91.MethodDispatcher_0_91;
-import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
public class ServerMethodDispatcherImpl_0_91
@@ -165,4 +165,4 @@ public class ServerMethodDispatcherImpl_0_91 _queueUnbindHandler.methodReceived(getStateManager(),body,channelId);
return true;
}
-}
\ No newline at end of file +}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_8_0.java index fabd2a5ccf..f05219712f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/ServerMethodDispatcherImpl_8_0.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ServerMethodDispatcherImpl_8_0.java @@ -18,7 +18,7 @@ * under the License.
*
*/
-package org.apache.qpid.server.handler;
+package org.apache.qpid.server.protocol.v0_8.handler;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.BasicRecoverOkBody;
@@ -32,7 +32,7 @@ import org.apache.qpid.framing.TestStringOkBody; import org.apache.qpid.framing.TestTableBody;
import org.apache.qpid.framing.TestTableOkBody;
import org.apache.qpid.framing.amqp_8_0.MethodDispatcher_8_0;
-import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager;
public class ServerMethodDispatcherImpl_8_0
extends ServerMethodDispatcherImpl
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxCommitHandler.java index afa5fdb72a..b257030a59 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxCommitHandler.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.log4j.Logger; @@ -26,10 +26,10 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.TxCommitBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody> { @@ -75,7 +75,7 @@ public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody> }, true); - + } catch (AMQException e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java index 010a07be14..19d0da007b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxRollbackHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxRollbackHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,16 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.TxRollbackBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class TxRollbackHandler implements StateAwareMethodListener<TxRollbackBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxSelectHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxSelectHandler.java index 44b47704d8..a43e1ebdab 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/TxSelectHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/TxSelectHandler.java @@ -7,9 +7,9 @@ * 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 @@ -18,16 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.handler; +package org.apache.qpid.server.protocol.v0_8.handler; import org.apache.qpid.AMQException; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.TxSelectBody; import org.apache.qpid.framing.TxSelectOkBody; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; +import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; public class TxSelectHandler implements StateAwareMethodListener<TxSelectBody> { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/UnexpectedMethodException.java index cfc52c558c..32a9f768ec 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/UnexpectedMethodException.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/UnexpectedMethodException.java @@ -18,7 +18,7 @@ * under the License.
*
*/
-package org.apache.qpid.server.handler;
+package org.apache.qpid.server.protocol.v0_8.handler;
import org.apache.qpid.AMQException;
@@ -26,7 +26,7 @@ import org.apache.qpid.framing.AMQMethodBody; public class UnexpectedMethodException extends AMQException
{
-
+
private static final long serialVersionUID = -255921574946294892L;
public UnexpectedMethodException(AMQMethodBody body)
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverter.java index 04d81bf2f5..48e42ce5a3 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverter.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverter.java @@ -24,7 +24,7 @@ * Supported AMQP versions:
* 8-0
*/
-package org.apache.qpid.server.output;
+package org.apache.qpid.server.protocol.v0_8.output;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQDataBlock;
@@ -32,7 +32,7 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.message.MessageContentSource;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession;
import org.apache.qpid.server.queue.QueueEntry;
public interface ProtocolOutputConverter
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterImpl.java index 917215a42f..dd5e13e56a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterImpl.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.output; +package org.apache.qpid.server.protocol.v0_8.output; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQBody; @@ -27,19 +27,19 @@ import org.apache.qpid.framing.AMQFrame; import org.apache.qpid.framing.AMQMethodBody; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicCancelOkBody; -import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.BasicGetOkBody; import org.apache.qpid.framing.BasicReturnBody; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.protocol.AMQVersionAwareProtocolSession; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.protocol.MessageConverterRegistry; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.message.MessageContentSource; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.transport.DeliveryProperties; import java.io.DataOutput; import java.io.IOException; @@ -67,33 +67,34 @@ class ProtocolOutputConverterImpl implements ProtocolOutputConverter public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag) throws AMQException { - AMQBody deliverBody = createEncodedDeliverBody(entry, deliveryTag, consumerTag); - writeMessageDelivery(entry, channelId, deliverBody); + AMQMessage msg = convertToAMQMessage(entry); + AMQBody deliverBody = createEncodedDeliverBody(msg, entry.isRedelivered(), deliveryTag, consumerTag); + writeMessageDelivery(msg, channelId, deliverBody); } - - private ContentHeaderBody getContentHeaderBody(QueueEntry entry) - throws AMQException + private AMQMessage convertToAMQMessage(QueueEntry entry) { - if(entry.getMessage() instanceof AMQMessage) + ServerMessage serverMessage = entry.getMessage(); + if(serverMessage instanceof AMQMessage) { - return ((AMQMessage)entry.getMessage()).getContentHeaderBody(); + return (AMQMessage) serverMessage; } else { - final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); - BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message, entry.getQueue().getVirtualHost()); - ContentHeaderBody chb = new ContentHeaderBody(props, BASIC_CLASS_ID); - chb.setBodySize(message.getSize()); - return chb; + return getMessageConverter(serverMessage).convert(serverMessage, entry.getQueue().getVirtualHost()); } } + private <M extends ServerMessage> MessageConverter<M, AMQMessage> getMessageConverter(M message) + { + Class<M> clazz = (Class<M>) message.getClass(); + return MessageConverterRegistry.getConverter(clazz, AMQMessage.class); + } - private void writeMessageDelivery(QueueEntry entry, int channelId, AMQBody deliverBody) + private void writeMessageDelivery(AMQMessage message, int channelId, AMQBody deliverBody) throws AMQException { - writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliverBody); + writeMessageDelivery(message, message.getContentHeaderBody(), channelId, deliverBody); } private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody contentHeaderBody, int channelId, AMQBody deliverBody) @@ -188,35 +189,23 @@ class ProtocolOutputConverterImpl implements ProtocolOutputConverter public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException { AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize); - writeMessageDelivery(entry, channelId, deliver); + writeMessageDelivery(convertToAMQMessage(entry), channelId, deliver); } - private AMQBody createEncodedDeliverBody(QueueEntry entry, - final long deliveryTag, - final AMQShortString consumerTag) + private AMQBody createEncodedDeliverBody(AMQMessage message, + boolean isRedelivered, + final long deliveryTag, + final AMQShortString consumerTag) throws AMQException { final AMQShortString exchangeName; final AMQShortString routingKey; - if(entry.getMessage() instanceof AMQMessage) - { - final AMQMessage message = (AMQMessage) entry.getMessage(); - final MessagePublishInfo pb = message.getMessagePublishInfo(); - exchangeName = pb.getExchange(); - routingKey = pb.getRoutingKey(); - } - else - { - MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); - DeliveryProperties delvProps = message.getHeader().getDeliveryProperties(); - exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange()); - routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey()); - } - - final boolean isRedelivered = entry.isRedelivered(); + final MessagePublishInfo pb = message.getMessagePublishInfo(); + exchangeName = pb.getExchange(); + routingKey = pb.getRoutingKey(); final AMQBody returnBlock = new EncodedDeliveryBody(deliveryTag, routingKey, exchangeName, consumerTag, isRedelivered); return returnBlock; @@ -291,20 +280,10 @@ class ProtocolOutputConverterImpl implements ProtocolOutputConverter final AMQShortString exchangeName; final AMQShortString routingKey; - if(entry.getMessage() instanceof AMQMessage) - { - final AMQMessage message = (AMQMessage) entry.getMessage(); - final MessagePublishInfo pb = message.getMessagePublishInfo(); - exchangeName = pb.getExchange(); - routingKey = pb.getRoutingKey(); - } - else - { - MessageTransferMessage message = (MessageTransferMessage) entry.getMessage(); - DeliveryProperties delvProps = message.getHeader().getDeliveryProperties(); - exchangeName = (delvProps == null || delvProps.getExchange() == null) ? null : new AMQShortString(delvProps.getExchange()); - routingKey = (delvProps == null || delvProps.getRoutingKey() == null) ? null : new AMQShortString(delvProps.getRoutingKey()); - } + final AMQMessage message = convertToAMQMessage(entry); + final MessagePublishInfo pb = message.getMessagePublishInfo(); + exchangeName = pb.getExchange(); + routingKey = pb.getRoutingKey(); final boolean isRedelivered = entry.isRedelivered(); @@ -449,4 +428,4 @@ class ProtocolOutputConverterImpl implements ProtocolOutputConverter } } -}
\ No newline at end of file +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterRegistry.java index dcbfd89298..d4332b37ee 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterRegistry.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/output/ProtocolOutputConverterRegistry.java @@ -24,12 +24,12 @@ * Supported AMQP versions:
* 8-0
*/
-package org.apache.qpid.server.output;
+package org.apache.qpid.server.protocol.v0_8.output;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.server.output.ProtocolOutputConverter.Factory;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter.Factory;
+import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession;
import java.util.HashMap;
import java.util.Map;
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQState.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQState.java index f427cc7206..ee97d5fa87 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQState.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQState.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.state; +package org.apache.qpid.server.protocol.v0_8.state; /** * States used in the AMQ protocol. Used by the finite state machine to determine @@ -32,5 +32,5 @@ public enum AMQState CONNECTION_NOT_OPENED, CONNECTION_OPEN, CONNECTION_CLOSING, - CONNECTION_CLOSED + CONNECTION_CLOSED } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQStateManager.java index ff41536a23..0555bba98b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/AMQStateManager.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.state; +package org.apache.qpid.server.protocol.v0_8.state; import org.apache.log4j.Logger; @@ -32,7 +32,7 @@ import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; @@ -154,7 +154,7 @@ public class AMQStateManager implements AMQMethodListener return _protocolSession; } - + public SubjectCreator getSubjectCreator() { return _broker.getSubjectCreator(getProtocolSession().getLocalAddress()); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/IllegalStateTransitionException.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/IllegalStateTransitionException.java index cec67a8a6d..f61553f8a2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/IllegalStateTransitionException.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/IllegalStateTransitionException.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.state; +package org.apache.qpid.server.protocol.v0_8.state; import org.apache.qpid.AMQException; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateAwareMethodListener.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateAwareMethodListener.java index b543728f3b..63ab23919d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateAwareMethodListener.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateAwareMethodListener.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.state; +package org.apache.qpid.server.protocol.v0_8.state; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQMethodBody; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateListener.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateListener.java index 00fc09867b..e065ae0d42 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/state/StateListener.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/state/StateListener.java @@ -7,9 +7,9 @@ * 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 @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.state; +package org.apache.qpid.server.protocol.v0_8.state; import org.apache.qpid.AMQException; diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType new file mode 100644 index 0000000000..43ad3adf13 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.protocol.v0_8.MessageMetaDataType_0_8 diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator new file mode 100644 index 0000000000..57ca615a04 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator @@ -0,0 +1,21 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.protocol.v0_8.ProtocolEngineCreator_0_8 +org.apache.qpid.server.protocol.v0_8.ProtocolEngineCreator_0_9 +org.apache.qpid.server.protocol.v0_8.ProtocolEngineCreator_0_9_1 diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQChannelTest.java index e10bdbbb35..b358c7c5c5 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/AMQChannelTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQChannelTest.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server; +package org.apache.qpid.server.protocol.v0_8; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -35,8 +35,6 @@ import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.message.MessageContentSource; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolEngineTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngineTest.java index cd2a0959dc..f5e58cfd02 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolEngineTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngineTest.java @@ -1,4 +1,4 @@ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.protocol.v0_8; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java index cbbf183232..4ab64ca100 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AckTest.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.queue; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; @@ -26,17 +26,13 @@ import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.ack.UnacknowledgedMessageMap; import org.apache.qpid.server.flow.LimitlessCreditManager; import org.apache.qpid.server.flow.Pre0_10CreditManager; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.util.BrokerTestHelper; @@ -69,7 +65,7 @@ public class AckTest extends QpidTestCase { super.setUp(); BrokerTestHelper.setUp(); - _channel = BrokerTestHelper.createChannel(5); + _channel = BrokerTestHelper_0_8.createChannel(5); _protocolSession = _channel.getProtocolSession(); _virtualHost = _protocolSession.getVirtualHost(); _queue = BrokerTestHelper.createQueue(getTestName(), _virtualHost); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java index 26fc51c400..43f88ca2a3 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/ack/AcknowledgeTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AcknowledgeTest.java @@ -18,14 +18,12 @@ * under the License. * */ -package org.apache.qpid.server.ack; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; @@ -47,7 +45,7 @@ public class AcknowledgeTest extends QpidTestCase { super.setUp(); BrokerTestHelper.setUp(); - _channel = BrokerTestHelper.createChannel(); + _channel = BrokerTestHelper_0_8.createChannel(); VirtualHost virtualHost = _channel.getVirtualHost(); _queueName = getTestName(); _queue = BrokerTestHelper.createQueue(_queueName, virtualHost); @@ -125,7 +123,10 @@ public class AcknowledgeTest extends QpidTestCase checkStoreContents(0); //Send required messsages to the queue - BrokerTestHelper.publishMessages(getChannel(), sendMessageCount, _queueName, ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); + BrokerTestHelper_0_8.publishMessages(getChannel(), + sendMessageCount, + _queueName, + ExchangeDefaults.DEFAULT_EXCHANGE_NAME); if (getChannel().isTransactional()) { diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/BrokerTestHelper_0_8.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/BrokerTestHelper_0_8.java new file mode 100644 index 0000000000..0919607bd7 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/BrokerTestHelper_0_8.java @@ -0,0 +1,99 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v0_8; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class BrokerTestHelper_0_8 extends BrokerTestHelper +{ + + public static AMQChannel createChannel(int channelId, AMQProtocolSession session) throws AMQException + { + AMQChannel channel = new AMQChannel(session, channelId, session.getVirtualHost().getMessageStore()); + session.addChannel(channel); + return channel; + } + + public static AMQChannel createChannel(int channelId) throws Exception + { + InternalTestProtocolSession session = createProtocolSession(); + return createChannel(channelId, session); + } + + public static AMQChannel createChannel() throws Exception + { + return createChannel(1); + } + + public static InternalTestProtocolSession createProtocolSession() throws Exception + { + return createProtocolSession("test"); + } + + public static InternalTestProtocolSession createProtocolSession(String hostName) throws Exception + { + VirtualHost virtualHost = createVirtualHost(hostName); + return new InternalTestProtocolSession(virtualHost, createBrokerMock()); + } + + public static void publishMessages(AMQChannel channel, int numberOfMessages, String queueName, String exchangeName) throws AMQException + { + AMQShortString rouningKey = new AMQShortString(queueName); + AMQShortString exchangeNameAsShortString = new AMQShortString(exchangeName); + MessagePublishInfo info = mock(MessagePublishInfo.class); + when(info.getExchange()).thenReturn(exchangeNameAsShortString); + when(info.getRoutingKey()).thenReturn(rouningKey); + + Exchange exchange = channel.getVirtualHost().getExchange(exchangeName); + for (int count = 0; count < numberOfMessages; count++) + { + channel.setPublishFrame(info, exchange); + + // Set the body size + ContentHeaderBody _headerBody = new ContentHeaderBody(); + _headerBody.setBodySize(0); + + // Set Minimum properties + BasicContentHeaderProperties properties = new BasicContentHeaderProperties(); + + properties.setExpiration(0L); + properties.setTimestamp(System.currentTimeMillis()); + + // Make Message Persistent + properties.setDeliveryMode((byte) 2); + + _headerBody.setProperties(properties); + + channel.publishContentHeader(_headerBody); + } + channel.sync(); + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java index 616ee74b2d..7f36b4a081 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/ExtractResendAndRequeueTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ExtractResendAndRequeueTest.java @@ -18,21 +18,18 @@ * under the License. * */ -package org.apache.qpid.server; +package org.apache.qpid.server.protocol.v0_8; import junit.framework.TestCase; import org.apache.qpid.AMQException; -import org.apache.qpid.server.ack.UnacknowledgedMessageMapImpl; -import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.MockAMQMessage; import org.apache.qpid.server.queue.MockAMQQueue; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.queue.QueueEntryIterator; import org.apache.qpid.server.queue.SimpleQueueEntryList; -import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.TestMemoryMessageStore; import org.apache.qpid.server.subscription.MockSubscription; import org.apache.qpid.server.subscription.Subscription; @@ -63,7 +60,7 @@ public class ExtractResendAndRequeueTest extends TestCase private UnacknowledgedMessageMapImpl _unacknowledgedMessageMap; private static final int INITIAL_MSG_COUNT = 10; private AMQQueue _queue = new MockAMQQueue(getName()); - private MessageStore _messageStore = new MemoryMessageStore(); + private MessageStore _messageStore = new TestMemoryMessageStore(); private LinkedList<QueueEntry> _referenceList = new LinkedList<QueueEntry>(); @Override diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java index 5d3051f7b2..e8fda2bc65 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/InternalTestProtocolSession.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java @@ -18,24 +18,26 @@ * under the License. * */ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.protocol.v0_8.AMQChannel; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; import org.apache.qpid.server.message.MessageContentSource; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.output.ProtocolOutputConverter; +import org.apache.qpid.server.protocol.v0_8.AMQProtocolEngine; +import org.apache.qpid.server.protocol.v0_8.output.ProtocolOutputConverter; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionImpl; +import org.apache.qpid.server.protocol.v0_8.SubscriptionImpl; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.TestNetworkConnection; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/MaxChannelsTest.java index 99dd42e179..a77475c05f 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MaxChannelsTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/MaxChannelsTest.java @@ -18,11 +18,10 @@ * under the License. * */ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.test.utils.QpidTestCase; @@ -36,7 +35,7 @@ public class MaxChannelsTest extends QpidTestCase { super.setUp(); BrokerTestHelper.setUp(); - _session = BrokerTestHelper.createSession(); + _session = BrokerTestHelper_0_8.createProtocolSession(); } public void testChannels() throws Exception diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/MockAMQMessage.java index 12369bd7d4..1cc3607298 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQMessage.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/MockAMQMessage.java @@ -18,9 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.queue; - -import org.apache.qpid.server.message.AMQMessage; +package org.apache.qpid.server.protocol.v0_8; public class MockAMQMessage extends AMQMessage { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockMessagePublishInfo.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/MockMessagePublishInfo.java index bcf4c7efc6..ab29e58a6c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockMessagePublishInfo.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/MockMessagePublishInfo.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.queue; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.abstraction.MessagePublishInfo; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/MockStoredMessage.java index 950d59bef5..15573a871f 100755 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockStoredMessage.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/MockStoredMessage.java @@ -18,13 +18,12 @@ * under the License. * */ -package org.apache.qpid.server.queue; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.store.StoreFuture; import org.apache.qpid.server.store.StoredMessage; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java index 25b86eb73f..4f9df3b38d 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/QueueBrowserUsesNoAckTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/QueueBrowserUsesNoAckTest.java @@ -18,20 +18,18 @@ * under the License. * */ -package org.apache.qpid.server.subscription; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; +import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; @@ -50,7 +48,7 @@ public class QueueBrowserUsesNoAckTest extends QpidTestCase { super.setUp(); BrokerTestHelper.setUp(); - _channel = BrokerTestHelper.createChannel(); + _channel = BrokerTestHelper_0_8.createChannel(); VirtualHost virtualHost = _channel.getVirtualHost(); _queueName = getTestName(); _queue = BrokerTestHelper.createQueue(_queueName, virtualHost); @@ -98,7 +96,10 @@ public class QueueBrowserUsesNoAckTest extends QpidTestCase checkStoreContents(0); //Send required messsages to the queue - BrokerTestHelper.publishMessages(getChannel(), sendMessageCount, _queueName, ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); + BrokerTestHelper_0_8.publishMessages(getChannel(), + sendMessageCount, + _queueName, + ExchangeDefaults.DEFAULT_EXCHANGE_NAME); //Ensure they are stored checkStoreContents(sendMessageCount); @@ -130,7 +131,7 @@ public class QueueBrowserUsesNoAckTest extends QpidTestCase // indicate we are using the prefetch credit. i.e. using acks not No-Ack assertTrue("The subscription has been suspended", !getChannel().getSubscription(browser).getState() - .equals(Subscription.State.SUSPENDED)); + .equals(Subscription.State.SUSPENDED)); } private void checkStoreContents(int messageCount) diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ReferenceCountingTest.java index 7c6891da71..87fbcfa9b3 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/ReferenceCountingTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/ReferenceCountingTest.java @@ -18,16 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.store; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.test.utils.QpidTestCase; /** diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImplTest.java index efb62ba085..e98dd63450 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/SubscriptionFactoryImplTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/SubscriptionFactoryImplTest.java @@ -18,27 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.subscription; +package org.apache.qpid.server.protocol.v0_8; import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.flow.WindowCreditManager; import org.apache.qpid.server.logging.UnitTestMessageLogger; import org.apache.qpid.server.logging.actors.GenericActor; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.ProtocolEngine_0_10; -import org.apache.qpid.server.transport.ServerConnection; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.server.transport.ServerSessionDelegate; +import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.test.utils.QpidTestCase; -import org.apache.qpid.transport.Binary; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageFlowMode; -import org.apache.qpid.transport.TestNetworkConnection; public class SubscriptionFactoryImplTest extends QpidTestCase { @@ -50,7 +39,7 @@ public class SubscriptionFactoryImplTest extends QpidTestCase { super.setUp(); BrokerTestHelper.setUp(); - _channel = BrokerTestHelper.createChannel(); + _channel = BrokerTestHelper_0_8.createChannel(); _session = _channel.getProtocolSession(); GenericActor.setDefaultMessageLogger(new UnitTestMessageLogger(false)); } @@ -102,17 +91,6 @@ public class SubscriptionFactoryImplTest extends QpidTestCase assertEquals("Unexpected Subscription ID allocated", previousId + 1, getNoAckSub.getSubscriptionID()); previousId = getNoAckSub.getSubscriptionID(); - //create a 0-10 subscription - ServerConnection conn = new ServerConnection(1); - ProtocolEngine_0_10 engine = new ProtocolEngine_0_10(conn, new TestNetworkConnection(), null, null); - conn.setVirtualHost(_session.getVirtualHost()); - ServerSessionDelegate sesDel = new ServerSessionDelegate(); - Binary name = new Binary(new byte[]{new Byte("1")}); - ServerSession session = new ServerSession(conn, sesDel, name, 0); - - Subscription sub_0_10 = SubscriptionFactoryImpl.INSTANCE.createSubscription(session, "1", MessageAcceptMode.EXPLICIT, - MessageAcquireMode.PRE_ACQUIRED, MessageFlowMode.WINDOW, new WindowCreditManager(), null, null); - assertEquals("Unexpected Subscription ID allocated", previousId + 1, sub_0_10.getSubscriptionID()); } } diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/build.xml b/qpid/java/broker-plugins/amqp-1-0-protocol/build.xml new file mode 100644 index 0000000000..b83e3eeae1 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/build.xml @@ -0,0 +1,40 @@ +<!-- + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + --> +<project name="Qpid Broker-Plugins AMQP 1.0 Protocol" default="build"> + <property name="module.depends" value="common broker amqp-1-0-common" /> + <property name="module.test.depends" value="common/tests broker/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/> + <property name="broker-plugins-amqp-1-0-protocol.libs" value="" /> + + <property name="broker.plugin" value="true"/> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> + + <!-- Overrides, but depends on, target in module.xml --> + <target name="copy-broker-plugin-jars-deps" depends="module.copy-broker-plugin-jars-deps" if="broker.plugin" description="copy broker plugins dependencies for use in release packaging"> + <copy todir="${build.scratch.broker.plugins.lib}" failonerror="true" flatten="true"> + <fileset file="${build.lib}/${project.name}-amqp-1-0-common-${project.version}.jar"/> + </copy> + </target> + +</project> diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java index bf5f34e17a..320875cc97 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java @@ -242,6 +242,12 @@ public class Connection_1_0 implements ConnectionEventListener } @Override + public String getVirtualHostName() + { + return _vhost == null ? null : _vhost.getName(); + } + + @Override public Port getPort() { return _port; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java index d45758391c..d45758391c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Destination.java diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java index 2cef27267b..2cef27267b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ExchangeDestination.java diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.java index db81d3b205..5ce24f406d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Link_1_0.java @@ -20,7 +20,9 @@ */ package org.apache.qpid.server.protocol.v1_0; -public interface Link_1_0 +import org.apache.qpid.server.protocol.LinkModel; + +public interface Link_1_0 extends LinkModel { void start(); } diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java new file mode 100644 index 0000000000..be9b0323a3 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java @@ -0,0 +1,245 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v1_0; + +import java.io.EOFException; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import org.apache.qpid.amqp_1_0.messaging.SectionEncoder; +import org.apache.qpid.amqp_1_0.messaging.SectionEncoderImpl; +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry; +import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; +import org.apache.qpid.amqp_1_0.type.messaging.Data; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.codec.BBDecoder; +import org.apache.qpid.typedmessage.TypedBytesContentReader; +import org.apache.qpid.typedmessage.TypedBytesFormatException; + +public abstract class MessageConverter_to_1_0<M extends ServerMessage> implements MessageConverter<M, Message_1_0> +{ + private final AMQPDescribedTypeRegistry _typeRegistry = AMQPDescribedTypeRegistry.newInstance() + .registerTransportLayer() + .registerMessagingLayer() + .registerTransactionLayer() + .registerSecurityLayer(); + + @Override + public final Class<Message_1_0> getOutputClass() + { + return Message_1_0.class; + } + + @Override + public final Message_1_0 convert(M message, VirtualHost vhost) + { + + SectionEncoder sectionEncoder = new SectionEncoderImpl(_typeRegistry); + return new Message_1_0(convertToStoredMessage(message, sectionEncoder)); + } + + + private StoredMessage<MessageMetaData_1_0> convertToStoredMessage(final M serverMessage, SectionEncoder sectionEncoder) + { + final MessageMetaData_1_0 metaData = convertMetaData(serverMessage, sectionEncoder); + return convertServerMessage(metaData, serverMessage, sectionEncoder); + } + + abstract protected MessageMetaData_1_0 convertMetaData(final M serverMessage, SectionEncoder sectionEncoder); + + + private static Section convertMessageBody(String mimeType, byte[] data) + { + if("text/plain".equals(mimeType) || "text/xml".equals(mimeType)) + { + String text = new String(data); + return new AmqpValue(text); + } + else if("jms/map-message".equals(mimeType)) + { + TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); + + LinkedHashMap map = new LinkedHashMap(); + final int entries = reader.readIntImpl(); + for (int i = 0; i < entries; i++) + { + try + { + String propName = reader.readStringImpl(); + Object value = reader.readObject(); + map.put(propName, value); + } + catch (EOFException e) + { + throw new IllegalArgumentException(e); + } + catch (TypedBytesFormatException e) + { + throw new IllegalArgumentException(e); + } + + } + + return new AmqpValue(map); + + } + else if("amqp/map".equals(mimeType)) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(data)); + return new AmqpValue(decoder.readMap()); + + } + else if("amqp/list".equals(mimeType)) + { + BBDecoder decoder = new BBDecoder(); + decoder.init(ByteBuffer.wrap(data)); + return new AmqpValue(decoder.readList()); + } + else if("jms/stream-message".equals(mimeType)) + { + TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); + + List list = new ArrayList(); + while (reader.remaining() != 0) + { + try + { + list.add(reader.readObject()); + } + catch (TypedBytesFormatException e) + { + throw new RuntimeException(e); // TODO - Implement + } + catch (EOFException e) + { + throw new RuntimeException(e); // TODO - Implement + } + } + return new AmqpValue(list); + } + else + { + return new Data(new Binary(data)); + + } + } + + private StoredMessage<MessageMetaData_1_0> convertServerMessage(final MessageMetaData_1_0 metaData, + final ServerMessage serverMessage, + SectionEncoder sectionEncoder) + { + final String mimeType = serverMessage.getMessageHeader().getMimeType(); + byte[] data = new byte[(int) serverMessage.getSize()]; + serverMessage.getContent(ByteBuffer.wrap(data), 0); + + Section bodySection = convertMessageBody(mimeType, data); + + final ByteBuffer allData = encodeConvertedMessage(metaData, bodySection, sectionEncoder); + + return new StoredMessage<MessageMetaData_1_0>() + { + @Override + public MessageMetaData_1_0 getMetaData() + { + return metaData; + } + + @Override + public long getMessageNumber() + { + return serverMessage.getMessageNumber(); + } + + @Override + public void addContent(int offsetInMessage, ByteBuffer src) + { + throw new UnsupportedOperationException(); + } + + @Override + public int getContent(int offsetInMessage, ByteBuffer dst) + { + ByteBuffer buf = allData.duplicate(); + buf.position(offsetInMessage); + buf = buf.slice(); + int size; + if(dst.remaining()<buf.remaining()) + { + buf.limit(dst.remaining()); + size = dst.remaining(); + } + else + { + size = buf.remaining(); + } + dst.put(buf); + return size; + } + + @Override + public ByteBuffer getContent(int offsetInMessage, int size) + { + ByteBuffer buf = allData.duplicate(); + buf.position(offsetInMessage); + buf = buf.slice(); + if(size < buf.remaining()) + { + buf.limit(size); + } + return buf; + } + + @Override + public StoreFuture flushToStore() + { + throw new UnsupportedOperationException(); + } + + @Override + public void remove() + { + serverMessage.getStoredMessage().remove(); + } + }; + } + + private ByteBuffer encodeConvertedMessage(MessageMetaData_1_0 metaData, Section bodySection, SectionEncoder sectionEncoder) + { + int headerSize = (int) metaData.getStorableSize(); + + sectionEncoder.reset(); + sectionEncoder.encodeObject(bodySection); + Binary dataEncoding = sectionEncoder.getEncoding(); + + final ByteBuffer allData = ByteBuffer.allocate(headerSize + dataEncoding.getLength()); + metaData.writeToBuffer(0,allData); + allData.put(dataEncoding.getArray(),dataEncoding.getArrayOffset(),dataEncoding.getLength()); + return allData; + } +} diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaDataType_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaDataType_1_0.java new file mode 100644 index 0000000000..44b1de74e1 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaDataType_1_0.java @@ -0,0 +1,67 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v1_0; + +import java.nio.ByteBuffer; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.plugin.MessageMetaDataType; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.store.StoredMessage; + +public class MessageMetaDataType_1_0 implements MessageMetaDataType<MessageMetaData_1_0> +{ + + public static final int TYPE = 2; + + @Override + public int ordinal() + { + return TYPE; + } + + @Override + public MessageMetaData_1_0 createMetaData(ByteBuffer buf) + { + return MessageMetaData_1_0.FACTORY.createMetaData(buf); + } + + @Override + public ServerMessage<MessageMetaData_1_0> createMessage(StoredMessage<MessageMetaData_1_0> msg) + { + return new Message_1_0(msg); + } + + public int hashCode() + { + return ordinal(); + } + + public boolean equals(Object o) + { + return o != null && o.getClass() == getClass(); + } + + @Override + public String getType() + { + return AmqpProtocolVersion.v1_0_0.toString(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java index 1d8b239733..8d48d70d9a 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageMetaData_1_0.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.message; +package org.apache.qpid.server.protocol.v1_0; import java.nio.ByteBuffer; import java.util.*; @@ -38,13 +38,16 @@ import org.apache.qpid.amqp_1_0.type.messaging.Footer; import org.apache.qpid.amqp_1_0.type.messaging.Header; import org.apache.qpid.amqp_1_0.type.messaging.MessageAnnotations; import org.apache.qpid.amqp_1_0.type.messaging.Properties; -import org.apache.qpid.server.store.MessageMetaDataType; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.plugin.MessageMetaDataType; import org.apache.qpid.server.store.StorableMessageMetaData; public class MessageMetaData_1_0 implements StorableMessageMetaData { // TODO move to somewhere more useful public static final Symbol JMS_TYPE = Symbol.valueOf("x-opt-jms-type"); + public static final MessageMetaDataType.Factory<MessageMetaData_1_0> FACTORY = new MetaDataFactory(); + private static final MessageMetaDataType_1_0 TYPE = new MessageMetaDataType_1_0(); private Header _header; @@ -280,7 +283,7 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData public MessageMetaDataType getType() { - return MessageMetaDataType.META_DATA_1_0; + return TYPE; } @@ -352,7 +355,7 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData return _messageHeader; } - public static final MessageMetaDataType.Factory<MessageMetaData_1_0> FACTORY = new MetaDataFactory(); + private static class MetaDataFactory implements MessageMetaDataType.Factory<MessageMetaData_1_0> diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java index c87028e190..68e9a88b0b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java @@ -28,12 +28,11 @@ import java.util.List; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageMetaData_1_0; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.store.StoredMessage; -public class Message_1_0 implements ServerMessage, InboundMessage +public class Message_1_0 implements ServerMessage<MessageMetaData_1_0>, InboundMessage { @@ -98,11 +97,6 @@ public class Message_1_0 implements ServerMessage, InboundMessage } } - public AMQShortString getRoutingKeyShortString() - { - return AMQShortString.valueOf(getRoutingKey()); - } - private MessageMetaData_1_0 getMessageMetaData() { return _storedMessage.getMetaData(); diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0.java new file mode 100644 index 0000000000..c06af603de --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0.java @@ -0,0 +1,80 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v1_0; + +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.plugin.ProtocolEngineCreator; +import org.apache.qpid.transport.network.NetworkConnection; + +public class ProtocolEngineCreator_1_0_0 implements ProtocolEngineCreator +{ + private static final byte[] AMQP_1_0_0_HEADER = + new byte[] { (byte) 'A', + (byte) 'M', + (byte) 'Q', + (byte) 'P', + (byte) 0, + (byte) 1, + (byte) 0, + (byte) 0 + }; + + public ProtocolEngineCreator_1_0_0() + { + } + + public AmqpProtocolVersion getVersion() + { + return AmqpProtocolVersion.v1_0_0; + } + + + public byte[] getHeaderIdentifier() + { + return AMQP_1_0_0_HEADER; + } + + public ServerProtocolEngine newProtocolEngine(Broker broker, + NetworkConnection network, + Port port, + Transport transport, + long id) + { + return new ProtocolEngine_1_0_0(network, broker, id, port, transport); + } + + private static ProtocolEngineCreator INSTANCE = new ProtocolEngineCreator_1_0_0(); + + public static ProtocolEngineCreator getInstance() + { + return INSTANCE; + } + + @Override + public String getType() + { + return getVersion().toString() + "_NO_SASL"; + } +} diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0_SASL.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0_SASL.java new file mode 100644 index 0000000000..d3936782da --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngineCreator_1_0_0_SASL.java @@ -0,0 +1,80 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.v1_0; + +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.plugin.ProtocolEngineCreator; +import org.apache.qpid.transport.network.NetworkConnection; + +public class ProtocolEngineCreator_1_0_0_SASL implements ProtocolEngineCreator +{ + private static final byte[] AMQP_SASL_1_0_0_HEADER = + new byte[] { (byte) 'A', + (byte) 'M', + (byte) 'Q', + (byte) 'P', + (byte) 3, + (byte) 1, + (byte) 0, + (byte) 0 + }; + + public ProtocolEngineCreator_1_0_0_SASL() + { + } + + public AmqpProtocolVersion getVersion() + { + return AmqpProtocolVersion.v1_0_0; + } + + + public byte[] getHeaderIdentifier() + { + return AMQP_SASL_1_0_0_HEADER; + } + + public ServerProtocolEngine newProtocolEngine(Broker broker, + NetworkConnection network, + Port port, + Transport transport, + long id) + { + return new ProtocolEngine_1_0_0_SASL(network, broker, id, port, transport); + } + + private static ProtocolEngineCreator INSTANCE = new ProtocolEngineCreator_1_0_0_SASL(); + + public static ProtocolEngineCreator getInstance() + { + return INSTANCE; + } + + @Override + public String getType() + { + return getVersion().toString(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java index 7d5459dce6..1bddda2f38 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.protocol.v1_0; import java.net.SocketAddress; import java.nio.ByteBuffer; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java index 9472e08ca5..d614f44981 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ProtocolEngine_1_0_0_SASL.java @@ -18,7 +18,7 @@ * under the License. * */ -package org.apache.qpid.server.protocol; +package org.apache.qpid.server.protocol.v1_0; import java.io.PrintWriter; import java.net.SocketAddress; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java index af3f0b7872..af3f0b7872 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/QueueDestination.java diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java index 4ae0596e25..4ae0596e25 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingDestination.java diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java index 46b9682c74..46b9682c74 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java index 3e2652b3b8..e971672767 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLink_1_0.java @@ -41,7 +41,6 @@ import org.apache.qpid.amqp_1_0.type.transaction.TransactionalState; import org.apache.qpid.amqp_1_0.type.transport.Detach; import org.apache.qpid.amqp_1_0.type.transport.ReceiverSettleMode; import org.apache.qpid.amqp_1_0.type.transport.Transfer; -import org.apache.qpid.server.message.MessageMetaData_1_0; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java index 6d601c9dda..6d601c9dda 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingDestination.java diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java index 09a2ddea3a..09a2ddea3a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java index ca67b6f79b..35f24afbce 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java @@ -110,10 +110,12 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS if(destination instanceof QueueDestination) { queue = ((QueueDestination) _destination).getQueue(); - if(queue.getArguments() != null && queue.getArguments().containsKey("topic")) + + if(queue.getAvailableAttributes().contains("topic")) { source.setDistributionMode(StdDistMode.COPY); } + qd = (QueueDestination) destination; Map<Symbol,Filter> filters = source.getFilter(); @@ -194,19 +196,19 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS name = UUID.randomUUID().toString(); } - queue = _vhost.getQueueRegistry().getQueue(name); + queue = _vhost.getQueue(name); Exchange exchange = exchangeDestination.getExchange(); if(queue == null) { - queue = AMQQueueFactory.createAMQQueueImpl( + queue = _vhost.createQueue( UUIDGenerator.generateQueueUUID(name, _vhost.getName()), name, isDurable, null, true, true, - _vhost, + true, Collections.EMPTY_MAP); } else @@ -309,11 +311,11 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS { public void doTask(Connection_1_0 session) { - if (_vhost.getQueueRegistry().getQueue(queueName) == tempQueue) + if (_vhost.getQueue(queueName) == tempQueue) { try { - tempQueue.delete(); + _vhost.removeQueue(tempQueue); } catch (AMQException e) { @@ -417,7 +419,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS { try { - queue.delete(); + queue.getVirtualHost().removeQueue(queue); } catch(AMQException e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java index ce6ef0b183..d3962c779c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java @@ -43,6 +43,7 @@ import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.protocol.LinkRegistry; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.txn.AutoCommitTransaction; @@ -81,13 +82,15 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu Link_1_0 link = null; Error error = null; - final LinkRegistry linkRegistry = _vhost.getLinkRegistry(endpoint.getSession().getConnection().getRemoteContainerId()); + final + LinkRegistry + linkRegistry = _vhost.getLinkRegistry(endpoint.getSession().getConnection().getRemoteContainerId()); if(endpoint.getRole() == Role.SENDER) { - SendingLink_1_0 previousLink = linkRegistry.getDurableSendingLink(endpoint.getName()); + SendingLink_1_0 previousLink = (SendingLink_1_0) linkRegistry.getDurableSendingLink(endpoint.getName()); if(previousLink == null) { @@ -104,7 +107,7 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu source.setAddress(tempQueue.getName()); } String addr = source.getAddress(); - AMQQueue queue = _vhost.getQueueRegistry().getQueue(addr); + AMQQueue queue = _vhost.getQueue(addr); if(queue != null) { @@ -227,7 +230,8 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu else { - ReceivingLink_1_0 previousLink = linkRegistry.getDurableReceivingLink(endpoint.getName()); + ReceivingLink_1_0 previousLink = + (ReceivingLink_1_0) linkRegistry.getDurableReceivingLink(endpoint.getName()); if(previousLink == null) { @@ -252,7 +256,7 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu } else { - AMQQueue queue = _vhost.getQueueRegistry().getQueue(addr); + AMQQueue queue = _vhost.getQueue(addr); if(queue != null) { @@ -325,14 +329,14 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu ? null : (LifetimePolicy) properties.get(LIFETIME_POLICY); - final AMQQueue tempQueue = queue = AMQQueueFactory.createAMQQueueImpl( UUIDGenerator.generateQueueUUID(queueName, _vhost.getName()), - queueName, - false, // durable - null, // owner - false, // autodelete - false, // exclusive - _vhost, - properties); + final AMQQueue tempQueue = queue = _vhost.createQueue( UUIDGenerator.generateQueueUUID(queueName, _vhost.getName()), + queueName, + false, // durable + null, // owner + false, // autodelete + false, // exclusive + false, + properties); @@ -343,11 +347,11 @@ public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSu { public void doTask(Connection_1_0 session) { - if (_vhost.getQueueRegistry().getQueue(queueName) == tempQueue) + if (_vhost.getQueue(queueName) == tempQueue) { try { - tempQueue.delete(); + _vhost.removeQueue(tempQueue); } catch (AMQException e) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java index 44ee945548..b9695ba87a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java @@ -20,10 +20,7 @@ */ package org.apache.qpid.server.protocol.v1_0; -import java.io.EOFException; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -38,46 +35,27 @@ import org.apache.qpid.amqp_1_0.type.AmqpErrorException; import org.apache.qpid.amqp_1_0.type.Binary; import org.apache.qpid.amqp_1_0.type.DeliveryState; import org.apache.qpid.amqp_1_0.type.Outcome; -import org.apache.qpid.amqp_1_0.type.Section; -import org.apache.qpid.amqp_1_0.type.Symbol; -import org.apache.qpid.amqp_1_0.type.UnsignedByte; import org.apache.qpid.amqp_1_0.type.UnsignedInteger; import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry; import org.apache.qpid.amqp_1_0.type.messaging.Accepted; -import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue; -import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties; -import org.apache.qpid.amqp_1_0.type.messaging.Data; import org.apache.qpid.amqp_1_0.type.messaging.Header; import org.apache.qpid.amqp_1_0.type.messaging.Modified; -import org.apache.qpid.amqp_1_0.type.messaging.Properties; import org.apache.qpid.amqp_1_0.type.messaging.Released; import org.apache.qpid.amqp_1_0.type.messaging.Source; import org.apache.qpid.amqp_1_0.type.messaging.StdDistMode; import org.apache.qpid.amqp_1_0.type.transaction.TransactionalState; import org.apache.qpid.amqp_1_0.type.transport.SenderSettleMode; import org.apache.qpid.amqp_1_0.type.transport.Transfer; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.typedmessage.TypedBytesContentReader; -import org.apache.qpid.typedmessage.TypedBytesFormatException; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.protocol.MessageConverterRegistry; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData_1_0; -import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.StoreFuture; -import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.txn.ServerTransaction; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.MessageDeliveryMode; -import org.apache.qpid.transport.MessageProperties; -import org.apache.qpid.transport.codec.BBDecoder; class Subscription_1_0 implements Subscription { @@ -169,9 +147,18 @@ class Subscription_1_0 implements Subscription public boolean hasInterest(final QueueEntry entry) { - return !(_noLocal && (entry.getMessage() instanceof Message_1_0) - && ((Message_1_0)entry.getMessage()).getSession() == getSession()) - && checkFilters(entry); + if(entry.getMessage() instanceof Message_1_0) + { + if(_noLocal && ((Message_1_0)entry.getMessage()).getSession() == getSession()) + { + return false; + } + } + else if(MessageConverterRegistry.getConverter(entry.getMessage().getClass(), Message_1_0.class)==null) + { + return false; + } + return checkFilters(entry); } @@ -222,18 +209,8 @@ class Subscription_1_0 implements Subscription } else { - if(serverMessage instanceof AMQMessage) - { - message = new Message_1_0(convert08Message((AMQMessage)serverMessage)); - } - else if(serverMessage instanceof MessageTransferMessage) - { - message = new Message_1_0(convert010Message((MessageTransferMessage)serverMessage)); - } - else - { - return; - } + final MessageConverter converter = MessageConverterRegistry.getConverter(serverMessage.getClass(), Message_1_0.class); + message = (Message_1_0) converter.convert(serverMessage, queueEntry.getQueue().getVirtualHost()); } Transfer transfer = new Transfer(); @@ -376,329 +353,6 @@ class Subscription_1_0 implements Subscription } - private StoredMessage<MessageMetaData_1_0> convert010Message(final MessageTransferMessage serverMessage) - { - final MessageMetaData_1_0 metaData = convertMetaData(serverMessage); - - return convertServerMessage(metaData, serverMessage); - - } - - private MessageMetaData_1_0 convertMetaData(final MessageTransferMessage serverMessage) - { - List<Section> sections = new ArrayList<Section>(3); - final MessageProperties msgProps = serverMessage.getHeader().getMessageProperties(); - final DeliveryProperties deliveryProps = serverMessage.getHeader().getDeliveryProperties(); - - Header header = new Header(); - if(deliveryProps != null) - { - header.setDurable(deliveryProps.hasDeliveryMode() && deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT); - if(deliveryProps.hasPriority()) - { - header.setPriority(UnsignedByte.valueOf((byte)deliveryProps.getPriority().getValue())); - } - if(deliveryProps.hasTtl()) - { - header.setTtl(UnsignedInteger.valueOf(deliveryProps.getTtl())); - } - sections.add(header); - } - - Properties props = new Properties(); - if(msgProps != null) - { - // props.setAbsoluteExpiryTime(); - if(msgProps.hasContentEncoding()) - { - props.setContentEncoding(Symbol.valueOf(msgProps.getContentEncoding())); - } - - if(msgProps.hasCorrelationId()) - { - props.setCorrelationId(msgProps.getCorrelationId()); - } - // props.setCreationTime(); - // props.setGroupId(); - // props.setGroupSequence(); - if(msgProps.hasMessageId()) - { - props.setMessageId(msgProps.getMessageId()); - } - if(msgProps.hasReplyTo()) - { - props.setReplyTo(msgProps.getReplyTo().getExchange()+"/"+msgProps.getReplyTo().getRoutingKey()); - } - if(msgProps.hasContentType()) - { - props.setContentType(Symbol.valueOf(msgProps.getContentType())); - - // Modify the content type when we are dealing with java object messages produced by the Qpid 0.x client - if(props.getContentType() == Symbol.valueOf("application/java-object-stream")) - { - props.setContentType(Symbol.valueOf("application/x-java-serialized-object")); - } - } - // props.setReplyToGroupId(); - props.setSubject(serverMessage.getRoutingKey()); - // props.setTo(); - if(msgProps.hasUserId()) - { - props.setUserId(new Binary(msgProps.getUserId())); - } - - sections.add(props); - - if(msgProps.getApplicationHeaders() != null) - { - sections.add(new ApplicationProperties(msgProps.getApplicationHeaders())); - } - } - return new MessageMetaData_1_0(sections, _sectionEncoder); - } - - private StoredMessage<MessageMetaData_1_0> convert08Message(final AMQMessage serverMessage) - { - final MessageMetaData_1_0 metaData = convertMetaData(serverMessage); - - return convertServerMessage(metaData, serverMessage); - - - } - - private StoredMessage<MessageMetaData_1_0> convertServerMessage(final MessageMetaData_1_0 metaData, - final ServerMessage serverMessage) - { - final String mimeType = serverMessage.getMessageHeader().getMimeType(); - byte[] data = new byte[(int) serverMessage.getSize()]; - serverMessage.getContent(ByteBuffer.wrap(data), 0); - - Section bodySection = convertMessageBody(mimeType, data); - - final ByteBuffer allData = encodeConvertedMessage(metaData, bodySection); - - return new StoredMessage<MessageMetaData_1_0>() - { - @Override - public MessageMetaData_1_0 getMetaData() - { - return metaData; - } - - @Override - public long getMessageNumber() - { - return serverMessage.getMessageNumber(); - } - - @Override - public void addContent(int offsetInMessage, ByteBuffer src) - { - throw new UnsupportedOperationException(); - } - - @Override - public int getContent(int offsetInMessage, ByteBuffer dst) - { - ByteBuffer buf = allData.duplicate(); - buf.position(offsetInMessage); - buf = buf.slice(); - int size; - if(dst.remaining()<buf.remaining()) - { - buf.limit(dst.remaining()); - size = dst.remaining(); - } - else - { - size = buf.remaining(); - } - dst.put(buf); - return size; - } - - @Override - public ByteBuffer getContent(int offsetInMessage, int size) - { - ByteBuffer buf = allData.duplicate(); - buf.position(offsetInMessage); - buf = buf.slice(); - if(size < buf.remaining()) - { - buf.limit(size); - } - return buf; - } - - @Override - public StoreFuture flushToStore() - { - throw new UnsupportedOperationException(); - } - - @Override - public void remove() - { - serverMessage.getStoredMessage().remove(); - } - }; - } - - private ByteBuffer encodeConvertedMessage(MessageMetaData_1_0 metaData, Section bodySection) - { - int headerSize = (int) metaData.getStorableSize(); - - _sectionEncoder.reset(); - _sectionEncoder.encodeObject(bodySection); - Binary dataEncoding = _sectionEncoder.getEncoding(); - - final ByteBuffer allData = ByteBuffer.allocate(headerSize + dataEncoding.getLength()); - metaData.writeToBuffer(0,allData); - allData.put(dataEncoding.getArray(),dataEncoding.getArrayOffset(),dataEncoding.getLength()); - return allData; - } - - private static Section convertMessageBody(String mimeType, byte[] data) - { - if("text/plain".equals(mimeType) || "text/xml".equals(mimeType)) - { - String text = new String(data); - return new AmqpValue(text); - } - else if("jms/map-message".equals(mimeType)) - { - TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); - - LinkedHashMap map = new LinkedHashMap(); - final int entries = reader.readIntImpl(); - for (int i = 0; i < entries; i++) - { - try - { - String propName = reader.readStringImpl(); - Object value = reader.readObject(); - map.put(propName, value); - } - catch (EOFException e) - { - throw new IllegalArgumentException(e); - } - catch (TypedBytesFormatException e) - { - throw new IllegalArgumentException(e); - } - - } - - return new AmqpValue(map); - - } - else if("amqp/map".equals(mimeType)) - { - BBDecoder decoder = new BBDecoder(); - decoder.init(ByteBuffer.wrap(data)); - return new AmqpValue(decoder.readMap()); - - } - else if("amqp/list".equals(mimeType)) - { - BBDecoder decoder = new BBDecoder(); - decoder.init(ByteBuffer.wrap(data)); - return new AmqpValue(decoder.readList()); - } - else if("jms/stream-message".equals(mimeType)) - { - TypedBytesContentReader reader = new TypedBytesContentReader(ByteBuffer.wrap(data)); - - List list = new ArrayList(); - while (reader.remaining() != 0) - { - try - { - list.add(reader.readObject()); - } - catch (TypedBytesFormatException e) - { - throw new RuntimeException(e); // TODO - Implement - } - catch (EOFException e) - { - throw new RuntimeException(e); // TODO - Implement - } - } - return new AmqpValue(list); - } - else - { - return new Data(new Binary(data)); - - } - } - - private MessageMetaData_1_0 convertMetaData(final AMQMessage serverMessage) - { - - List<Section> sections = new ArrayList<Section>(3); - - Header header = new Header(); - - header.setDurable(serverMessage.isPersistent()); - - BasicContentHeaderProperties contentHeader = - (BasicContentHeaderProperties) serverMessage.getContentHeaderBody().getProperties(); - - header.setPriority(UnsignedByte.valueOf(contentHeader.getPriority())); - final long expiration = serverMessage.getExpiration(); - final long arrivalTime = serverMessage.getArrivalTime(); - - if(expiration > arrivalTime) - { - header.setTtl(UnsignedInteger.valueOf(expiration - arrivalTime)); - } - sections.add(header); - - - Properties props = new Properties(); - - props.setContentEncoding(Symbol.valueOf(contentHeader.getEncodingAsString())); - - props.setContentType(Symbol.valueOf(contentHeader.getContentTypeAsString())); - - // Modify the content type when we are dealing with java object messages produced by the Qpid 0.x client - if(props.getContentType() == Symbol.valueOf("application/java-object-stream")) - { - props.setContentType(Symbol.valueOf("application/x-java-serialized-object")); - } - - final AMQShortString correlationId = contentHeader.getCorrelationId(); - if(correlationId != null) - { - props.setCorrelationId(new Binary(correlationId.getBytes())); - } - // props.setCreationTime(); - // props.setGroupId(); - // props.setGroupSequence(); - final AMQShortString messageId = contentHeader.getMessageId(); - if(messageId != null) - { - props.setMessageId(new Binary(messageId.getBytes())); - } - props.setReplyTo(String.valueOf(contentHeader.getReplyTo())); - - // props.setReplyToGroupId(); - props.setSubject(serverMessage.getRoutingKey()); - // props.setTo(); - if(contentHeader.getUserId() != null) - { - props.setUserId(new Binary(contentHeader.getUserId().getBytes())); - } - sections.add(props); - - sections.add(new ApplicationProperties(FieldTable.convertToMap(contentHeader.getHeaders()))); - - return new MessageMetaData_1_0(sections, _sectionEncoder); - } - public void queueDeleted(final AMQQueue queue) { //TODO diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java index a05d14816a..a05d14816a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/TxnCoordinatorLink_1_0.java diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java index 0fee4086b4..0fee4086b4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType new file mode 100644 index 0000000000..91c673215c --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageMetaDataType @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.protocol.v1_0.MessageMetaDataType_1_0 diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator new file mode 100644 index 0000000000..fafbacd0a1 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.ProtocolEngineCreator @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.protocol.v1_0.ProtocolEngineCreator_1_0_0 +org.apache.qpid.server.protocol.v1_0.ProtocolEngineCreator_1_0_0_SASL diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/build.xml b/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/build.xml new file mode 100644 index 0000000000..cddbcf5bae --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/build.xml @@ -0,0 +1,33 @@ +<!-- + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + --> +<project name="Qpid Broker-Plugins AMQP 0.8 to 1.0 MessageConversion" default="build"> + <property name="module.depends" value="common broker amqp-1-0-common broker-plugins/amqp-1-0-protocol broker-plugins/amqp-0-10-protocol" /> + <property name="module.test.depends" value="common/tests broker/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided -Sqpid-amqp-1-0-common=provided -Sqpid-broker-plugins-amqp-0-10-protocol=provided -Sqpid-broker-plugins-amqp-1-0-protocol=provided"/> + <property name="broker-plugins-amqp-msg-conv-0-10-to-1-0.libs" value="" /> + + <property name="broker.plugin" value="true"/> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> + +</project> diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_0_10_to_1_0.java b/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_0_10_to_1_0.java new file mode 100644 index 0000000000..a70bd4b243 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_10_v1_0/MessageConverter_0_10_to_1_0.java @@ -0,0 +1,140 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.protocol.converter.v0_10_v1_0; + +import java.util.ArrayList; +import java.util.List; +import org.apache.qpid.amqp_1_0.messaging.SectionEncoder; +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.Symbol; +import org.apache.qpid.amqp_1_0.type.UnsignedByte; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; +import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties; +import org.apache.qpid.amqp_1_0.type.messaging.Header; +import org.apache.qpid.amqp_1_0.type.messaging.Properties; +import org.apache.qpid.server.protocol.v0_10.MessageTransferMessage; +import org.apache.qpid.server.protocol.v1_0.MessageConverter_to_1_0; +import org.apache.qpid.server.protocol.v1_0.MessageMetaData_1_0; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.MessageDeliveryMode; +import org.apache.qpid.transport.MessageProperties; + +public class MessageConverter_0_10_to_1_0 extends MessageConverter_to_1_0<MessageTransferMessage> +{ + @Override + public Class<MessageTransferMessage> getInputClass() + { + return MessageTransferMessage.class; + } + + + @Override + protected MessageMetaData_1_0 convertMetaData(MessageTransferMessage serverMessage, + SectionEncoder sectionEncoder) + { + List<Section> sections = new ArrayList<Section>(3); + final MessageProperties msgProps = serverMessage.getHeader().getMessageProperties(); + final DeliveryProperties deliveryProps = serverMessage.getHeader().getDeliveryProperties(); + + Header header = new Header(); + if(deliveryProps != null) + { + header.setDurable(deliveryProps.hasDeliveryMode() && deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT); + if(deliveryProps.hasPriority()) + { + header.setPriority(UnsignedByte.valueOf((byte) deliveryProps.getPriority().getValue())); + } + if(deliveryProps.hasTtl()) + { + header.setTtl(UnsignedInteger.valueOf(deliveryProps.getTtl())); + } + sections.add(header); + } + + Properties props = new Properties(); + + /* + TODO: the current properties are not currently set: + + absoluteExpiryTime + creationTime + groupId + groupSequence + replyToGroupId + to + */ + + if(msgProps != null) + { + if(msgProps.hasContentEncoding()) + { + props.setContentEncoding(Symbol.valueOf(msgProps.getContentEncoding())); + } + + if(msgProps.hasCorrelationId()) + { + props.setCorrelationId(msgProps.getCorrelationId()); + } + + if(msgProps.hasMessageId()) + { + props.setMessageId(msgProps.getMessageId()); + } + if(msgProps.hasReplyTo()) + { + props.setReplyTo(msgProps.getReplyTo().getExchange()+"/"+msgProps.getReplyTo().getRoutingKey()); + } + if(msgProps.hasContentType()) + { + props.setContentType(Symbol.valueOf(msgProps.getContentType())); + + // Modify the content type when we are dealing with java object messages produced by the Qpid 0.x client + if(props.getContentType() == Symbol.valueOf("application/java-object-stream")) + { + props.setContentType(Symbol.valueOf("application/x-java-serialized-object")); + } + } + + props.setSubject(serverMessage.getRoutingKey()); + + if(msgProps.hasUserId()) + { + props.setUserId(new Binary(msgProps.getUserId())); + } + + sections.add(props); + + if(msgProps.getApplicationHeaders() != null) + { + sections.add(new ApplicationProperties(msgProps.getApplicationHeaders())); + } + } + return new MessageMetaData_1_0(sections, sectionEncoder); + } + + @Override + public String getType() + { + return "v0-10 to v1-0"; + } +} diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter new file mode 100644 index 0000000000..045eb72cb1 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-10-to-1-0/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter @@ -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.protocol.converter.v0_10_v1_0.MessageConverter_0_10_to_1_0 diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/build.xml b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/build.xml new file mode 100644 index 0000000000..f405eb8868 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/build.xml @@ -0,0 +1,33 @@ +<!-- + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + --> +<project name="Qpid Broker-Plugins AMQP 0.8 to 0.10 MessageConversion" default="build"> + <property name="module.depends" value="common broker broker-plugins/amqp-0-8-protocol broker-plugins/amqp-0-10-protocol" /> + <property name="module.test.depends" value="common/tests broker/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided -Sqpid-broker-plugins-amqp-0-10-protocol=provided -Sqpid-broker-plugins-amqp-0-8-protocol=provided"/> + <property name="broker-plugins-amqp-msg-conv-0-8-to-0-10.libs" value="" /> + + <property name="broker.plugin" value="true"/> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> + +</project> diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java new file mode 100644 index 0000000000..e832ef7569 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java @@ -0,0 +1,271 @@ +package org.apache.qpid.server.protocol.converter.v0_8_v0_10; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import org.apache.qpid.AMQPInvalidClassException; +import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.protocol.v0_10.MessageTransferMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageDeliveryMode; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.ReplyTo; + +public class MessageConverter_0_10_to_0_8 implements MessageConverter<MessageTransferMessage, AMQMessage> +{ + private static final int BASIC_CLASS_ID = 60; + + public static BasicContentHeaderProperties convertContentHeaderProperties(MessageTransferMessage messageTransferMessage, + VirtualHost vhost) + { + BasicContentHeaderProperties props = new BasicContentHeaderProperties(); + + Header header = messageTransferMessage.getHeader(); + DeliveryProperties deliveryProps = header.getDeliveryProperties(); + MessageProperties messageProps = header.getMessageProperties(); + + if(deliveryProps != null) + { + if(deliveryProps.hasDeliveryMode()) + { + props.setDeliveryMode((byte) (deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT + ? BasicContentHeaderProperties.PERSISTENT + : BasicContentHeaderProperties.NON_PERSISTENT)); + } + if(deliveryProps.hasExpiration()) + { + props.setExpiration(deliveryProps.getExpiration()); + } + if(deliveryProps.hasPriority()) + { + props.setPriority((byte) deliveryProps.getPriority().getValue()); + } + if(deliveryProps.hasTimestamp()) + { + props.setTimestamp(deliveryProps.getTimestamp()); + } + } + if(messageProps != null) + { + if(messageProps.hasAppId()) + { + props.setAppId(new AMQShortString(messageProps.getAppId())); + } + if(messageProps.hasContentType()) + { + props.setContentType(messageProps.getContentType()); + } + if(messageProps.hasCorrelationId()) + { + props.setCorrelationId(new AMQShortString(messageProps.getCorrelationId())); + } + if(messageProps.hasContentEncoding()) + { + props.setEncoding(messageProps.getContentEncoding()); + } + if(messageProps.hasMessageId()) + { + props.setMessageId("ID:" + messageProps.getMessageId().toString()); + } + if(messageProps.hasReplyTo()) + { + ReplyTo replyTo = messageProps.getReplyTo(); + String exchangeName = replyTo.getExchange(); + String routingKey = replyTo.getRoutingKey(); + if(exchangeName == null) + { + exchangeName = ""; + } + + Exchange exchange = vhost.getExchange(exchangeName); + String exchangeClass = exchange == null + ? ExchangeDefaults.DIRECT_EXCHANGE_CLASS + : exchange.getTypeName(); + props.setReplyTo(exchangeClass + "://" + exchangeName + "//?routingkey='" + (routingKey == null + ? "" + : routingKey + "'")); + + } + if(messageProps.hasUserId()) + { + props.setUserId(new AMQShortString(messageProps.getUserId())); + } + + if(messageProps.hasApplicationHeaders()) + { + Map<String, Object> appHeaders = new HashMap<String, Object>(messageProps.getApplicationHeaders()); + if(messageProps.getApplicationHeaders().containsKey("x-jms-type")) + { + props.setType(String.valueOf(appHeaders.remove("x-jms-type"))); + } + + FieldTable ft = new FieldTable(); + for(Map.Entry<String, Object> entry : appHeaders.entrySet()) + { + try + { + ft.put(new AMQShortString(entry.getKey()), entry.getValue()); + } + catch (AMQPInvalidClassException e) + { + // TODO + // log here, but ignore - just can;t convert + } + } + props.setHeaders(ft); + + } + } + + return props; + } + + @Override + public Class<MessageTransferMessage> getInputClass() + { + return MessageTransferMessage.class; + } + + @Override + public Class<AMQMessage> getOutputClass() + { + return AMQMessage.class; + } + + @Override + public AMQMessage convert(MessageTransferMessage message, VirtualHost vhost) + { + return new AMQMessage(convertToStoredMessage(message, vhost)); + } + + private StoredMessage<MessageMetaData> convertToStoredMessage(final MessageTransferMessage message, + VirtualHost vhost) + { + final MessageMetaData metaData = convertMetaData(message, vhost); + return new StoredMessage<org.apache.qpid.server.protocol.v0_8.MessageMetaData>() + { + @Override + public MessageMetaData getMetaData() + { + return metaData; + } + + @Override + public long getMessageNumber() + { + return message.getMessageNumber(); + } + + @Override + public void addContent(int offsetInMessage, ByteBuffer src) + { + throw new UnsupportedOperationException(); + } + + @Override + public int getContent(int offsetInMessage, ByteBuffer dst) + { + return message.getContent(dst, offsetInMessage); + } + + @Override + public ByteBuffer getContent(int offsetInMessage, int size) + { + return message.getContent(offsetInMessage, size); + } + + @Override + public StoreFuture flushToStore() + { + return StoreFuture.IMMEDIATE_FUTURE; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } + + private MessageMetaData convertMetaData(MessageTransferMessage message, VirtualHost vhost) + { + return new MessageMetaData(convertPublishBody(message), + convertContentHeaderBody(message, vhost), + 1, + message.getArrivalTime()); + } + + private ContentHeaderBody convertContentHeaderBody(MessageTransferMessage message, VirtualHost vhost) + { + BasicContentHeaderProperties props = convertContentHeaderProperties(message, vhost); + ContentHeaderBody chb = new ContentHeaderBody(props, BASIC_CLASS_ID); + chb.setBodySize(message.getSize()); + return chb; + } + + private MessagePublishInfo convertPublishBody(MessageTransferMessage message) + { + DeliveryProperties delvProps = message.getHeader().getDeliveryProperties(); + final AMQShortString exchangeName = (delvProps == null || delvProps.getExchange() == null) + ? null + : new AMQShortString(delvProps.getExchange()); + final AMQShortString routingKey = (delvProps == null || delvProps.getRoutingKey() == null) + ? null + : new AMQShortString(delvProps.getRoutingKey()); + final boolean immediate = delvProps != null && delvProps.getImmediate(); + final boolean mandatory = delvProps != null && !delvProps.getDiscardUnroutable(); + + return new MessagePublishInfo() + { + @Override + public AMQShortString getExchange() + { + return exchangeName; + } + + @Override + public void setExchange(AMQShortString exchange) + { + throw new UnsupportedOperationException(); + } + + @Override + public boolean isImmediate() + { + return immediate; + } + + @Override + public boolean isMandatory() + { + return mandatory; + } + + @Override + public AMQShortString getRoutingKey() + { + return routingKey; + } + }; + } + + @Override + public String getType() + { + return "v0-10 to v0-8"; + } +} diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_8_to_0_10.java b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_8_to_0_10.java new file mode 100644 index 0000000000..e1e8fbd9d3 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_8_to_0_10.java @@ -0,0 +1,226 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.converter.v0_8_v0_10; + +import java.net.URISyntaxException; +import java.nio.ByteBuffer; +import java.util.Map; +import java.util.UUID; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.protocol.v0_10.MessageMetaData_0_10; +import org.apache.qpid.server.protocol.v0_10.MessageTransferMessage; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.StoredMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; +import org.apache.qpid.transport.DeliveryProperties; +import org.apache.qpid.transport.Header; +import org.apache.qpid.transport.MessageDeliveryPriority; +import org.apache.qpid.transport.MessageProperties; +import org.apache.qpid.transport.ReplyTo; +import org.apache.qpid.url.AMQBindingURL; + +public class MessageConverter_0_8_to_0_10 implements MessageConverter<AMQMessage, MessageTransferMessage> +{ + @Override + public Class<AMQMessage> getInputClass() + { + return AMQMessage.class; + } + + @Override + public Class<MessageTransferMessage> getOutputClass() + { + return MessageTransferMessage.class; + } + + @Override + public MessageTransferMessage convert(AMQMessage message_0_8, VirtualHost vhost) + { + return new MessageTransferMessage(convertToStoredMessage(message_0_8), null); + } + + private StoredMessage<MessageMetaData_0_10> convertToStoredMessage(final AMQMessage message_0_8) + { + final MessageMetaData_0_10 messageMetaData_0_10 = convertMetaData(message_0_8); + return new StoredMessage<MessageMetaData_0_10>() + { + @Override + public MessageMetaData_0_10 getMetaData() + { + return messageMetaData_0_10; + } + + @Override + public long getMessageNumber() + { + return message_0_8.getMessageNumber(); + } + + @Override + public void addContent(int offsetInMessage, ByteBuffer src) + { + throw new UnsupportedOperationException(); + } + + @Override + public int getContent(int offsetInMessage, ByteBuffer dst) + { + return message_0_8.getContent(dst, offsetInMessage); + } + + @Override + public ByteBuffer getContent(int offsetInMessage, int size) + { + return message_0_8.getContent(offsetInMessage, size); + } + + @Override + public StoreFuture flushToStore() + { + return StoreFuture.IMMEDIATE_FUTURE; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + }; + } + + private MessageMetaData_0_10 convertMetaData(AMQMessage message_0_8) + { + DeliveryProperties deliveryProps = new DeliveryProperties(); + MessageProperties messageProps = new MessageProperties(); + + int size = (int) message_0_8.getSize(); + ByteBuffer body = ByteBuffer.allocate(size); + message_0_8.getContent(body, 0); + body.flip(); + + BasicContentHeaderProperties properties = + (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().getProperties(); + + final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange(); + if(exchange != null) + { + deliveryProps.setExchange(exchange.toString()); + } + + deliveryProps.setExpiration(message_0_8.getExpiration()); + deliveryProps.setImmediate(message_0_8.isImmediate()); + deliveryProps.setPriority(MessageDeliveryPriority.get(properties.getPriority())); + deliveryProps.setRoutingKey(message_0_8.getRoutingKey()); + deliveryProps.setTimestamp(properties.getTimestamp()); + + messageProps.setContentEncoding(properties.getEncodingAsString()); + messageProps.setContentLength(size); + if(properties.getAppId() != null) + { + messageProps.setAppId(properties.getAppId().getBytes()); + } + messageProps.setContentType(properties.getContentTypeAsString()); + if(properties.getCorrelationId() != null) + { + messageProps.setCorrelationId(properties.getCorrelationId().getBytes()); + } + + if(properties.getReplyTo() != null && properties.getReplyTo().length() != 0) + { + String origReplyToString = properties.getReplyTo().asString(); + ReplyTo replyTo = new ReplyTo(); + // if the string looks like a binding URL, then attempt to parse it... + try + { + AMQBindingURL burl = new AMQBindingURL(origReplyToString); + AMQShortString routingKey = burl.getRoutingKey(); + if(routingKey != null) + { + replyTo.setRoutingKey(routingKey.asString()); + } + + AMQShortString exchangeName = burl.getExchangeName(); + if(exchangeName != null) + { + replyTo.setExchange(exchangeName.asString()); + } + } + catch (URISyntaxException e) + { + replyTo.setRoutingKey(origReplyToString); + } + messageProps.setReplyTo(replyTo); + + } + + if(properties.getMessageId() != null) + { + try + { + String messageIdAsString = properties.getMessageIdAsString(); + if(messageIdAsString.startsWith("ID:")) + { + messageIdAsString = messageIdAsString.substring(3); + } + UUID uuid = UUID.fromString(messageIdAsString); + messageProps.setMessageId(uuid); + } + catch(IllegalArgumentException e) + { + // ignore - can't parse + } + } + + + + if(properties.getUserId() != null) + { + messageProps.setUserId(properties.getUserId().getBytes()); + } + + FieldTable fieldTable = properties.getHeaders(); + + Map<String, Object> appHeaders = FieldTable.convertToMap(fieldTable); + + if(properties.getType() != null) + { + appHeaders.put("x-jms-type", properties.getTypeAsString()); + } + + + messageProps.setApplicationHeaders(appHeaders); + + Header header = new Header(deliveryProps, messageProps, null); + + + return new MessageMetaData_0_10(header, size, message_0_8.getArrivalTime()); + } + + @Override + public String getType() + { + return "v0-8 to v0-10"; + } +} diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter new file mode 100644 index 0000000000..5aeef786ae --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter @@ -0,0 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.protocol.converter.v0_8_v0_10.MessageConverter_0_8_to_0_10 +org.apache.qpid.server.protocol.converter.v0_8_v0_10.MessageConverter_0_10_to_0_8 diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/build.xml b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/build.xml new file mode 100644 index 0000000000..897da14d1f --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/build.xml @@ -0,0 +1,33 @@ +<!-- + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + --> +<project name="Qpid Broker-Plugins AMQP 0.8 to 1.0 MessageConversion" default="build"> + <property name="module.depends" value="common broker amqp-1-0-common broker-plugins/amqp-0-8-protocol broker-plugins/amqp-1-0-protocol" /> + <property name="module.test.depends" value="common/tests broker/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided -Sqpid-amqp-1-0-common=provided -Sqpid-broker-plugins-amqp-1-0-protocol=provided -Sqpid-broker-plugins-amqp-0-8-protocol=provided"/> + <property name="broker-plugins-amqp-msg-conv-0-8-to-1-0.libs" value="" /> + + <property name="broker.plugin" value="true"/> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> + +</project> diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/MessageConverter_0_8_to_1_0.java b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/MessageConverter_0_8_to_1_0.java new file mode 100644 index 0000000000..0d9d59ff56 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v1_0/MessageConverter_0_8_to_1_0.java @@ -0,0 +1,125 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol.converter.v0_8_v1_0; + +import java.util.ArrayList; +import java.util.List; +import org.apache.qpid.amqp_1_0.messaging.SectionEncoder; +import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.type.Section; +import org.apache.qpid.amqp_1_0.type.Symbol; +import org.apache.qpid.amqp_1_0.type.UnsignedByte; +import org.apache.qpid.amqp_1_0.type.UnsignedInteger; +import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties; +import org.apache.qpid.amqp_1_0.type.messaging.Header; +import org.apache.qpid.amqp_1_0.type.messaging.Properties; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v1_0.MessageConverter_to_1_0; +import org.apache.qpid.server.protocol.v1_0.MessageMetaData_1_0; + +public class MessageConverter_0_8_to_1_0 extends MessageConverter_to_1_0<AMQMessage> +{ + @Override + public Class<AMQMessage> getInputClass() + { + return AMQMessage.class; + } + + protected MessageMetaData_1_0 convertMetaData(final AMQMessage serverMessage, SectionEncoder sectionEncoder) + { + + List<Section> sections = new ArrayList<Section>(3); + + Header header = new Header(); + + header.setDurable(serverMessage.isPersistent()); + + BasicContentHeaderProperties contentHeader = + (BasicContentHeaderProperties) serverMessage.getContentHeaderBody().getProperties(); + + header.setPriority(UnsignedByte.valueOf(contentHeader.getPriority())); + final long expiration = serverMessage.getExpiration(); + final long arrivalTime = serverMessage.getArrivalTime(); + + if(expiration > arrivalTime) + { + header.setTtl(UnsignedInteger.valueOf(expiration - arrivalTime)); + } + sections.add(header); + + + Properties props = new Properties(); + + /* + TODO: The following properties are not currently set: + + creationTime + groupId + groupSequence + replyToGroupId + to + */ + + props.setContentEncoding(Symbol.valueOf(contentHeader.getEncodingAsString())); + + props.setContentType(Symbol.valueOf(contentHeader.getContentTypeAsString())); + + // Modify the content type when we are dealing with java object messages produced by the Qpid 0.x client + if(props.getContentType() == Symbol.valueOf("application/java-object-stream")) + { + props.setContentType(Symbol.valueOf("application/x-java-serialized-object")); + } + + final AMQShortString correlationId = contentHeader.getCorrelationId(); + if(correlationId != null) + { + props.setCorrelationId(new Binary(correlationId.getBytes())); + } + + final AMQShortString messageId = contentHeader.getMessageId(); + if(messageId != null) + { + props.setMessageId(new Binary(messageId.getBytes())); + } + props.setReplyTo(String.valueOf(contentHeader.getReplyTo())); + + props.setSubject(serverMessage.getRoutingKey()); + if(contentHeader.getUserId() != null) + { + props.setUserId(new Binary(contentHeader.getUserId().getBytes())); + } + + sections.add(props); + + sections.add(new ApplicationProperties(FieldTable.convertToMap(contentHeader.getHeaders()))); + + return new MessageMetaData_1_0(sections, sectionEncoder); + } + + @Override + public String getType() + { + return "v0-8 to v1-0"; + } +} diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter new file mode 100644 index 0000000000..cf4643f2b8 --- /dev/null +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-1-0/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageConverter @@ -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.protocol.converter.v0_8_v1_0.MessageConverter_0_8_to_1_0 diff --git a/qpid/java/broker-plugins/derby-store/build.xml b/qpid/java/broker-plugins/derby-store/build.xml index e93b81aad7..be3d72f059 100644 --- a/qpid/java/broker-plugins/derby-store/build.xml +++ b/qpid/java/broker-plugins/derby-store/build.xml @@ -22,6 +22,7 @@ <property name="module.genpom" value="true"/> <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/> + <property name="broker-plugins-derby-store.libs" value="" /> <property name="broker.plugin" value="true"/> diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java index ac310d02c9..bc8d157346 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java +++ b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java @@ -132,7 +132,7 @@ public class DerbyMessageStore extends AbstractJDBCMessageStore implements Messa _driverClass = (Class<Driver>) Class.forName(SQL_DRIVER_NAME); String defaultPath = System.getProperty("QPID_WORK") + File.separator + "derbyDB"; - String databasePath = (String) virtualHost.getAttribute(VirtualHost.STORE_PATH); + String databasePath = isConfigStoreOnly() ? (String) virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH) : (String) virtualHost.getAttribute(VirtualHost.STORE_PATH); if(databasePath == null) { databasePath = defaultPath; diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java index 1b111ad65e..47a451ccf6 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java +++ b/qpid/java/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java @@ -24,10 +24,12 @@ import java.util.Collections; import java.util.Map; import org.apache.commons.configuration.Configuration; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; import org.apache.qpid.server.plugin.MessageStoreFactory; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; -public class DerbyMessageStoreFactory implements MessageStoreFactory +public class DerbyMessageStoreFactory implements MessageStoreFactory, DurableConfigurationStoreFactory { @Override @@ -37,6 +39,12 @@ public class DerbyMessageStoreFactory implements MessageStoreFactory } @Override + public DurableConfigurationStore createDurableConfigurationStore() + { + return new DerbyMessageStore(); + } + + @Override public MessageStore createMessageStore() { return new DerbyMessageStore(); @@ -52,12 +60,25 @@ public class DerbyMessageStoreFactory implements MessageStoreFactory @Override public void validateAttributes(Map<String, Object> attributes) { - Object storePath = attributes.get(VirtualHost.STORE_PATH); - if(!(storePath instanceof String)) + if(getType().equals(attributes.get(VirtualHost.STORE_TYPE))) + { + Object storePath = attributes.get(VirtualHost.STORE_PATH); + if(!(storePath instanceof String)) + { + throw new IllegalArgumentException("Attribute '"+ VirtualHost.STORE_PATH + +"' is required and must be of type String."); + + } + } + if(getType().equals(attributes.get(VirtualHost.CONFIG_STORE_TYPE))) { - throw new IllegalArgumentException("Attribute '"+ VirtualHost.STORE_PATH - +"' is required and must be of type String."); + Object storePath = attributes.get(VirtualHost.CONFIG_STORE_PATH); + if(!(storePath instanceof String)) + { + throw new IllegalArgumentException("Attribute '"+ VirtualHost.CONFIG_STORE_PATH + +"' is required and must be of type String."); + } } } diff --git a/qpid/java/broker-plugins/derby-store/src/main/resources/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/broker-plugins/derby-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory index 88ca1fed5e..88ca1fed5e 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/resources/services/org.apache.qpid.server.plugin.MessageStoreFactory +++ b/qpid/java/broker-plugins/derby-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory diff --git a/qpid/java/broker-plugins/derby-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/broker-plugins/derby-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory new file mode 100644 index 0000000000..88ca1fed5e --- /dev/null +++ b/qpid/java/broker-plugins/derby-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory @@ -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.derby.DerbyMessageStoreFactory diff --git a/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreConfigurationTest.java b/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreConfigurationTest.java index ffb6ac479a..4a1a3251e3 100644 --- a/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreConfigurationTest.java +++ b/qpid/java/broker-plugins/derby-store/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreConfigurationTest.java @@ -28,18 +28,17 @@ public class DerbyMessageStoreConfigurationTest extends AbstractDurableConfigura private DerbyMessageStore _derbyMessageStore; @Override - protected void onReopenStore() - { - _derbyMessageStore = null; - } - - @Override protected DerbyMessageStore createMessageStore() throws Exception { createStoreIfNecessary(); return _derbyMessageStore; } + @Override + protected void closeMessageStore() throws Exception + { + closeStoreIfNecessary(); + } private void createStoreIfNecessary() { @@ -55,4 +54,19 @@ public class DerbyMessageStoreConfigurationTest extends AbstractDurableConfigura createStoreIfNecessary(); return _derbyMessageStore; } + + @Override + protected void closeConfigStore() throws Exception + { + closeStoreIfNecessary(); + } + + private void closeStoreIfNecessary() throws Exception + { + if (_derbyMessageStore != null) + { + _derbyMessageStore.close(); + _derbyMessageStore = null; + } + } } diff --git a/qpid/java/broker-plugins/jdbc-provider-bone/build.xml b/qpid/java/broker-plugins/jdbc-provider-bone/build.xml index df21d3ed38..eb3f40734f 100644 --- a/qpid/java/broker-plugins/jdbc-provider-bone/build.xml +++ b/qpid/java/broker-plugins/jdbc-provider-bone/build.xml @@ -21,6 +21,8 @@ <property name="module.genpom" value="true"/> <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/> + <property name="broker.plugin" value="true"/> + <import file="../../module.xml" /> <condition property="download.bonecp.jar"> diff --git a/qpid/java/broker-plugins/jdbc-store/build.xml b/qpid/java/broker-plugins/jdbc-store/build.xml index de6ec59845..9b6aeb32d6 100644 --- a/qpid/java/broker-plugins/jdbc-store/build.xml +++ b/qpid/java/broker-plugins/jdbc-store/build.xml @@ -22,6 +22,7 @@ <property name="module.genpom" value="true"/> <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/> + <property name="broker-plugins-jdbc-store.libs" value="" /> <property name="broker.plugin" value="true"/> diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java index f8d93536bb..6fdfa40561 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStore.java @@ -51,6 +51,7 @@ public class JDBCMessageStore extends AbstractJDBCMessageStore implements Messag public static final String TYPE = "JDBC"; public static final String CONNECTION_URL = "connectionURL"; + public static final String CONFIG_CONNECTION_URL = "configConnectionURL"; protected String _connectionURL; private ConnectionProvider _connectionProvider; @@ -280,11 +281,20 @@ public class JDBCMessageStore extends AbstractJDBCMessageStore implements Messag throws ClassNotFoundException, SQLException { + String connectionURL; + if(!isConfigStoreOnly()) + { + connectionURL = virtualHost.getAttribute(CONNECTION_URL) == null + ? String.valueOf(virtualHost.getAttribute(VirtualHost.STORE_PATH)) + : String.valueOf(virtualHost.getAttribute(CONNECTION_URL)); + } + else + { + connectionURL = virtualHost.getAttribute(CONFIG_CONNECTION_URL) == null + ? String.valueOf(virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH)) + : String.valueOf(virtualHost.getAttribute(CONFIG_CONNECTION_URL)); - String connectionURL = virtualHost.getAttribute(CONNECTION_URL) == null - ? String.valueOf(virtualHost.getAttribute(VirtualHost.STORE_PATH)) - : String.valueOf(virtualHost.getAttribute(CONNECTION_URL)); - + } JDBCDetails details = null; String[] components = connectionURL.split(":",3); diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java index 82d2275156..1144eaaf18 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/store/jdbc/JDBCMessageStoreFactory.java @@ -24,10 +24,12 @@ import java.util.HashMap; import java.util.Map; import org.apache.commons.configuration.Configuration; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; import org.apache.qpid.server.plugin.MessageStoreFactory; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; -public class JDBCMessageStoreFactory implements MessageStoreFactory +public class JDBCMessageStoreFactory implements MessageStoreFactory, DurableConfigurationStoreFactory { @Override @@ -43,6 +45,12 @@ public class JDBCMessageStoreFactory implements MessageStoreFactory } @Override + public DurableConfigurationStore createDurableConfigurationStore() + { + return new JDBCMessageStore(); + } + + @Override public Map<String, Object> convertStoreConfiguration(Configuration storeConfiguration) { Map<String,Object> convertedMap = new HashMap<String,Object>(); @@ -67,15 +75,32 @@ public class JDBCMessageStoreFactory implements MessageStoreFactory @Override public void validateAttributes(Map<String, Object> attributes) { - Object connectionURL = attributes.get(JDBCMessageStore.CONNECTION_URL); - if(!(connectionURL instanceof String)) + if(getType().equals(attributes.get(VirtualHost.STORE_TYPE))) + { + Object connectionURL = attributes.get(JDBCMessageStore.CONNECTION_URL); + if(!(connectionURL instanceof String)) + { + Object storePath = attributes.get(VirtualHost.STORE_PATH); + if(!(storePath instanceof String)) + { + throw new IllegalArgumentException("Attribute '"+ JDBCMessageStore.CONNECTION_URL + +"' is required and must be of type String."); + + } + } + } + if(getType().equals(attributes.get(VirtualHost.CONFIG_STORE_TYPE))) { - Object storePath = attributes.get(VirtualHost.STORE_PATH); - if(!(storePath instanceof String)) + Object connectionURL = attributes.get(JDBCMessageStore.CONFIG_CONNECTION_URL); + if(!(connectionURL instanceof String)) { - throw new IllegalArgumentException("Attribute '"+ JDBCMessageStore.CONNECTION_URL - +"' is required and must be of type String."); + Object storePath = attributes.get(VirtualHost.CONFIG_STORE_PATH); + if(!(storePath instanceof String)) + { + throw new IllegalArgumentException("Attribute '"+ JDBCMessageStore.CONFIG_CONNECTION_URL + +"' is required and must be of type String."); + } } } } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/virtualhost/store/memory/add.html b/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/pool/none/add.html index e69de29bb2..e69de29bb2 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/virtualhost/store/memory/add.html +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/pool/none/add.html diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/resources/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory index a77458f27d..a77458f27d 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/resources/services/org.apache.qpid.server.plugin.MessageStoreFactory +++ b/qpid/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory new file mode 100644 index 0000000000..a77458f27d --- /dev/null +++ b/qpid/java/broker-plugins/jdbc-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory @@ -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.jdbc.JDBCMessageStoreFactory diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java index d87a1755da..c6623aefcf 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -20,9 +20,9 @@ */ package org.apache.qpid.server.management.plugin; -import java.io.File; import java.lang.reflect.Type; import java.net.SocketAddress; +import java.security.GeneralSecurityException; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; @@ -31,6 +31,7 @@ import java.util.HashSet; import java.util.Map; import java.util.UUID; +import javax.net.ssl.SSLContext; import org.apache.log4j.Logger; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -39,11 +40,15 @@ import org.apache.qpid.server.management.plugin.filter.ForbiddingAuthorisationFi import org.apache.qpid.server.management.plugin.filter.RedirectingAuthorisationFilter; import org.apache.qpid.server.management.plugin.servlet.DefinedFileServlet; import org.apache.qpid.server.management.plugin.servlet.FileServlet; +import org.apache.qpid.server.management.plugin.servlet.LogFileServlet; import org.apache.qpid.server.management.plugin.servlet.rest.HelperServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.LogFileListingServlet; import org.apache.qpid.server.management.plugin.servlet.rest.LogRecordsServlet; import org.apache.qpid.server.management.plugin.servlet.rest.LogoutServlet; import org.apache.qpid.server.management.plugin.servlet.rest.MessageContentServlet; import org.apache.qpid.server.management.plugin.servlet.rest.MessageServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.PreferencesServlet; +import org.apache.qpid.server.management.plugin.servlet.rest.UserPreferencesServlet; import org.apache.qpid.server.management.plugin.servlet.rest.RestServlet; import org.apache.qpid.server.management.plugin.servlet.rest.SaslServlet; import org.apache.qpid.server.management.plugin.servlet.rest.StructureServlet; @@ -60,6 +65,7 @@ import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.Session; @@ -70,7 +76,6 @@ import org.apache.qpid.server.model.User; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.adapter.AbstractPluginAdapter; import org.apache.qpid.server.plugin.PluginFactory; -import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.util.MapValueConverter; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.DispatcherType; @@ -238,13 +243,17 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem { throw new IllegalConfigurationException("Key store is not configured. Cannot start management on HTTPS port without keystore"); } - String keyStorePath = (String)keyStore.getAttribute(KeyStore.PATH); - String keyStorePassword = keyStore.getPassword(); - SslContextFactory factory = new SslContextFactory(); - factory.setKeyStorePath(keyStorePath); - factory.setKeyStorePassword(keyStorePassword); - + try + { + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyStore.getKeyManagers(), null, null); + factory.setSslContext(sslContext); + } + catch (GeneralSecurityException e) + { + throw new RuntimeException("Cannot configure port " + port.getName() + " for transport " + Transport.SSL, e); + } connector = new SslSocketConnector(factory); } else @@ -288,7 +297,10 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem addRestServlet(root, "keystore", KeyStore.class); addRestServlet(root, "truststore", TrustStore.class); addRestServlet(root, "plugin", Plugin.class); + addRestServlet(root, "preferencesprovider", AuthenticationProvider.class, PreferencesProvider.class); + root.addServlet(new ServletHolder(new UserPreferencesServlet()), "/rest/userpreferences/*"); + root.addServlet(new ServletHolder(new PreferencesServlet()), "/rest/preferences"); root.addServlet(new ServletHolder(new StructureServlet()), "/rest/structure"); root.addServlet(new ServletHolder(new MessageServlet()), "/rest/message/*"); root.addServlet(new ServletHolder(new MessageContentServlet()), "/rest/message-content/*"); @@ -312,6 +324,15 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.txt"); root.addServlet(new ServletHolder(FileServlet.INSTANCE), "*.xsl"); root.addServlet(new ServletHolder(new HelperServlet()), "/rest/helper"); + root.addServlet(new ServletHolder(new LogFileListingServlet()), "/rest/logfiles"); + root.addServlet(new ServletHolder(new LogFileServlet()), "/rest/logfile"); + + String[] timeZoneFiles = {"africa", "antarctica", "asia", "australasia", "backward", + "etcetera", "europe", "northamerica", "pacificnew", "southamerica"}; + for (String timeZoneFile : timeZoneFiles) + { + root.addServlet(new ServletHolder(FileServlet.INSTANCE), "/dojo/dojox/date/zoneinfo/" + timeZoneFile); + } final SessionManager sessionManager = root.getSessionHandler().getSessionManager(); sessionManager.setSessionCookie(JSESSIONID_COOKIE_PREFIX + lastPort); @@ -407,9 +428,9 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem } @Override - public SubjectCreator getSubjectCreator(SocketAddress localAddress) + public AuthenticationProvider getAuthenticationProvider(SocketAddress localAddress) { - return getBroker().getSubjectCreator(localAddress); + return getBroker().getAuthenticationProvider(localAddress); } @Override diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java index 56919e2e6b..7d89daa427 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementConfiguration.java @@ -22,7 +22,7 @@ package org.apache.qpid.server.management.plugin; import java.net.SocketAddress; -import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.model.AuthenticationProvider; public interface HttpManagementConfiguration { @@ -34,5 +34,5 @@ public interface HttpManagementConfiguration boolean isHttpBasicAuthenticationEnabled(); - SubjectCreator getSubjectCreator(SocketAddress localAddress); + AuthenticationProvider getAuthenticationProvider(SocketAddress localAddress); } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java index 4c6e5bf63e..990ff1c53b 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java @@ -168,7 +168,7 @@ public class HttpManagementUtil { Subject subject = null; SocketAddress localAddress = getSocketAddress(request); - SubjectCreator subjectCreator = managementConfig.getSubjectCreator(localAddress); + SubjectCreator subjectCreator = managementConfig.getAuthenticationProvider(localAddress).getSubjectCreator(); String remoteUser = request.getRemoteUser(); if (remoteUser != null || subjectCreator.isAnonymousAuthenticationAllowed()) diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/log/LogFileDetails.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/log/LogFileDetails.java new file mode 100644 index 0000000000..09dabd0e73 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/log/LogFileDetails.java @@ -0,0 +1,78 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.qpid.server.management.plugin.log; + +import java.io.File; + +public class LogFileDetails +{ + private String _name; + private File _location; + private String _mimeType; + private long _size; + private long _lastModified; + private String _appenderName; + + public LogFileDetails(String name, String appenderName, File location, String mimeType, long fileSize, long lastUpdateTime) + { + super(); + _name = name; + _location = location; + _mimeType = mimeType; + _size = fileSize; + _lastModified = lastUpdateTime; + _appenderName = appenderName; + } + + public String getName() + { + return _name; + } + + public File getLocation() + { + return _location; + } + + public String getMimeType() + { + return _mimeType; + } + + public long getSize() + { + return _size; + } + + public long getLastModified() + { + return _lastModified; + } + + public String getAppenderName() + { + return _appenderName; + } + + @Override + public String toString() + { + return "LogFileDetails [name=" + _name + "]"; + } + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/log/LogFileHelper.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/log/LogFileHelper.java new file mode 100644 index 0000000000..03d98d020b --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/log/LogFileHelper.java @@ -0,0 +1,228 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.qpid.server.management.plugin.log; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.OutputStream; +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.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import org.apache.log4j.Appender; +import org.apache.log4j.FileAppender; +import org.apache.log4j.QpidCompositeRollingAppender; + +public class LogFileHelper +{ + public static final String GZIP_MIME_TYPE = "application/x-gzip"; + public static final String TEXT_MIME_TYPE = "text/plain"; + public static final String ZIP_MIME_TYPE = "application/zip"; + public static final String GZIP_EXTENSION = ".gz"; + private static final int BUFFER_LENGTH = 1024 * 4; + private Collection<Appender> _appenders; + + public LogFileHelper(Collection<Appender> appenders) + { + super(); + _appenders = appenders; + } + + public List<LogFileDetails> findLogFileDetails(String[] requestedFiles) + { + List<LogFileDetails> logFiles = new ArrayList<LogFileDetails>(); + Map<String, List<LogFileDetails>> cache = new HashMap<String, List<LogFileDetails>>(); + for (int i = 0; i < requestedFiles.length; i++) + { + String[] paths = requestedFiles[i].split("/"); + if (paths.length != 2) + { + throw new IllegalArgumentException("Log file name '" + requestedFiles[i] + "' does not include an appender name"); + } + + String appenderName = paths[0]; + String fileName = paths[1]; + + List<LogFileDetails> appenderFiles = cache.get(appenderName); + if (appenderFiles == null) + { + Appender fileAppender = null; + for (Appender appender : _appenders) + { + if (appenderName.equals(appender.getName())) + { + fileAppender = appender; + break; + } + } + if (fileAppender == null) + { + continue; + } + appenderFiles = getAppenderFiles(fileAppender, true); + if (appenderFiles == null) + { + continue; + } + cache.put(appenderName, appenderFiles); + } + for (LogFileDetails logFileDetails : appenderFiles) + { + if (logFileDetails.getName().equals(fileName)) + { + logFiles.add(logFileDetails); + } + } + } + return logFiles; + } + + public List<LogFileDetails> getLogFileDetails(boolean includeLogFileLocation) + { + List<LogFileDetails> results = new ArrayList<LogFileDetails>(); + for (Appender appender : _appenders) + { + List<LogFileDetails> appenderFiles = getAppenderFiles(appender, includeLogFileLocation); + if (appenderFiles != null) + { + results.addAll(appenderFiles); + } + } + return results; + } + + public void writeLogFiles(List<LogFileDetails> logFiles, OutputStream os) throws IOException + { + ZipOutputStream out = new ZipOutputStream(os); + try + { + addLogFileEntries(logFiles, out); + } + finally + { + out.close(); + } + } + + public void writeLogFile(File file, OutputStream os) throws IOException + { + FileInputStream fis = new FileInputStream(file); + try + { + byte[] bytes = new byte[BUFFER_LENGTH]; + int length = 1; + while ((length = fis.read(bytes)) != -1) + { + os.write(bytes, 0, length); + } + } + finally + { + fis.close(); + } + } + + private List<LogFileDetails> getAppenderFiles(Appender appender, boolean includeLogFileLocation) + { + if (appender instanceof QpidCompositeRollingAppender) + { + return listAppenderFiles((QpidCompositeRollingAppender) appender, includeLogFileLocation); + } + else if (appender instanceof FileAppender) + { + return listAppenderFiles((FileAppender) appender, includeLogFileLocation); + } + return null; + } + + private List<LogFileDetails> listAppenderFiles(FileAppender appender, boolean includeLogFileLocation) + { + String appenderFilePath = appender.getFile(); + File appenderFile = new File(appenderFilePath); + if (appenderFile.exists()) + { + return listLogFiles(appenderFile.getParentFile(), appenderFile.getName(), appender.getName(), "", includeLogFileLocation); + } + return Collections.emptyList(); + } + + private List<LogFileDetails> listAppenderFiles(QpidCompositeRollingAppender appender, boolean includeLogFileLocation) + { + List<LogFileDetails> files = listAppenderFiles((FileAppender) appender, includeLogFileLocation); + String appenderFilePath = appender.getFile(); + File appenderFile = new File(appenderFilePath); + File backupFolder = new File(appender.getBackupFilesToPath()); + if (backupFolder.exists()) + { + String backFolderName = backupFolder.getName() + "/"; + List<LogFileDetails> backedUpFiles = listLogFiles(backupFolder, appenderFile.getName(), appender.getName(), + backFolderName, includeLogFileLocation); + files.addAll(backedUpFiles); + } + return files; + } + + private List<LogFileDetails> listLogFiles(File parent, String baseFileName, String appenderName, String relativePath, + boolean includeLogFileLocation) + { + List<LogFileDetails> files = new ArrayList<LogFileDetails>(); + for (File file : parent.listFiles()) + { + String name = file.getName(); + if (name.startsWith(baseFileName)) + { + files.add(new LogFileDetails(name, appenderName, includeLogFileLocation ? file : null, getMimeType(name), file.length(), + file.lastModified())); + } + } + return files; + } + + private String getMimeType(String fileName) + { + if (fileName.endsWith(GZIP_EXTENSION)) + { + return GZIP_MIME_TYPE; + } + return TEXT_MIME_TYPE; + } + + private void addLogFileEntries(List<LogFileDetails> files, ZipOutputStream out) throws IOException + { + for (LogFileDetails logFileDetails : files) + { + File file = logFileDetails.getLocation(); + if (file.exists()) + { + ZipEntry entry = new ZipEntry(logFileDetails.getAppenderName() + "/" + logFileDetails.getName()); + entry.setSize(file.length()); + out.putNextEntry(entry); + writeLogFile(file, out); + out.closeEntry(); + } + out.flush(); + } + } + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/LogFileServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/LogFileServlet.java new file mode 100644 index 0000000000..1fa03dc3dc --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/LogFileServlet.java @@ -0,0 +1,105 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.qpid.server.management.plugin.servlet; + +import java.io.IOException; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.LogManager; +import org.apache.qpid.server.management.plugin.log.LogFileDetails; +import org.apache.qpid.server.management.plugin.log.LogFileHelper; +import org.apache.qpid.server.management.plugin.servlet.rest.AbstractServlet; + +public class LogFileServlet extends AbstractServlet +{ + private static final long serialVersionUID = 1L; + + public static final String LOGS_FILE_NAME = "qpid-logs-%s.zip"; + public static final String DATE_FORMAT = "yyyy-MM-dd-mmHHss"; + + @SuppressWarnings("unchecked") + private LogFileHelper _helper = new LogFileHelper(Collections.list(LogManager.getRootLogger().getAllAppenders())); + + @Override + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 0); + + if (!getBroker().getSecurityManager().authoriseLogsAccess()) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Log files download is denied"); + return; + } + + String[] requestedFiles = request.getParameterValues("l"); + + if (requestedFiles == null || requestedFiles.length == 0) + { + response.setStatus(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + List<LogFileDetails> logFiles = null; + + try + { + logFiles = _helper.findLogFileDetails(requestedFiles); + } + catch(IllegalArgumentException e) + { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + if (logFiles.size() == 0) + { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + String fileName = String.format(LOGS_FILE_NAME, new SimpleDateFormat(DATE_FORMAT).format(new Date())); + response.setStatus(HttpServletResponse.SC_OK); + response.setHeader("Content-Disposition", "attachment;filename=" + fileName); + response.setContentType(LogFileHelper.ZIP_MIME_TYPE); + + OutputStream os = response.getOutputStream(); + try + { + _helper.writeLogFiles(logFiles, os); + } + finally + { + if (os != null) + { + os.close(); + } + } + } + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java index 9614ded3d8..c0f4b55f64 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.management.plugin.servlet.rest; import java.io.IOException; +import java.io.PrintWriter; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; @@ -40,6 +41,10 @@ import org.apache.qpid.server.management.plugin.HttpManagementConfiguration; import org.apache.qpid.server.management.plugin.HttpManagementUtil; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.security.SecurityManager; +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; public abstract class AbstractServlet extends HttpServlet { @@ -219,14 +224,7 @@ public abstract class AbstractServlet extends HttpServlet } finally { - try - { - SecurityManager.setThreadSubject(null); - } - finally - { - AMQShortString.clearLocalCache(); - } + SecurityManager.setThreadSubject(null); } } @@ -261,4 +259,20 @@ public abstract class AbstractServlet extends HttpServlet throw new RuntimeException("Failed to send error response code " + errorCode, e); } } + + protected void sendJsonResponse(Object object, HttpServletResponse response) throws IOException, + JsonGenerationException, JsonMappingException + { + response.setStatus(HttpServletResponse.SC_OK); + + response.setHeader("Cache-Control","no-cache"); + response.setHeader("Pragma","no-cache"); + response.setDateHeader ("Expires", 0); + response.setContentType("application/json"); + + final PrintWriter writer = response.getWriter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + mapper.writeValue(writer, object); + } } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java index 75e5bd9842..9ba36bb5c2 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/HelperServlet.java @@ -41,6 +41,8 @@ import org.codehaus.jackson.map.SerializationConfig; public class HelperServlet extends AbstractServlet { + private static final long serialVersionUID = 1L; + private static final String PARAM_ACTION = "action"; private Map<String, Action> _actions; @@ -55,6 +57,8 @@ public class HelperServlet extends AbstractServlet new ListAuthenticationProviderAttributes(), new ListBrokerAttribute(Broker.SUPPORTED_VIRTUALHOST_STORE_TYPES, "ListMessageStoreTypes"), new ListBrokerAttribute(Broker.SUPPORTED_VIRTUALHOST_TYPES, "ListVirtualHostTypes"), + new ListBrokerAttribute(Broker.SUPPORTED_PREFERENCES_PROVIDERS_TYPES, "ListPreferencesProvidersTypes"), + new ListBrokerAttribute(Broker.PRODUCT_VERSION, "version"), new ListGroupProviderAttributes(), new ListAccessControlProviderAttributes(), new PluginClassProviderAction() diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogFileListingServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogFileListingServlet.java new file mode 100644 index 0000000000..b6face18e3 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogFileListingServlet.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collections; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.LogManager; +import org.apache.qpid.server.management.plugin.log.LogFileDetails; +import org.apache.qpid.server.management.plugin.log.LogFileHelper; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; + +public class LogFileListingServlet extends AbstractServlet +{ + private static final long serialVersionUID = 1L; + + @SuppressWarnings("unchecked") + private LogFileHelper _helper = new LogFileHelper(Collections.list(LogManager.getRootLogger().getAllAppenders())); + + @Override + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + response.setHeader("Cache-Control", "no-cache"); + response.setHeader("Pragma", "no-cache"); + response.setDateHeader("Expires", 0); + + if (!getBroker().getSecurityManager().authoriseLogsAccess()) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Log files download is denied"); + return; + } + + List<LogFileDetails> logFiles = _helper.getLogFileDetails(false); + response.setContentType("application/json"); + response.setStatus(HttpServletResponse.SC_OK); + + final PrintWriter writer = response.getWriter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + mapper.writeValue(writer, logFiles); + + response.setStatus(HttpServletResponse.SC_OK); + } + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java index f2cf5d7734..35523ddf0f 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/LogRecordsServlet.java @@ -31,6 +31,10 @@ import org.codehaus.jackson.map.SerializationConfig; public class LogRecordsServlet extends AbstractServlet { + private static final long serialVersionUID = 2L; + + public static final String PARAM_LAST_LOG_ID = "lastLogId"; + public LogRecordsServlet() { super(); @@ -46,12 +50,31 @@ public class LogRecordsServlet extends AbstractServlet response.setHeader("Pragma","no-cache"); response.setDateHeader ("Expires", 0); + if (!getBroker().getSecurityManager().authoriseLogsAccess()) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Broker logs access is denied"); + return; + } + + long lastLogId = 0; + try + { + lastLogId = Long.parseLong(request.getParameter(PARAM_LAST_LOG_ID)); + } + catch(Exception e) + { + // ignore null and incorrect parameter values + } + List<Map<String,Object>> logRecords = new ArrayList<Map<String, Object>>(); LogRecorder logRecorder = getBroker().getLogRecorder(); for(LogRecorder.Record record : logRecorder) { - logRecords.add(logRecordToObject(record)); + if (record.getId() > lastLogId) + { + logRecords.add(logRecordToObject(record)); + } } final PrintWriter writer = response.getWriter(); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java index 49e0c2b1bf..83208516c7 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java @@ -80,6 +80,7 @@ public class MessageServlet extends AbstractServlet response.setHeader("Cache-Control","no-cache"); response.setHeader("Pragma","no-cache"); response.setDateHeader ("Expires", 0); + response.setContentType("application/json"); final PrintWriter writer = response.getWriter(); ObjectMapper mapper = new ObjectMapper(); @@ -352,20 +353,32 @@ public class MessageServlet extends AbstractServlet if(messageHeader != null) { addIfPresent(object, "messageId", messageHeader.getMessageId()); - addIfPresent(object, "expirationTime", messageHeader.getExpiration()); + addIfPresentAndNotZero(object, "expirationTime", messageHeader.getExpiration()); addIfPresent(object, "applicationId", messageHeader.getAppId()); addIfPresent(object, "correlationId", messageHeader.getCorrelationId()); addIfPresent(object, "encoding", messageHeader.getEncoding()); addIfPresent(object, "mimeType", messageHeader.getMimeType()); addIfPresent(object, "priority", messageHeader.getPriority()); addIfPresent(object, "replyTo", messageHeader.getReplyTo()); - addIfPresent(object, "timestamp", messageHeader.getTimestamp()); + addIfPresentAndNotZero(object, "timestamp", messageHeader.getTimestamp()); addIfPresent(object, "type", messageHeader.getType()); addIfPresent(object, "userId", messageHeader.getUserId()); } } + private void addIfPresentAndNotZero(Map<String, Object> object, String name, Object property) + { + if(property instanceof Number) + { + Number value = (Number)property; + if (value.longValue() != 0) + { + object.put(name, property); + } + } + } + private void addIfPresent(Map<String, Object> object, String name, Object property) { if(property != null) diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java new file mode 100644 index 0000000000..bf2a88a2c1 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/PreferencesServlet.java @@ -0,0 +1,137 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.IOException; +import java.net.SocketAddress; +import java.security.Principal; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; + +import javax.security.auth.Subject; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.server.management.plugin.HttpManagementUtil; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; +import org.codehaus.jackson.map.ObjectMapper; + +public class PreferencesServlet extends AbstractServlet +{ + private static final long serialVersionUID = 1L; + + @Override + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + PreferencesProvider preferencesProvider = getPreferencesProvider(request); + if (preferencesProvider == null) + { + response.sendError(HttpServletResponse.SC_NOT_FOUND, "Preferences provider is not configured"); + return; + } + String userName = getAuthenticatedUserName(request); + Map<String, Object> preferences = preferencesProvider.getPreferences(userName); + if (preferences == null) + { + preferences = Collections.<String, Object>emptyMap(); + } + sendJsonResponse(preferences, response); + } + + /* + * replace preferences + */ + @Override + protected void doPutWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + PreferencesProvider preferencesProvider = getPreferencesProvider(request); + if (preferencesProvider == null) + { + response.sendError(HttpServletResponse.SC_NOT_FOUND, "Preferences provider is not configured"); + return; + } + String userName = getAuthenticatedUserName(request); + + ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unchecked") + Map<String, Object> newPreferences = mapper.readValue(request.getInputStream(), LinkedHashMap.class); + + preferencesProvider.deletePreferences(userName); + Map<String, Object> preferences = preferencesProvider.setPreferences(userName, newPreferences); + if (preferences == null) + { + preferences = Collections.<String, Object>emptyMap(); + } + sendJsonResponse(preferences, response); + } + + /* + * update preferences + */ + @Override + protected void doPostWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException + { + PreferencesProvider preferencesProvider = getPreferencesProvider(request); + if (preferencesProvider == null) + { + throw new IllegalStateException("Preferences provider is not configured"); + } + String userName = getAuthenticatedUserName(request); + + ObjectMapper mapper = new ObjectMapper(); + + @SuppressWarnings("unchecked") + Map<String, Object> newPreferences = mapper.readValue(request.getInputStream(), LinkedHashMap.class); + Map<String, Object> preferences = preferencesProvider.setPreferences(userName, newPreferences); + if (preferences == null) + { + preferences = Collections.<String, Object>emptyMap(); + } + sendJsonResponse(preferences, response); + } + + private String getAuthenticatedUserName(HttpServletRequest request) + { + Subject subject = getAuthorisedSubject(request); + Principal principal = AuthenticatedPrincipal.getAuthenticatedPrincipalFromSubject(subject); + return principal.getName(); + } + + private PreferencesProvider getPreferencesProvider(HttpServletRequest request) + { + SocketAddress localAddress = HttpManagementUtil.getSocketAddress(request); + AuthenticationProvider authenticationProvider = getManagementConfiguration().getAuthenticationProvider(localAddress); + if (authenticationProvider == null) + { + throw new IllegalStateException("Authentication provider is not found"); + } + return authenticationProvider.getPreferencesProvider(); + } +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java index 1cebe3ec19..8ea0aa538a 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java @@ -123,7 +123,7 @@ public class RestServlet extends AbstractServlet if(names.size() > _hierarchy.length) { - throw new IllegalArgumentException("Too many entries in path"); + throw new IllegalArgumentException("Too many entries in path. Expected " + _hierarchy.length + "; path: " + names); } } @@ -337,7 +337,7 @@ public class RestServlet extends AbstractServlet if(names.size() != _hierarchy.length) { throw new IllegalArgumentException("Path to object to create must be fully specified. " - + "Found " + names.size() + " expecting " + _hierarchy.length); + + "Found " + names + " of size " + names.size() + " expecting " + _hierarchy.length); } } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java index b67c83dc7a..2b035fed8f 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java @@ -278,7 +278,7 @@ public class SaslServlet extends AbstractServlet private SubjectCreator getSubjectCreator(HttpServletRequest request) { SocketAddress localAddress = HttpManagementUtil.getSocketAddress(request); - return HttpManagementUtil.getManagementConfiguration(getServletContext()).getSubjectCreator(localAddress); + return HttpManagementUtil.getManagementConfiguration(getServletContext()).getAuthenticationProvider(localAddress).getSubjectCreator(); } @Override diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java new file mode 100644 index 0000000000..808e3210dd --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/UserPreferencesServlet.java @@ -0,0 +1,215 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.security.access.Operation; + +public class UserPreferencesServlet extends AbstractServlet +{ + private static final Logger LOGGER = Logger.getLogger(UserPreferencesServlet.class); + private static final long serialVersionUID = 1L; + + @Override + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException, + ServletException + { + String[] pathElements = null; + if (request.getPathInfo() != null && request.getPathInfo().length() > 0) + { + pathElements = request.getPathInfo().substring(1).split("/"); + } + if (pathElements != null && pathElements.length > 1) + { + getUserPreferences(pathElements[0], pathElements[1], response); + } + else + { + getUserList(pathElements, response); + } + } + + private void getUserPreferences(String authenticationProviderName, String userId, HttpServletResponse response) + throws IOException + { + if (!userPreferencesOperationAuthorized(userId)) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Vieweing of preferences is not allowed"); + return; + } + Map<String, Object> preferences = null; + PreferencesProvider preferencesProvider = getPreferencesProvider(authenticationProviderName); + if (preferencesProvider == null) + { + response.sendError(HttpServletResponse.SC_NOT_FOUND, "Preferences provider is not configured"); + return; + } + preferences = preferencesProvider.getPreferences(userId); + + sendJsonResponse(preferences, response); + } + + private void getUserList(String[] pathElements, HttpServletResponse response) throws IOException + { + List<Map<String, Object>> users = null; + try + { + users = getUsers(pathElements); + } + catch (Exception e) + { + LOGGER.debug("Bad preferences request", e); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } + sendJsonResponse(users, response); + } + + private PreferencesProvider getPreferencesProvider(String authenticationProviderName) + { + AuthenticationProvider authenticationProvider = getAuthenticationProvider(authenticationProviderName); + if (authenticationProvider == null) + { + throw new IllegalArgumentException(String.format("Authentication provider '%s' is not found", + authenticationProviderName)); + } + PreferencesProvider preferencesProvider = authenticationProvider.getPreferencesProvider(); + return preferencesProvider; + } + + private AuthenticationProvider getAuthenticationProvider(String authenticationProviderName) + { + Broker broker = getBroker(); + Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders(); + for (AuthenticationProvider authenticationProvider : authenticationProviders) + { + if (authenticationProviderName.equals(authenticationProvider.getName())) + { + return authenticationProvider; + } + } + return null; + } + + private List<Map<String, Object>> getUsers(String[] pathElements) + { + List<Map<String, Object>> users = new ArrayList<Map<String, Object>>(); + String authenticationProviderName = pathElements != null && pathElements.length > 0 ? pathElements[0] : null; + + Broker broker = getBroker(); + Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders(); + for (AuthenticationProvider authenticationProvider : authenticationProviders) + { + if (authenticationProviderName != null && !authenticationProvider.getName().equals(authenticationProviderName)) + { + continue; + } + PreferencesProvider preferencesProvider = authenticationProvider.getPreferencesProvider(); + if (preferencesProvider != null) + { + Set<String> usernames = preferencesProvider.listUserIDs(); + for (String name : usernames) + { + Map<String, Object> userMap = new HashMap<String, Object>(); + userMap.put(User.NAME, name); + userMap.put("authenticationProvider", authenticationProvider.getName()); + users.add(userMap); + } + } + } + return users; + } + + /* + * removes preferences + */ + @Override + protected void doDeleteWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws IOException + { + final List<String[]> userData = new ArrayList<String[]>(); + for (String name : request.getParameterValues("user")) + { + String[] elements = name.split("/"); + if (elements.length != 2) + { + throw new IllegalArgumentException("Illegal parameter"); + } + userData.add(elements); + } + + if (!userData.isEmpty()) + { + Broker broker = getBroker(); + Collection<AuthenticationProvider> authenticationProviders = broker.getAuthenticationProviders(); + for (Iterator<String[]> it = userData.iterator(); it.hasNext();) + { + String[] data = (String[]) it.next(); + String authenticationProviderName = data[0]; + String userId = data[1]; + + for (AuthenticationProvider authenticationProvider : authenticationProviders) + { + if (authenticationProviderName.equals(authenticationProvider.getName())) + { + PreferencesProvider preferencesProvider = authenticationProvider.getPreferencesProvider(); + if (preferencesProvider != null) + { + Set<String> usernames = preferencesProvider.listUserIDs(); + if (usernames.contains(userId)) + { + if (!userPreferencesOperationAuthorized(userId)) + { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Deletion of preferences is not allowed"); + return; + } + preferencesProvider.deletePreferences(userId); + } + } + break; + } + } + } + } + + } + + private boolean userPreferencesOperationAuthorized(String userId) + { + return getBroker().getSecurityManager().authoriseUserOperation(Operation.UPDATE, userId); + } +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPreferencesProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPreferencesProvider.html new file mode 100644 index 0000000000..ac5dd32119 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPreferencesProvider.html @@ -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. + --> +<div class="dijitHidden"> + <div data-dojo-type="dijit.Dialog" data-dojo-props="title:'Preferences Provider'" id="addPreferencesProvider"> + <form id="formAddPreferencesProvider" method="post" data-dojo-type="dijit.form.Form"> + <input type="hidden" id="preferencesProvider.id" name="id"/> + <div style="height:100px; width:420px; overflow: auto"> + <table class="tableContainer-table tableContainer-table-horiz" width="100%" cellspacing="1"> + <tr> + <td class="tableContainer-labelCell" style="width: 200px;"><strong>Type*:</strong></td> + <td class="tableContainer-valueCell"><div id="addPreferencesProvider.selectPreferencesProviderDiv"></div></td> + </tr> + <tr> + <td class="tableContainer-labelCell" style="width: 200px;"><strong>Name*:</strong></td> + <td class="tableContainer-valueCell"><input type="text" name="name" + id="preferencesProvider.name" data-dojo-type="dijit.form.ValidationTextBox" + data-dojo-props="placeHolder: 'Name', + required: true, + missingMessage: 'A name must be supplied', + title: 'Enter name', + pattern: '^[\x20-\x2e\x30-\x7F]{1,255}$'" /></td> + </tr> + </table> + <div id="preferencesProvider.fieldsContainer"></div> + </div> + <div class="dijitDialogPaneActionBar"> + <!-- submit buttons --> + <input type="submit" value="Save Preferences Provider" data-dojo-props="label: 'Save Preferences Provider'" data-dojo-type="dijit.form.Button" /> + <input type="button" value="Cancel" data-dojo-props="label: 'Cancel'" data-dojo-type="dijit.form.Button" id="addPreferencesProvider.cancelButton"/> + </div> + </form> + </div> +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/preferences/filesystempreferences/add.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/preferences/filesystempreferences/add.html new file mode 100644 index 0000000000..f46da4b017 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/preferences/filesystempreferences/add.html @@ -0,0 +1,29 @@ +<!-- + ~ 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. + --> +<table class="tableContainer-table tableContainer-table-horiz" style="margin:0; width:100%" cellspacing="1"> + <tr> + <td class="tableContainer-labelCell" style="width: 200px;"><strong>Path*: </strong></td> + <td class="tableContainer-valueCell" > + <input type="text" name="path" + id="preferencesProvider.path" + data-dojo-type="dijit.form.ValidationTextBox" + data-dojo-props="placeHolder: 'Path/to/file', + required: true, + missingMessage: 'A path must be supplied', + title: 'Enter path'"/></td> + </tr> +</table> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/preferences/filesystempreferences/show.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/preferences/filesystempreferences/show.html new file mode 100644 index 0000000000..bc302d1e65 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/authenticationprovider/preferences/filesystempreferences/show.html @@ -0,0 +1,21 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> + +<div style="clear:both"> + <div class="formLabel-labelCell" style="float:left; width: 100px;">Path:</div> + <div class="fileSystemPreferencesProviderPath" style="float:left;"></div> +</div>
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/common/TimeZoneSelector.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/common/TimeZoneSelector.html new file mode 100644 index 0000000000..7027a4555c --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/common/TimeZoneSelector.html @@ -0,0 +1,55 @@ +<!-- + - + - 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. + - + --> +<table cellpadding="0" cellspacing="2"> + <tr> + <td>Region</td> + <td> + <select class='timezoneRegion' name="region" data-dojo-type="dijit/form/FilteringSelect" data-dojo-props=" + placeholder: 'Select region', + required: true, + missingMessage: 'A region must be supplied', + title: 'Select region', + autoComplete: true, + value:'undefined'"> + <option value="undefined">Undefined</option> + <option value="Africa">Africa</option> + <option value="America">America</option> + <option value="Antarctica">Antarctica</option> + <option value="Arctic">Arctic</option> + <option value="Asia">Asia</option> + <option value="Atlantic">Atlantic</option> + <option value="Australia">Australia</option> + <option value="Europe">Europe</option> + <option value="Indian">Indian</option> + <option value="Pacific">Pacific</option> + </select> + </td> + <td>City</td> + <td> + <select class='timezoneCity' name="city" data-dojo-type="dijit/form/FilteringSelect" data-dojo-props=" + placeholder: 'Select city', + required: true, + missingMessage: 'A city must be supplied', + title: 'Select city'"> + </select> + </td> + </tr> +</table>
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css index 4c8b79ab82..d9064f40c9 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/css/common.css @@ -92,4 +92,74 @@ div .messages { .formLabel-labelCell { font-weight: bold; +} + +.columnDefDialogButtonIcon { + background: url("../dojo/dojox/grid/enhanced/resources/images/sprite_icons.png") no-repeat; + background-position: -260px 2px; + width: 14px; + height: 14px; +} + +.logViewerIcon { + background: url("../images/log-viewer.png") no-repeat; + width: 14px; + height: 16px; +} + +.downloadLogsIcon { + background: url("../images/download.png") no-repeat; + width: 14px; + height: 14px; +} + +.dojoxGridFBarClearFilterButtontnIcon +{ + background: url("../dojo/dojox/grid/enhanced/resources/images/sprite_icons.png") no-repeat; + background-position: -120px -18px; + width: 14px; + height: 14px; +} + +.rowNumberLimitIcon +{ + background: url("../dojo/dojox/grid/enhanced/resources/images/sprite_icons.png") no-repeat; + background-position: -240px -18px; + width: 14px; + height: 14px; +} + +.gridRefreshIcon +{ + background: url("../images/refresh.png") no-repeat; + width: 16px; + height: 16px; +} + +.gridAutoRefreshIcon +{ + background: url("../images/auto-refresh.png") no-repeat; + width: 16px; + height: 16px; +} + +.redBackground tr{ background-color:#ffdcd7 !important; background-image: none !important;} +.yellowBackground tr{background-color:#fbfddf !important; background-image: none !important;} +.grayBackground tr{background-color:#eeeeee !important; background-image: none !important;} +.dojoxGridRowOdd.grayBackground tr{ background-color:#e9e9e9 !important; background-image: none !important;} +.dojoxGridRowOdd.yellowBackground tr{background-color:#fafdd5 !important; background-image: none !important;} +.dojoxGridRowOdd.redBackground tr{background-color:#f4c1c1 !important; background-image: none !important;} + +.preferencesIcon +{ + background: url("../images/gear.png") no-repeat; + width: 16px; + height: 16px; +} + +.helpIcon +{ + background: url("../images/help.png") no-repeat; + width: 16px; + height: 16px; }
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/grid/showColumnDefDialog.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/grid/showColumnDefDialog.html new file mode 100644 index 0000000000..5b6b8ad774 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/grid/showColumnDefDialog.html @@ -0,0 +1,32 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> +<div> + <div> + <div>Select columns to display:</div> + <div class="columnList"></div> + </div> + <div class="dijitDialogPaneActionBar"> + <button value="Display" data-dojo-type="dijit.form.Button" + class="displayButton" data-dojo-props="label: 'Display' "></button> + <button value="Cancel" data-dojo-type="dijit.form.Button" data-dojo-props="label: 'Cancel'" + class="cancelButton"></button> + </div> +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/grid/showRowNumberLimitDialog.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/grid/showRowNumberLimitDialog.html new file mode 100644 index 0000000000..087d54c0f9 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/grid/showRowNumberLimitDialog.html @@ -0,0 +1,33 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> +<div> + <div> + <div>Set the maximum number of rows to cache and display:</div> + <input class="rowNumberLimit" data-dojo-type="dijit.form.NumberSpinner" + data-dojo-props="invalidMessage: 'Invalid value', required: true, smallDelta: 1,mconstraints: {min:1,max:65535,places:0, pattern: '#####'}, label: 'Maximum number of rows:', name: 'rowNumberLimit'"></input> + </div> + <div class="dijitDialogPaneActionBar"> + <button value="Submit" data-dojo-type="dijit.form.Button" + class="submitButton" data-dojo-props="label: 'Submit' "></button> + <button value="Cancel" data-dojo-type="dijit.form.Button" data-dojo-props="label: 'Cancel'" + class="cancelButton"></button> + </div> +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/images/auto-refresh.png b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/auto-refresh.png Binary files differnew file mode 100644 index 0000000000..493636f467 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/auto-refresh.png diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/images/download.png b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/download.png Binary files differnew file mode 100644 index 0000000000..b64b41d476 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/download.png diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/images/gear.png b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/gear.png Binary files differnew file mode 100644 index 0000000000..0bb4394b46 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/gear.png diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/images/help.png b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/help.png Binary files differnew file mode 100644 index 0000000000..f7d3698d25 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/help.png diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/images/log-viewer.png b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/log-viewer.png Binary files differnew file mode 100644 index 0000000000..858fd48beb --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/log-viewer.png diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png Binary files differindex 95d49ea469..ae0fbb462f 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/qpid-logo.png diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/images/refresh.png b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/refresh.png Binary files differnew file mode 100644 index 0000000000..083044979b --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/images/refresh.png diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html index 4b97c464ec..4fc961ec12 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/index.html @@ -42,7 +42,6 @@ var dojoConfig = { tlmSiblingOfDojo:false, - parseOnLoad:true, async:true, baseUrl: getContextPath(), packages:[ @@ -58,7 +57,14 @@ </script> <script> - require(["dijit/layout/BorderContainer", + var qpidHelpLocation = "http://qpid.apache.org/releases/qpid-"; + var qpidHelpURL = null; + var qpidPreferences = null; + require([ + "dojo/_base/xhr", + "dojo/parser", + "qpid/management/Preferences", + "dijit/layout/BorderContainer", "dijit/layout/TabContainer", "dijit/layout/ContentPane", "dijit/TitlePane", @@ -66,7 +72,18 @@ "qpid/management/treeView", "qpid/management/controller", "qpid/common/footer", - "qpid/authorization/checkUser"]); + "qpid/authorization/checkUser"], function(xhr, parser, Preferences){ + parser.parse(); + qpidPreferences = new Preferences(); + xhr.get({ + sync: true, + url: "rest/helper?action=version", + handleAs: "json" + }).then(function(qpidVersion) { + qpidHelpURL = qpidHelpLocation + qpidVersion + "/java-broker/book/index.html"; + }); + + }); </script> </head> @@ -75,7 +92,27 @@ <div id="pageLayout" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'headline', gutters: false"> <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'"> <div id="header" class="header" style="float: left; width: 300px"></div> - <div id="login" style="float: right; display:none"><strong>User: </strong> <span id="authenticatedUser"></span><a href="logout">[logout]</a></div> + <div style="float: right;"> + <div id="login" style="display:none"><strong>User: </strong> <span id="authenticatedUser"></span><a href="logout">[logout]</a></div> + <div id="preferencesButton" style="float: right; margin-top: 0px;" data-dojo-type="dijit.form.DropDownButton" data-dojo-props="iconClass: 'preferencesIcon', title: 'Preferences', showLabel:false"> + <div data-dojo-type="dijit.Menu"> + <div data-dojo-type="dijit.MenuItem" data-dojo-props=" + iconClass: 'dijitIconFunction', + onClick: function(){ qpidPreferences.showDialog(); } "> + Preferences + </div> + <!-- + <div data-dojo-type="dijit.MenuItem" data-dojo-props="iconClass: 'dijitIconMail', onClick: function(){ console.log('TODO'); }"> + Contacts + </div> + --> + <div data-dojo-type="dijit.MenuItem" data-dojo-props="iconClass: 'helpIcon', onClick: function(){ + var newWindow = window.open(qpidHelpURL,'QpidHelp','height=600,width=600,scrollbars=1,location=1,resizable=1,status=0,toolbar=0,titlebar=1,menubar=0',true); newWindow.focus(); } "> + Help + </div> + </div> + </div> + </div> </div> <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'leading', splitter: true" style="width:20%"> <div qpid-type="treeView" qpid-props="query: 'rest/structure'" ></div> @@ -104,4 +141,4 @@ </div> </body> -</html>
\ No newline at end of file +</html> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/checkUser.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/checkUser.js index 159c7458ed..d65e6c6e07 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/checkUser.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/authorization/checkUser.js @@ -29,7 +29,7 @@ var updateUI = function updateUI(data) if(data.user) { dom.byId("authenticatedUser").innerHTML = entities.encode(String(data.user)); - dom.byId("login").style.display = "block"; + dom.byId("login").style.display = "inline"; } }; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TimeZoneSelector.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TimeZoneSelector.js new file mode 100644 index 0000000000..287fbc9619 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/TimeZoneSelector.js @@ -0,0 +1,176 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define([ + "dojo/_base/declare", + "dojo/_base/array", + "dojo/dom-construct", + "dojo/parser", + "dojo/query", + "dojo/store/Memory", + "dijit/_WidgetBase", + "dijit/registry", + "dojo/text!common/TimeZoneSelector.html", + "dijit/form/ComboBox", + "dijit/form/FilteringSelect", + "dojox/date/timezone", + "dojox/validate/us", + "dojox/validate/web", + "dojo/domReady!"], +function (declare, array, domConstruct, parser, query, Memory, _WidgetBase, registry, template) { + + var preferencesRegions = ["Africa","America","Antarctica","Arctic","Asia","Atlantic","Australia","Europe","Indian","Pacific"]; + + function initSupportedTimeZones() + { + var supportedTimeZones = []; + var allTimeZones = dojox.date.timezone.getAllZones(); + for(var i = 0; i < allTimeZones.length; i++) + { + var timeZone = allTimeZones[i]; + var elements = timeZone.split("/"); + if (elements.length > 1) + { + for(var j = 0; j<preferencesRegions.length; j++) + { + if (elements[0] == preferencesRegions[j]) + { + supportedTimeZones.push({id: timeZone, region: elements[0], city: elements.slice(1).join("/").replace("_", " ") }) + break; + } + } + } + } + return supportedTimeZones; + } + + function initSupportedRegions() + { + var supportedRegions = [{"id": "undefined", "name": "Undefined"}]; + for(var j = 0; j<preferencesRegions.length; j++) + { + supportedRegions.push({id: preferencesRegions[j], name: preferencesRegions[j] }); + } + return supportedRegions; + } + + return declare("qpid.common.TimeZoneSelector", [_WidgetBase], { + + value: null, + domNode: null, + _regionSelector: null, + _citySelector: null, + + constructor: function(args) + { + this._args = args; + }, + + buildRendering: function(){ + this.domNode = domConstruct.create("div", {innerHTML: template}); + parser.parse(this.domNode); + }, + + postCreate: function(){ + this.inherited(arguments); + + var supportedTimeZones = initSupportedTimeZones(); + + this._citySelector = registry.byNode(query(".timezoneCity", this.domNode)[0]); + this._citySelector.set("searchAttr", "city"); + this._citySelector.set("query", {region: /.*/}); + this._citySelector.set("labelAttr", "city"); + this._citySelector.set("store", new Memory({ data: supportedTimeZones })); + if (this._args.name) + { + this._citySelector.set("name", this._args.name); + } + this._regionSelector = registry.byNode(query(".timezoneRegion", this.domNode)[0]); + var supportedRegions = initSupportedRegions(); + this._regionSelector.set("store", new Memory({ data: supportedRegions })); + var self = this; + + this._regionSelector.on("change", function(value){ + if (value=="undefined") + { + self._citySelector.set("disabled", true); + self._citySelector.query.region = /.*/; + self.value = null; + self._citySelector.set("value", null); + } + else + { + self._citySelector.set("disabled", false); + self._citySelector.query.region = value || /.*/; + if (this.timeZone) + { + self._citySelector.set("value", this.timeZone); + this.timeZone = null; + } + else + { + self._citySelector.set("value", null); + } + } + }); + + this._citySelector.on("change", function(value){ + self.value = value; + }); + + this._setValueAttr(this._args.value); + }, + + _setValueAttr: function(value) + { + if (value) + { + var elements = value.split("/"); + if (elements.length > 1) + { + this._regionSelector.timeZone = value; + this._regionSelector.set("value", elements[0]); + this._citySelector.set("value", value); + } + else + { + this._regionSelector.set("value", "undefined"); + } + } + else + { + this._regionSelector.set("value", "undefined"); + } + this.value = value; + }, + + destroy: function() + { + if (this.domNode) + { + this.domNode.destroy(); + this.domNode = null; + } + _regionSelector: null; + _citySelector: null; + } + + }); +});
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js index f7ede1a7f7..ea3ba78372 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/UpdatableStore.js @@ -23,12 +23,13 @@ define(["dojo/store/Memory", "dojo/data/ObjectStore", "dojo/store/Observable"], function (Memory, DataGrid, ObjectStore, Observable) { - function UpdatableStore( data, divName, structure, func, props, Grid ) { + function UpdatableStore( data, divName, structure, func, props, Grid, notObservable ) { var that = this; var GridType = DataGrid; - that.store = Observable(Memory({data: data, idProperty: "id"})); + that.memoryStore = new Memory({data: data, idProperty: "id"}); + that.store = notObservable? that.memoryStore : new Observable(that.memoryStore); that.dataStore = ObjectStore({objectStore: that.store}); var gridProperties = { store: that.dataStore, @@ -63,7 +64,7 @@ define(["dojo/store/Memory", UpdatableStore.prototype.update = function(data) { - + var changed = false; var store = this.store; var theItem; @@ -78,7 +79,7 @@ define(["dojo/store/Memory", } } store.remove(object.id); - + changed = true; }); // iterate over data... @@ -91,20 +92,84 @@ define(["dojo/store/Memory", if(theItem[ propName ] != data[i][ propName ]) { theItem[ propName ] = data[i][ propName ]; modified = true; + changed = true; } } } if(modified) { // ... check attributes for updates store.notify(theItem, data[i].id); + changed = true; } } else { // ,,, if not in the store then add store.put(data[i]); + changed = true; } } } + return changed; + }; + + function removeItemsFromArray(items, numberToRemove) + { + if (items) + { + if (numberToRemove > 0 && items.length > 0) + { + if (numberToRemove >= items.length) + { + numberToRemove = numberToRemove - items.length; + items.length = 0 + } + else + { + items.splice(0, numberToRemove); + numberToRemove = 0; + } + } + } + return numberToRemove; + }; + + UpdatableStore.prototype.append = function(data, limit) + { + var changed = false; + var items = this.memoryStore.data; + + if (limit) + { + var totalSize = items.length + (data ? data.length : 0); + var numberToRemove = totalSize - limit; + + if (numberToRemove > 0) + { + changed = true; + numberToRemove = removeItemsFromArray(items, numberToRemove); + if (numberToRemove > 0) + { + removeItemsFromArray(data, numberToRemove); + } + } + } + + if (data && data.length > 0) + { + changed = true; + items.push.apply(items, data); + } + + this.memoryStore.setData(items); + return changed; + }; + + UpdatableStore.prototype.close = function() + { + this.dataStore.close(); + this.dataStore = null; + this.store = null; + this.memoryStore = null; }; return UpdatableStore; }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/ColumnDefDialog.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/ColumnDefDialog.js new file mode 100644 index 0000000000..d285dfaad6 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/ColumnDefDialog.js @@ -0,0 +1,140 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +define([ + "dojo/_base/declare", + "dojo/_base/event", + "dojo/_base/array", + "dojo/_base/lang", + "dojo/parser", + "dojo/dom-construct", + "dojo/query", + "dijit/registry", + "dijit/form/Button", + "dijit/form/CheckBox", + "dojox/grid/enhanced/plugins/Dialog", + "dojo/text!../../../grid/showColumnDefDialog.html", + "dojo/domReady!" +], function(declare, event, array, lang, parser, dom, query, registry, Button, CheckBox, Dialog, template ){ + + +return declare("qpid.common.grid.ColumnDefDialog", null, { + + grid: null, + containerNode: null, + _columns: [], + _dialog: null, + + constructor: function(args){ + var grid = this.grid = args.grid; + + this.containerNode = dom.create("div", {innerHTML: template}); + parser.parse(this.containerNode); + + var submitButton = registry.byNode(query(".displayButton", this.containerNode)[0]); + this.closeButton = registry.byNode(query(".cancelButton", this.containerNode)[0]); + var columnsContainer = query(".columnList", this.containerNode)[0]; + + this._buildColumnWidgets(columnsContainer); + + this._dialog = new Dialog({ + "refNode": this.grid.domNode, + "title": "Grid Columns", + "content": this.containerNode + }); + + var self = this; + submitButton.on("click", function(e){self._onColumnsSelect(e); }); + this.closeButton.on("click", function(e){self._dialog.hide(); }); + + this._dialog.startup(); + }, + + destroy: function(){ + this._dialog.destroyRecursive(); + this._dialog = null; + this.grid = null; + this.containerNode = null; + this._columns = null; + }, + + showDialog: function(){ + this._initColumnWidgets(); + this._dialog.show(); + }, + + _initColumnWidgets: function() + { + var cells = this.grid.layout.cells; + for(var i in cells) + { + var cell = cells[i]; + this._columns[cell.name].checked = !cell.hidden; + } + }, + + _onColumnsSelect: function(evt){ + event.stop(evt); + var grid = this.grid; + grid.beginUpdate(); + var cells = grid.layout.cells; + try + { + for(var i in cells) + { + var cell = cells[i]; + var widget = this._columns[cell.name]; + grid.layout.setColumnVisibility(i, widget.checked); + } + } + finally + { + grid.endUpdate(); + this._dialog.hide(); + } + }, + + _buildColumnWidgets: function(columnsContainer) + { + var cells = this.grid.layout.cells; + for(var i in cells) + { + var cell = cells[i]; + var widget = new dijit.form.CheckBox({ + required: false, + checked: !cell.hidden, + label: cell.name, + name: this.grid.id + "_cchb_ " + i + }); + + this._columns[cell.name] = widget; + + var div = dom.create("div"); + div.appendChild(widget.domNode); + div.appendChild(dom.create("span", {innerHTML: cell.name})); + + columnsContainer.appendChild(div); + } + } + + }); + +}); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilter.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilter.js new file mode 100644 index 0000000000..9c0baf3111 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilter.js @@ -0,0 +1,229 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +define([ + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/array", + "dijit/Toolbar", + "dojox/grid/enhanced/_Plugin", + "dojox/grid/enhanced/plugins/Dialog", + "dojox/grid/enhanced/plugins/filter/FilterLayer", + "dojox/grid/enhanced/plugins/filter/FilterDefDialog", + "dojox/grid/enhanced/plugins/filter/FilterStatusTip", + "dojox/grid/enhanced/plugins/filter/ClearFilterConfirm", + "dojox/grid/EnhancedGrid", + "dojo/i18n!dojox/grid/enhanced/nls/Filter", + "qpid/common/grid/EnhancedFilterTools" +], function(declare, lang, array, Toolbar, _Plugin, + Dialog, FilterLayer, FilterDefDialog, FilterStatusTip, ClearFilterConfirm, EnhancedGrid, nls, EnhancedFilterTools){ + + // override CriteriaBox#_getColumnOptions to show criteria for hidden columns with EnhancedFilter + dojo.extend(dojox.grid.enhanced.plugins.filter.CriteriaBox, { + _getColumnOptions: function(){ + var colIdx = this.dlg.curColIdx >= 0 ? String(this.dlg.curColIdx) : "anycolumn"; + var filterHidden = this.plugin.filterHidden; + return array.map(array.filter(this.plugin.grid.layout.cells, function(cell){ + return !(cell.filterable === false || (!filterHidden && cell.hidden)); + }), function(cell){ + return { + label: cell.name || cell.field, + value: String(cell.index), + selected: colIdx == String(cell.index) + }; + }); + } + }); + + // Enhanced filter has extra functionality for refreshing, limiting rows, displaying/hiding columns in the grid + var EnhancedFilter = declare("qpid.common.grid.EnhancedFilter", _Plugin, { + // summary: + // Accept the same plugin parameters as dojox.grid.enhanced.plugins.Filter and the following: + // + // filterHidden: boolean: + // Whether to display filtering criteria for hidden columns. Default to true. + // + // defaulGridRowLimit: int: + // Default limit for numbers of items to cache in the gris dtore + // + // disableFiltering: boolean: + // Whether to disable a filtering including filter button, clear filter button and filter summary. + // + // toolbar: dijit.Toolbar: + // An instance of toolbar to add the enhanced filter widgets. + + + // name: String + // plugin name + name: "enhancedFilter", + + // filterHidden: Boolean + // whether to filter hidden columns + filterHidden: true, + + constructor: function(grid, args){ + // summary: + // See constructor of dojox.grid.enhanced._Plugin. + this.grid = grid; + this.nls = nls; + + args = this.args = lang.isObject(args) ? args : {}; + if(typeof args.ruleCount != 'number' || args.ruleCount < 0){ + args.ruleCount = 0; + } + var rc = this.ruleCountToConfirmClearFilter = args.ruleCountToConfirmClearFilter; + if(rc === undefined){ + this.ruleCountToConfirmClearFilter = 5; + } + + if (args.filterHidden){ + this.filterHidden = args.filterHidden; + } + this.defaulGridRowLimit = args.defaulGridRowLimit; + this.disableFiltering = args.disableFiltering; + + //Install UI components + var obj = { "plugin": this }; + + this.filterBar = ( args.toolbar && args.toolbar instanceof dijit.Toolbar) ? args.toolbar: new Toolbar(); + + if (!this.disableFiltering) + { + //Install filter layer + this._wrapStore(); + + this.clearFilterDialog = new Dialog({ + refNode: this.grid.domNode, + title: this.nls["clearFilterDialogTitle"], + content: new ClearFilterConfirm(obj) + }); + + this.filterDefDialog = new FilterDefDialog(obj); + + nls["statusTipTitleNoFilter"] = "Filter is not set"; + nls["statusTipMsg"] = "Click on 'Set Filter' button to specify filtering conditions"; + this.filterStatusTip = new FilterStatusTip(obj); + + var self = this; + var toggleClearFilterBtn = function (arg){ self.enhancedFilterTools.toggleClearFilterBtn(arg); }; + + this.filterBar.toggleClearFilterBtn = toggleClearFilterBtn; + + this.grid.isFilterBarShown = function (){return true}; + + this.connect(this.grid.layer("filter"), "onFilterDefined", function(filter){ + toggleClearFilterBtn(true); + }); + + //Expose the layer event to grid. + grid.onFilterDefined = function(){}; + this.connect(grid.layer("filter"), "onFilterDefined", function(filter){ + grid.onFilterDefined(grid.getFilter(), grid.getFilterRelation()); + }); + } + + // add extra buttons into toolbar + this.enhancedFilterTools = new EnhancedFilterTools({ + grid: grid, + toolbar: this.filterBar, + filterStatusTip: this.filterStatusTip, + clearFilterDialog: this.clearFilterDialog, + filterDefDialog: this.filterDefDialog, + defaulGridRowLimit: this.defaulGridRowLimit, + disableFiltering: this.disableFiltering, + nls: nls + }); + + this.filterBar.placeAt(this.grid.viewsHeaderNode, "before"); + this.filterBar.startup(); + + }, + + destroy: function(){ + this.inherited(arguments); + try + { + if (this.filterDefDialog) + { + this.filterDefDialog.destroy(); + this.filterDefDialog = null; + } + if (this.grid) + { + this.grid.unwrap("filter"); + this.grid = null; + } + if (this.filterBar) + { + this.filterBar.destroyRecursive(); + this.filterBar = null; + } + if (this.enhancedFilterTools) + { + this.enhancedFilterTools.destroy(); + this.enhancedFilterTools = null; + } + if (this.clearFilterDialog) + { + this.clearFilterDialog.destroyRecursive(); + this.clearFilterDialog = null; + } + if (this.filterStatusTip) + { + this.filterStatusTip.destroy(); + this.filterStatusTip = null; + } + this.args = null; + + }catch(e){ + console.warn("Filter.destroy() error:",e); + } + }, + + _wrapStore: function(){ + var g = this.grid; + var args = this.args; + var filterLayer = args.isServerSide ? new FilterLayer.ServerSideFilterLayer(args) : + new FilterLayer.ClientSideFilterLayer({ + cacheSize: args.filterCacheSize, + fetchAll: args.fetchAllOnFirstFilter, + getter: this._clientFilterGetter + }); + FilterLayer.wrap(g, "_storeLayerFetch", filterLayer); + + this.connect(g, "_onDelete", lang.hitch(filterLayer, "invalidate")); + }, + + onSetStore: function(store){ + this.filterDefDialog.clearFilter(true); + }, + + _clientFilterGetter: function(/* data item */ datarow,/* cell */cell, /* int */rowIndex){ + return cell.get(rowIndex, datarow); + } + + }); + + EnhancedGrid.registerPlugin(EnhancedFilter); + + return EnhancedFilter; + +}); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilterTools.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilterTools.js new file mode 100644 index 0000000000..b1645b4905 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/EnhancedFilterTools.js @@ -0,0 +1,270 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +define([ + "dojo/_base/declare", + "dojo/_base/event", + "dijit/form/Button", + "dijit/form/ToggleButton", + "qpid/common/grid/RowNumberLimitDialog", + "qpid/common/grid/ColumnDefDialog", + "qpid/common/grid/FilterSummary" +], function(declare, event, Button, ToggleButton, RowNumberLimitDialog, ColumnDefDialog, FilterSummary){ + + var _stopEvent = function (evt){ + try{ + if(evt && evt.preventDefault){ + event.stop(evt); + } + }catch(e){} + }; + + return declare("qpid.common.grid.EnhancedFilterTools", null, { + + grid: null, + filterBar: null, + filterStatusTip: null, + clearFilterDialog: null, + filterDefDialog: null, + + columnDefDialog: null, + columnDefButton: null, + filterDefButton: null, + clearFilterButton: null, + filterSummary: null, + setRowNumberLimitButton: null, + setRowNumberLimitDialog: null, + refreshButton: null, + autoRefreshButton: null, + + constructor: function(params) + { + this.inherited(arguments); + + this.filterBar = params.toolbar; + this.grid = params.grid; + this.filterStatusTip= params.filterStatusTip; + this.clearFilterDialog = params.clearFilterDialog; + this.filterDefDialog = params.filterDefDialog; + + this._addRefreshButtons(); + this._addRowLimitButton(params.defaulGridRowLimit); + this._addColumnsButton(); + + if (!params.disableFiltering) + { + this._addFilteringTools(params.nls); + } + }, + + toggleClearFilterBtn: function(clearFlag) + { + var filterLayer = this.grid.layer("filter"); + var filterSet = filterLayer && filterLayer.filterDef && filterLayer.filterDef(); + this.clearFilterButton.set("disabled", !filterSet); + }, + + destroy: function() + { + this.inherited(arguments); + + if (this.columnDefDialog) + { + this.columnDefDialog.destroy(); + this.columnDefDialog = null; + } + if (this.columnDefButton) + { + this.columnDefButton.destroy(); + this.columnDefButton = null; + } + if (this.filterDefButton) + { + this.filterDefButton.destroy(); + this.filterDefButton = null; + } + if (this.clearFilterButton) + { + this.clearFilterButton.destroy(); + this.clearFilterButton = null; + } + if (this.filterSummary) + { + this.filterSummary.destroy(); + this.filterSummary = null; + } + if (this.setRowNumberLimitButton) + { + this.setRowNumberLimitButton.destroy(); + this.setRowNumberLimitButton = null; + } + if (this.setRowNumberLimitDialog) + { + this.setRowNumberLimitDialog.destroy(); + this.setRowNumberLimitDialog = null; + } + if (this.refreshButton) + { + this.refreshButton.destroy(); + this.refreshButton = null; + } + if (this.autoRefreshButton) + { + this.autoRefreshButton.destroy(); + this.autoRefreshButton = null; + } + + this.grid = null; + this.filterBar = null; + this.filterStatusTip = null; + this.clearFilterDialog = null; + this.filterDefDialog = null; + }, + + _addRefreshButtons: function() + { + var self = this; + this.refreshButton = new dijit.form.Button({ + label: "Refresh", + type: "button", + iconClass: "gridRefreshIcon", + title: "Manual Refresh" + }); + + this.autoRefreshButton = new dijit.form.ToggleButton({ + label: "Auto Refresh", + type: "button", + iconClass: "gridAutoRefreshIcon", + title: "Auto Refresh" + }); + + this.autoRefreshButton.on("change", function(value){ + self.grid.updater.updatable=value; + self.refreshButton.set("disabled", value); + }); + + this.refreshButton.on("click", function(value){ + self.grid.updater.performUpdate(); + }); + + this.filterBar.addChild(this.autoRefreshButton); + this.filterBar.addChild(this.refreshButton); + }, + + _addRowLimitButton: function(defaulGridRowLimit) + { + var self = this; + this.setRowNumberLimitButton = new dijit.form.Button({ + label: "Set Row Limit", + type: "button", + iconClass: "rowNumberLimitIcon", + title: "Set Row Number Limit" + }); + this.setRowNumberLimitButton.set("title", "Set Row Number Limit (Current: " + defaulGridRowLimit +")"); + + this.setRowNumberLimitDialog = new RowNumberLimitDialog(this.grid.domNode, function(newLimit){ + if (newLimit > 0 && self.grid.updater.appendLimit != newLimit ) + { + self.grid.updater.appendLimit = newLimit; + self.grid.updater.performRefresh([]); + self.setRowNumberLimitButton.set("title", "Set Row Number Limit (Current: " + newLimit +")"); + } + }); + + this.setRowNumberLimitButton.on("click", function(evt){ + self.setRowNumberLimitDialog.showDialog(self.grid.updater.appendLimit); + }); + + this.filterBar.addChild(this.setRowNumberLimitButton); + }, + + _addColumnsButton: function() + { + var self = this; + this.columnDefDialog = new ColumnDefDialog({grid: this.grid}); + + this.columnDefButton = new dijit.form.Button({ + label: "Display Columns", + type: "button", + iconClass: "columnDefDialogButtonIcon", + title: "Show/Hide Columns" + }); + + this.columnDefButton.on("click", function(e){ + _stopEvent(e); + self.columnDefDialog.showDialog(); + }); + + this.filterBar.addChild(this.columnDefButton); + }, + + _addFilteringTools: function(nls) + { + var self = this; + + this.filterDefButton = new dijit.form.Button({ + "class": "dojoxGridFBarBtn", + label: "Set Filter", + iconClass: "dojoxGridFBarDefFilterBtnIcon", + showLabel: "true", + title: "Define filter" + }); + + this.clearFilterButton = new dijit.form.Button({ + "class": "dojoxGridFBarBtn", + label: "Clear filter", + iconClass: "dojoxGridFBarClearFilterButtontnIcon", + showLabel: "true", + title: "Clear filter", + disabled: true + }); + + + this.filterDefButton.on("click", function(e){ + _stopEvent(e); + self.filterDefDialog.showDialog(); + }); + + this.clearFilterButton.on("click", function(e){ + _stopEvent(e); + if (self.ruleCountToConfirmClearFilter && self.filterDefDialog.getCriteria() >= self.ruleCountToConfirmClearFilter) + { + self.clearFilterDialog.show(); + } + else + { + self.grid.layer("filter").filterDef(null); + self.toggleClearFilterBtn(true) + } + }); + + this.filterSummary = new FilterSummary({grid: this.grid, filterStatusTip: this.filterStatusTip, nls: nls}); + + this.filterBar.addChild(this.filterDefButton); + this.filterBar.addChild(this.clearFilterButton); + + this.filterBar.addChild(new dijit.ToolbarSeparator()); + this.filterBar.addChild(this.filterSummary, "last"); + this.filterBar.getColumnIdx = function(coordX){return self.filterSummary._getColumnIdx(coordX);}; + + } + }); +});
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/FilterSummary.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/FilterSummary.js new file mode 100644 index 0000000000..2b1d960fa5 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/FilterSummary.js @@ -0,0 +1,173 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +define([ + "dojo/_base/declare", + "dojo/_base/lang", + "dojo/_base/html", + "dojo/query", + "dojo/dom-construct", + "dojo/string", + "dojo/on", + "dijit/_WidgetBase" +], function(declare, lang, html, query, domConstruct, string, on, _WidgetBase){ + +return declare("qpid.common.grid.FilterSummary", [_WidgetBase], { + + domNode: null, + itemName: null, + filterStatusTip: null, + grid: null, + _handle_statusTooltip: null, + _timeout_statusTooltip: 300, + _nls: null, + + constructor: function(params) + { + this.inherited(arguments); + this.itemName = params.itemsName; + this.initialize(params.filterStatusTip, params.grid); + this._nls = params.nls; + }, + + buildRendering: function(){ + this.inherited(arguments); + var itemsName = this.itemName || this._nls["defaultItemsName"]; + var message = string.substitute(this._nls["filterBarMsgNoFilterTemplate"], [0, itemsName ]); + this.domNode = domConstruct.create("span", {innerHTML: message, "class": "dijit dijitReset dijitInline dijitButtonInline", role: "presentation" }); + }, + + postCreate: function(){ + this.inherited(arguments); + on(this.domNode, "mouseenter", lang.hitch(this, this._onMouseEnter)); + on(this.domNode, "mouseleave", lang.hitch(this, this._onMouseLeave)); + on(this.domNode, "mousemove", lang.hitch(this, this._onMouseMove)); + }, + + destroy: function() + { + this.inherited(arguments); + this.itemName = null; + this.filterStatusTip = null; + this.grid = null; + this._handle_statusTooltip = null; + this._filteredClass = null; + this._nls = null; + }, + + initialize: function(filterStatusTip, grid) + { + this.filterStatusTip = filterStatusTip; + this.grid = grid; + if (this.grid) + { + var filterLayer = grid.layer("filter"); + this.connect(filterLayer, "onFiltered", this.onFiltered); + } + }, + + onFiltered: function(filteredSize, originSize) + { + try + { + var itemsName = this.itemName || this._nls["defaultItemsName"], + msg = "", g = this.grid, + filterLayer = g.layer("filter"); + if(filterLayer.filterDef()){ + msg = string.substitute(this._nls["filterBarMsgHasFilterTemplate"], [filteredSize, originSize, itemsName]); + }else{ + msg = string.substitute(this._nls["filterBarMsgNoFilterTemplate"], [originSize, itemsName]); + } + this.domNode.innerHTML = msg; + } + catch(e) + { + // swallow and log exception + // otherwise grid rendering is screwed + console.error(e); + } + }, + + _getColumnIdx: function(coordX){ + var headers = query("[role='columnheader']", this.grid.viewsHeaderNode); + var idx = -1; + for(var i = headers.length - 1; i >= 0; --i){ + var coord = html.position(headers[i]); + if(coordX >= coord.x && coordX < coord.x + coord.w){ + idx = i; + break; + } + } + if(idx >= 0 && this.grid.layout.cells[idx].filterable !== false){ + return idx; + }else{ + return -1; + } + }, + + _setStatusTipTimeout: function(){ + this._clearStatusTipTimeout(); + this._handle_statusTooltip = setTimeout(lang.hitch(this,this._showStatusTooltip),this._timeout_statusTooltip); + }, + + _clearStatusTipTimeout: function(){ + if (this._handle_statusTooltip){ + clearTimeout(this._handle_statusTooltip); + } + this._handle_statusTooltip = null; + }, + + _showStatusTooltip: function(){ + this._handle_statusTooltip = null; + if(this.filterStatusTip){ + this.filterStatusTip.showDialog(this._tippos.x, this._tippos.y, this._getColumnIdx(this._tippos.x)); + } + }, + + _updateTipPosition: function(evt){ + this._tippos = { + x: evt.pageX, + y: evt.pageY + }; + }, + + _onMouseEnter: function(e){ + this._updateTipPosition(e); + if(this.filterStatusTip){ + this._setStatusTipTimeout(); + } + }, + + _onMouseMove: function(e){ + if(this.filterStatusTip){ + this._setStatusTipTimeout(); + if(this._handle_statusTooltip){ + this._updateTipPosition(e); + } + } + }, + + _onMouseLeave: function(e){ + this._clearStatusTipTimeout(); + }, + }); + +});
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/GridUpdater.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/GridUpdater.js new file mode 100644 index 0000000000..7016e4eb5b --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/GridUpdater.js @@ -0,0 +1,258 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + + +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/_base/array", + "dojo/_base/lang", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/UpdatableStore", + "qpid/common/util", + "dojo/store/Memory", + "dojo/data/ObjectStore", + "qpid/common/grid/EnhancedFilter", + "dojox/grid/enhanced/plugins/NestedSorting", + "dojo/domReady!"], + function (xhr, parser, array, lang, properties, updater, UpdatableStore, util, Memory, ObjectStore) { + + function GridUpdater(args, store) { + this.updatable = args.hasOwnProperty("updatable") ? args.updatable : true ; + this.serviceUrl = args.serviceUrl; + + this.onUpdate = args.onUpdate; + + this.appendData = args.append; + this.appendLimit = args.appendLimit; + this.initialData = args.data; + this.initializeStore(store); + }; + + GridUpdater.prototype.buildUpdatableGridArguments = function(args) + { + var filterPluginFound = args && args.hasOwnProperty("plugins") && args.plugins.filter ? true: false; + + var gridProperties = { + autoHeight: true, + plugins: { + pagination: { + defaultPageSize: 25, + pageSizes: [10, 25, 50, 100], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + enhancedFilter: { + disableFiltering: filterPluginFound + } + } + }; + + if(args) + { + for(var argProperty in args) + { + if(args.hasOwnProperty(argProperty)) + { + if (argProperty == "plugins") + { + var argPlugins = args[ argProperty ]; + for(var argPlugin in argPlugins) + { + if(argPlugins.hasOwnProperty(argPlugin)) + { + var argPluginProperties = argPlugins[ argPlugin ]; + if (argPluginProperties && gridProperties.plugins.hasOwnProperty(argPlugin)) + { + var gridPlugin = gridProperties.plugins[ argPlugin ]; + for(var pluginProperty in argPluginProperties) + { + if(argPluginProperties.hasOwnProperty(pluginProperty)) + { + gridPlugin[pluginProperty] = argPluginProperties[pluginProperty]; + } + } + } + else + { + gridProperties.plugins[ argPlugin ] = argPlugins[ argPlugin ]; + } + } + } + } + else + { + gridProperties[ argProperty ] = args[ argProperty ]; + } + } + } + } + + gridProperties.updater = this; + gridProperties.store = this.dataStore; + + return gridProperties; + }; + + GridUpdater.prototype.initializeStore = function(store) + { + var self = this; + + function processData(data) + { + var dataSet = false; + if (!store) + { + store = new ObjectStore({objectStore: new Memory({data: data, idProperty: "id"})}); + dataSet = true; + } + self.dataStore = store + self.store = store; + if (store instanceof ObjectStore) + { + if( store.objectStore instanceof Memory) + { + self.memoryStore = store.objectStore; + } + self.store = store.objectStore + } + + if (data) + { + try + { + if ((dataSet || self.updateOrAppend(data)) && self.onUpdate) + { + self.onUpdate(data); + } + } + catch(e) + { + console.error(e); + } + } + }; + + if (this.serviceUrl) + { + var requestUrl = lang.isFunction(this.serviceUrl) ? this.serviceUrl() : this.serviceUrl; + xhr.get({url: requestUrl, sync: true, handleAs: "json"}).then(processData, util.errorHandler); + } + else + { + processData(this.initialData); + } + }; + + GridUpdater.prototype.start = function(grid) + { + this.grid = grid; + if (this.serviceUrl) + { + updater.add(this); + } + }; + + GridUpdater.prototype.destroy = function() + { + updater.remove(this); + if (this.dataStore) + { + this.dataStore.close(); + this.dataStore = null; + } + this.store = null; + this.memoryStore = null; + this.grid = null; + }; + + GridUpdater.prototype.updateOrAppend = function(data) + { + return this.appendData ? + UpdatableStore.prototype.append.call(this, data, this.appendLimit): + UpdatableStore.prototype.update.call(this, data); + }; + + GridUpdater.prototype.refresh = function(data) + { + this.updating = true; + try + { + if (this.updateOrAppend(data)) + { + // EnhancedGrid with Filter plugin has "filter" layer. + // The filter expression needs to be re-applied after the data update + var filterLayer = this.grid.layer("filter"); + if ( filterLayer && filterLayer.filterDef) + { + var currentFilter = filterLayer.filterDef(); + + if (currentFilter) + { + // re-apply filter in the filter layer + filterLayer.filterDef(currentFilter); + } + } + + // refresh grid to render updates + this.grid._refresh(); + } + } + finally + { + this.updating = false; + if (this.onUpdate) + { + this.onUpdate(data); + } + } + } + + GridUpdater.prototype.update = function() + { + if (this.updatable) + { + this.performUpdate(); + } + }; + + GridUpdater.prototype.performUpdate = function() + { + var self = this; + var requestUrl = lang.isFunction(this.serviceUrl) ? this.serviceUrl() : this.serviceUrl; + var requestArguments = {url: requestUrl, sync: properties.useSyncGet, handleAs: "json"}; + xhr.get(requestArguments).then(function(data){self.refresh(data);}); + }; + + GridUpdater.prototype.performRefresh = function(data) + { + if (!this.updating) + { + this.refresh(data); + } + }; + + return GridUpdater; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/RowNumberLimitDialog.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/RowNumberLimitDialog.js new file mode 100644 index 0000000000..db3ae5a2ea --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/RowNumberLimitDialog.js @@ -0,0 +1,96 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +define([ + "dojo/_base/declare", + "dojo/_base/event", + "dojo/_base/array", + "dojo/_base/lang", + "dojo/parser", + "dojo/dom-construct", + "dojo/query", + "dijit/registry", + "dijit/form/Button", + "dijit/form/CheckBox", + "dojox/grid/enhanced/plugins/Dialog", + "dojo/text!../../../grid/showRowNumberLimitDialog.html", + "dojo/domReady!" +], function(declare, event, array, lang, parser, dom, query, registry, Button, CheckBox, Dialog, template ){ + + +return declare("qpid.management.logs.RowNumberLimitDialog", null, { + + grid: null, + dialog: null, + + constructor: function(domNode, limitChangedCallback){ + + this.containerNode = dom.create("div", {innerHTML: template}); + parser.parse(this.containerNode); + + this.rowNumberLimit = registry.byNode(query(".rowNumberLimit", this.containerNode)[0]) + this.submitButton = registry.byNode(query(".submitButton", this.containerNode)[0]); + this.closeButton = registry.byNode(query(".cancelButton", this.containerNode)[0]); + + this.dialog = new Dialog({ + "refNode": domNode, + "title": "Grid Rows Number", + "content": this.containerNode + }); + + var self = this; + this.submitButton.on("click", function(e){ + if (self.rowNumberLimit.value > 0) + { + try + { + limitChangedCallback(self.rowNumberLimit.value); + } + catch(e) + { + console.error(e); + } + finally + { + self.dialog.hide(); + } + } + }); + + this.closeButton.on("click", function(e){self.dialog.hide(); }); + this.dialog.startup(); + }, + + destroy: function(){ + this.submitButton.destroy(); + this.closeButton.destroy(); + this.dialog.destroy(); + this.dialog = null; + }, + + showDialog: function(currentLimit){ + this.rowNumberLimit.set("value", currentLimit); + this.dialog.show(); + } + + }); + +}); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/UpdatableGrid.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/UpdatableGrid.js new file mode 100644 index 0000000000..04041388bd --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/UpdatableGrid.js @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +define([ + "dojo/_base/declare", + "dojox/grid/EnhancedGrid", + "dojo/domReady!"], function(declare, EnhancedGrid){ + + return declare("qpid.common.grid.UpdatableGrid", [EnhancedGrid], { + + updater: null, + + postCreate: function(){ + this.inherited(arguments); + if (this.updater) + { + this.updater.start(this); + } + }, + + destroy: function(){ + if (this.updater) + { + try + { + this.updater.destroy(); + } + catch(e) + { + console.error(e) + } + this.updater = null; + } + this.inherited(arguments); + } + }); + +}); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js index 2c2096d390..3d349830ac 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js @@ -77,10 +77,10 @@ define(["dojo/_base/xhr", return exchangeName == null || exchangeName == "" || "<<default>>" == exchangeName || exchangeName.indexOf("amq.") == 0 || exchangeName.indexOf("qpid.") == 0; }; - util.deleteGridSelections = function(updater, grid, url, confirmationMessageStart) + util.deleteGridSelections = function(updater, grid, url, confirmationMessageStart, idParam) { var data = grid.selection.getSelected(); - + var success = false; if(data.length) { var confirmationMessage = null; @@ -114,18 +114,19 @@ define(["dojo/_base/xhr", { queryParam = "?"; } - queryParam += "id=" + data[i].id; + queryParam += ( idParam || "id" ) + "=" + encodeURIComponent(data[i].id); } var query = url + queryParam; - var success = true var failureReason = ""; xhr.del({url: query, sync: true, handleAs: "json"}).then( function(data) { - // TODO why query *?? - //grid.setQuery({id: "*"}); + success = true; grid.selection.deselectAll(); - updater.update(); + if (updater) + { + updater.update(); + } }, function(error) {success = false; failureReason = error;}); if(!success ) @@ -134,6 +135,7 @@ define(["dojo/_base/xhr", } } } + return success; } util.isProviderManagingUsers = function(type) @@ -353,5 +355,21 @@ define(["dojo/_base/xhr", } }; + util.errorHandler = function errorHandler(error) + { + if(error.status == 401) + { + alert("Authentication Failed"); + } + else if(error.status == 403) + { + alert("Access Denied"); + } + else + { + alert(error); + } + } + return util; });
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js index 978ac4b45f..b5b4380a0d 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/AuthenticationProvider.js @@ -32,10 +32,13 @@ define(["dojo/_base/xhr", "dijit/registry", "dojo/dom-style", "dojox/html/entities", - "dojox/grid/enhanced/plugins/Pagination", - "dojox/grid/enhanced/plugins/IndirectSelection", + "dojo/dom", + "qpid/management/addPreferencesProvider", + "qpid/management/PreferencesProvider", + "qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager", "dojo/domReady!"], - function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, addAuthenticationProvider, event, registry, domStyle, entities) { + function (xhr, parser, query, connect, properties, updater, util, UpdatableStore, EnhancedGrid, + addAuthenticationProvider, event, registry, domStyle, entities, dom, addPreferencesProvider, PreferencesProvider, PrincipalDatabaseAuthenticationManager) { function AuthenticationProvider(name, parent, controller) { this.name = name; @@ -48,7 +51,7 @@ define(["dojo/_base/xhr", } AuthenticationProvider.prototype.getTitle = function() { - return "AuthenticationProvider"; + return "AuthenticationProvider:" + this.name; }; AuthenticationProvider.prototype.open = function(contentPane) { @@ -62,8 +65,6 @@ define(["dojo/_base/xhr", that.authProviderUpdater = new AuthProviderUpdater(contentPane.containerNode, that.modelObj, that.controller, that); - updater.add( that.authProviderUpdater ); - that.authProviderUpdater.update(); var editButton = query(".editAuthenticationProviderButton", contentPane.containerNode)[0]; @@ -81,6 +82,15 @@ define(["dojo/_base/xhr", event.stop(evt); that.deleteAuthenticationProvider(); }); + + var addPreferencesProviderButton = query(".addPreferencesProviderButton", contentPane.containerNode)[0]; + var addPreferencesProviderWidget = registry.byNode(addPreferencesProviderButton); + connect.connect(addPreferencesProviderWidget, "onClick", + function(evt){ + event.stop(evt); + that.addPreferencesProvider(); + }); + updater.add( that.authProviderUpdater ); }}); }; @@ -111,6 +121,14 @@ define(["dojo/_base/xhr", } }; + AuthenticationProvider.prototype.addPreferencesProvider = function() { + if (this.authProviderUpdater && this.authProviderUpdater.authProviderData + && (!this.authProviderUpdater.authProviderData.preferencesproviders + || !this.authProviderUpdater.authProviderData.preferencesproviders[0])){ + addPreferencesProvider.show(this.name); + } + }; + function AuthProviderUpdater(node, authProviderObj, controller, authenticationProvider) { this.controller = controller; @@ -118,6 +136,13 @@ define(["dojo/_base/xhr", this.type = query(".type", node)[0]; this.state = query(".state", node)[0]; this.authenticationProvider = authenticationProvider; + this.preferencesProviderType=dom.byId("preferencesProviderType"); + this.preferencesProviderName=dom.byId("preferencesProviderName"); + this.preferencesProviderState=dom.byId("preferencesProviderState"); + this.addPreferencesProviderButton = query(".addPreferencesProviderButton", node)[0]; + this.editPreferencesProviderButton = query(".editPreferencesProviderButton", node)[0]; + this.deletePreferencesProviderButton = query(".deletePreferencesProviderButton", node)[0]; + this.preferencesProviderAttributes = dom.byId("preferencesProviderAttributes") this.query = "rest/authenticationprovider/" + encodeURIComponent(authProviderObj.name); @@ -139,16 +164,46 @@ define(["dojo/_base/xhr", if (util.isProviderManagingUsers(that.authProviderData.type)) { - require(["qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager"], - function(PrincipalDatabaseAuthenticationManager) { - that.details = new PrincipalDatabaseAuthenticationManager(node, data[0], controller, that); - that.details.update(); - }); + that.details = new PrincipalDatabaseAuthenticationManager(node, that.authProviderData, controller); + that.details.update(that.authProviderData); + } + if (that.authProviderData.type == "Anonymous") + { + var authenticationProviderPanel = registry.byNode( query(".preferencesPanel", node)[0]); + domStyle.set(authenticationProviderPanel.domNode, "display","none"); + } + else + { + var preferencesProviderData = that.authProviderData.preferencesproviders? that.authProviderData.preferencesproviders[0]: null; + that.preferencesNode = query(".preferencesProviderDetails", node)[0]; + that.updatePreferencesProvider(preferencesProviderData); } }); } + AuthProviderUpdater.prototype.updatePreferencesProvider = function(preferencesProviderData) + { + if (preferencesProviderData) + { + this.addPreferencesProviderButton.style.display = 'none'; + if (!this.preferencesProvider) + { + this.preferencesProvider=new PreferencesProvider(preferencesProviderData.name, this.authProviderData); + this.preferencesProvider.init(this.preferencesNode); + } + this.preferencesProvider.update(preferencesProviderData); + } + else + { + if (this.preferencesProvider) + { + this.preferencesProvider.update(null); + } + this.addPreferencesProviderButton.style.display = 'inline'; + } + }; + AuthProviderUpdater.prototype.updateHeader = function() { this.authenticationProvider.name = this.authProviderData[ "name" ] @@ -159,8 +214,44 @@ define(["dojo/_base/xhr", AuthProviderUpdater.prototype.update = function() { + var that = this; - var that = this; + xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + that.authProviderData = data[0]; + that.name = data[0].name + util.flattenStatistics( that.authProviderData ); + that.updateHeader(); + if (that.details) + { + try + { + that.details.update(that.authProviderData); + } + catch(e) + { + if (console) + { + console.error(e); + } + } + } + var preferencesProviderData = that.authProviderData.preferencesproviders? that.authProviderData.preferencesproviders[0]: null; + if (preferencesProviderData) + { + try + { + that.updatePreferencesProvider(preferencesProviderData); + } + catch(e) + { + if (console) + { + console.error(e); + } + } + } + }); }; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js index f721ad6fa5..1bb0ca0afa 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Broker.js @@ -352,6 +352,12 @@ define(["dojo/_base/xhr", that.brokerUpdater.update(); + var logViewerButton = query(".logViewer", contentPane.containerNode)[0]; + registry.byNode(logViewerButton).on("click", function(evt){ + that.controller.show("logViewer", null, null); + }); + + var addProviderButton = query(".addAuthenticationProvider", contentPane.containerNode)[0]; connect.connect(registry.byNode(addProviderButton), "onClick", function(evt){ addAuthenticationProvider.show(); }); @@ -664,43 +670,6 @@ define(["dojo/_base/xhr", }, gridProperties, EnhancedGrid); that.displayACLWarnMessage(aclData); }); - - xhr.get({url: "rest/logrecords", sync: properties.useSyncGet, handleAs: "json"}) - .then(function(data) - { - that.logData = data; - - var gridProperties = { - height: 400, - plugins: { - pagination: { - pageSizes: ["10", "25", "50", "100"], - description: true, - sizeSwitch: true, - pageStepper: true, - gotoButton: true, - maxPageStep: 4, - position: "bottom" - } - }}; - - - that.logfileGrid = - new UpdatableStore(that.logData, query(".broker-logfile")[0], - [ { name: "Timestamp", field: "timestamp", width: "200px", - formatter: function(val) { - var d = new Date(0); - d.setUTCSeconds(val/1000); - - return d.toLocaleString(); - }}, - { name: "Level", field: "level", width: "60px"}, - { name: "Logger", field: "logger", width: "280px"}, - { name: "Thread", field: "thread", width: "120px"}, - { name: "Log Message", field: "message", width: "100%"} - - ], null, gridProperties, EnhancedGrid); - }); } BrokerUpdater.prototype.updateHeader = function() @@ -805,15 +774,6 @@ define(["dojo/_base/xhr", that.displayACLWarnMessage(data); } }); - - - xhr.get({url: "rest/logrecords", sync: properties.useSyncGet, handleAs: "json"}) - .then(function(data) - { - that.logData = data; - that.logfileGrid.update(that.logData); - }); - }; BrokerUpdater.prototype.showReadOnlyAttributes = function() diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js new file mode 100644 index 0000000000..735a657c61 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js @@ -0,0 +1,204 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define([ + "dojo/_base/declare", + "dojo/_base/xhr", + "dojo/_base/event", + "dojo/_base/connect", + "dojo/dom", + "dojo/dom-construct", + "dojo/parser", + "dojo/json", + "dojo/store/Memory", + "dojo/data/ObjectStore", + "dojox/html/entities", + "dijit/registry", + "qpid/common/TimeZoneSelector", + "dojo/text!../../showPreferences.html", + "qpid/common/util", + "dijit/Dialog", + "dijit/form/NumberSpinner", + "dijit/form/CheckBox", + "dijit/form/Textarea", + "dijit/form/FilteringSelect", + "dijit/form/TextBox", + "dijit/form/DropDownButton", + "dijit/form/Button", + "dijit/form/Form", + "dijit/layout/TabContainer", + "dijit/layout/ContentPane", + "dojox/grid/EnhancedGrid", + "dojox/validate/us", + "dojox/validate/web", + "dojo/domReady!"], +function (declare, xhr, event, connect, dom, domConstruct, parser, json, Memory, ObjectStore, entities, registry, TimeZoneSelector, markup, util) { + + var preferenceNames = ["timeZone", "updatePeriod", "saveTabs"]; + + return declare("qpid.management.Preferences", null, { + + preferencesDialog: null, + saveButton: null, + cancelButton: null, + + constructor: function() + { + var that = this; + + this.domNode = domConstruct.create("div", {innerHTML: markup}); + this.preferencesDialog = parser.parse(this.domNode)[0]; + + for(var i=0; i<preferenceNames.length; i++) + { + var name = preferenceNames[i]; + this[name] = registry.byId("preferences." + name); + } + + this.saveButton = registry.byId("preferences.saveButton"); + this.cancelButton = registry.byId("preferences.cancelButton"); + this.theForm = registry.byId("preferences.preferencesForm"); + this.users = registry.byId("preferences.users"); + this.users.set("structure", [ { name: "User", field: "name", width: "50%"}, + { name: "Authentication Provider", field: "authenticationProvider", width: "50%"}]); + this.cancelButton.on("click", function(){that.preferencesDialog.hide();}); + this.deletePreferencesButton = registry.byId("preferences.deletePreeferencesButton"); + this.deletePreferencesButton.on("click", function(){ + if (util.deleteGridSelections( + null, + that.users, + "rest/userpreferences", + "Are you sure you want to delete preferences for user", + "user")) + { + that._updateUsersWithPreferences(); + } + }); + var deletePreferencesButtonToggler = function(rowIndex){ + var data = that.users.selection.getSelected(); + that.deletePreferencesButton.set("disabled",!data.length ); + }; + connect.connect(this.users.selection, 'onSelected', deletePreferencesButtonToggler); + connect.connect(this.users.selection, 'onDeselected', deletePreferencesButtonToggler); + this.theForm.on("submit", function(e){ + event.stop(e); + if(that.theForm.validate()){ + var preferences = {}; + for(var i=0; i<preferenceNames.length; i++) + { + var name = preferenceNames[i]; + var preferenceWidget = that[name]; + if (preferenceWidget) + { + preferences[name] = preferenceWidget.get("value"); + } + } + xhr.post({ + url: "rest/preferences", + sync: true, + handleAs: "json", + headers: { "Content-Type": "application/json"}, + postData: json.stringify(preferences), + load: function(x) {that.success = true; }, + error: function(error) {that.success = false; that.failureReason = error;} + }); + if(that.success === true) + { + that.preferencesDialog.hide(); + } + else + { + alert("Error:" + that.failureReason); + } + } + return false; + }); + this.preferencesDialog.startup(); + }, + + showDialog: function(){ + var that = this; + xhr.get({ + url: "rest/preferences", + sync: true, + handleAs: "json", + load: function(data) { + that._updatePreferencesWidgets(data); + that._updateUsersWithPreferences(); + that.preferencesDialog.show(); + }, + error: function(error){ + alert("Cannot load user preferences : " + error); + } + }); + }, + + destroy: function() + { + if (this.preferencesDialog) + { + this.preferencesDialog.destroyRecursevly(); + this.preferencesDialog = null; + } + }, + + _updatePreferencesWidgets: function(data) + { + for(var i=0; i<preferenceNames.length; i++) + { + var preference = preferenceNames[i]; + if (this.hasOwnProperty(preference)) + { + var value = data ? data[preference] : null; + if (typeof value == "string") + { + value = entities.encode(String(value)) + } + this[preference].set("value", value); + } + } + }, + + _updateUsersWithPreferences: function() + { + var that = this; + xhr.get({ + url: "rest/userpreferences", + sync: false, + handleAs: "json" + }).then( + function(users) { + for(var i=0; i<users.length; i++) + { + users[i].id = users[i].authenticationProvider + "/" + users[i].name; + } + var usersStore = new Memory({data: users, idProperty: "id"}); + var usersDataStore = new ObjectStore({objectStore: usersStore}); + if (that.users.store) + { + that.users.store.close(); + } + that.users.set("store", usersDataStore); + that.users._refresh(); + }); + } + + }); +});
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/PreferencesProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/PreferencesProvider.js new file mode 100644 index 0000000000..c8e6f9845c --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/PreferencesProvider.js @@ -0,0 +1,179 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dojo/_base/connect", + "qpid/common/properties", + "qpid/common/updater", + "qpid/common/util", + "dojo/_base/event", + "dijit/registry", + "dojo/dom-style", + "dojox/html/entities", + "qpid/management/addPreferencesProvider", + "dojo/domReady!"], + function (xhr, parser, query, connect, properties, updater, util, event, registry, domStyle, entities, addPreferencesProvider) { + + function PreferencesProvider(name, parent, controller) { + this.name = name; + this.controller = controller; + this.modelObj = { type: "preferencesprovider", name: name }; + this.authenticationProviderName = parent.name; + if(parent) { + this.modelObj.parent = {}; + this.modelObj.parent[parent.type] = parent; + } + } + + PreferencesProvider.prototype.getTitle = function() { + return "PreferencesProvider:" + this.authenticationProviderName + "/" + this.name ; + }; + + PreferencesProvider.prototype.init = function(node) { + var that = this; + xhr.get({url: "showPreferencesProvider.html", + sync: true, + load: function(data) { + node.innerHTML = data; + parser.parse(node); + + that.preferencesProviderType=query(".preferencesProviderType", node)[0]; + that.preferencesProviderName=query(".preferencesProviderName", node)[0]; + that.preferencesProviderState=query(".preferencesProviderState", node)[0]; + that.editPreferencesProviderButton = query(".editPreferencesProviderButton", node)[0]; + that.deletePreferencesProviderButton = query(".deletePreferencesProviderButton", node)[0]; + that.preferencesProviderAttributes = query(".preferencesProviderAttributes", node)[0]; + that.preferencesDetailsDiv = query(".preferencesDetails", node)[0]; + var editPreferencesProviderWidget = registry.byNode(that.editPreferencesProviderButton); + editPreferencesProviderWidget.on("click", function(evt){ event.stop(evt); that.editPreferencesProvider();}); + var deletePreferencesProviderWidget = registry.byNode(that.deletePreferencesProviderButton); + deletePreferencesProviderWidget.on("click", function(evt){ event.stop(evt); that.deletePreferencesProvider();}); + }}); + this.reload(); + }; + + PreferencesProvider.prototype.open = function(contentPane) { + this.contentPane = contentPane; + this.init(contentPane.containerNode); + this.updater = new PreferencesProviderUpdater(this); + updater.add(this.updater); + }; + + PreferencesProvider.prototype.close = function() { + if (this.updater) + { + updater.remove( this.updater); + } + }; + + PreferencesProvider.prototype.deletePreferencesProvider = function() { + if (this.preferencesProviderData){ + var preferencesProviderData = this.preferencesProviderData; + if(confirm("Are you sure you want to delete preferences provider '" + preferencesProviderData.name + "'?")) { + var query = "rest/preferencesprovider/" + encodeURIComponent(this.authenticationProviderName) + "/" + encodeURIComponent(preferencesProviderData.name); + this.success = true + var that = this; + xhr.del({url: query, sync: true, handleAs: "json"}).then( + function(data) { + that.update(null); + + // if opened in tab + if (that.contentPane) + { + that.close(); + that.contentPane.onClose() + that.controller.tabContainer.removeChild(that.contentPane); + that.contentPane.destroyRecursive(); + } + }, + function(error) {that.success = false; that.failureReason = error;}); + if(!this.success ) { + alert("Error:" + this.failureReason); + } + } + } + }; + + PreferencesProvider.prototype.editPreferencesProvider = function() { + if (this.preferencesProviderData){ + addPreferencesProvider.show(this.authenticationProviderName, this.name); + } + }; + + PreferencesProvider.prototype.update = function(data) { + this.preferencesProviderData = data; + if (data) + { + this.name = data.name; + this.preferencesProviderAttributes.style.display = 'block'; + this.editPreferencesProviderButton.style.display = 'inline'; + this.deletePreferencesProviderButton.style.display = 'inline'; + this.preferencesProviderType.innerHTML = entities.encode(String(data.type)); + this.preferencesProviderName.innerHTML = entities.encode(String(data.name)); + this.preferencesProviderState.innerHTML = entities.encode(String(data.state)); + if (!this.details) + { + var that = this; + require(["qpid/management/authenticationprovider/preferences/" + data.type.toLowerCase() + "/show"], + function(PreferencesProviderDetails) { + that.details = new PreferencesProviderDetails(that.preferencesDetailsDiv); + that.details.update(data); + }); + } + else + { + this.details.update(data); + } + } + else + { + this.editPreferencesProviderButton.style.display = 'none'; + this.deletePreferencesProviderButton.style.display = 'none'; + this.preferencesProviderAttributes.style.display = 'none'; + this.details = null; + } + }; + + PreferencesProvider.prototype.reload = function() + { + var query = "rest/preferencesprovider/" + encodeURIComponent(this.authenticationProviderName) + "/" + encodeURIComponent(this.name); + var that = this; + xhr.get({url: query, sync: properties.useSyncGet, handleAs: "json"}) + .then(function(data) { + var preferencesProviderData = data[0]; + util.flattenStatistics( preferencesProviderData ); + that.update(preferencesProviderData); + }); + }; + + function PreferencesProviderUpdater(preferencesProvider) + { + this.preferencesProvider = preferencesProvider; + }; + + PreferencesProviderUpdater.prototype.update = function() + { + this.preferencesProvider.reload(); + }; + + return PreferencesProvider; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js index d2891c7d3b..3737e41da4 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addAuthenticationProvider.js @@ -31,6 +31,7 @@ define(["dojo/_base/xhr", "dijit/form/FilteringSelect", "dojo/_base/connect", "dojo/dom-style", + "qpid/management/addPreferencesProvider", /* dojox/ validate resources */ "dojox/validate/us", "dojox/validate/web", /* basic dijit classes */ @@ -44,7 +45,7 @@ define(["dojo/_base/xhr", "dojox/form/BusyButton", "dojox/form/CheckedMultiSelect", "dojox/layout/TableContainer", "dojo/domReady!"], - function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, FilteringSelect, connect, domStyle) { + function (xhr, dom, construct, win, registry, parser, array, event, json, Memory, FilteringSelect, connect, domStyle, addPreferencesProvider) { var addAuthenticationProvider = {}; @@ -163,6 +164,10 @@ define(["dojo/_base/xhr", if(this.success === true) { registry.byId("addAuthenticationProvider").hide(); + if (newAuthenticationManager.type != "Anonymous" && dojo.byId("formAddAuthenticationProvider.id").value == "") + { + addPreferencesProvider.show(newAuthenticationManager.name); + } } else { diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPreferencesProvider.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPreferencesProvider.js new file mode 100644 index 0000000000..818dc32366 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPreferencesProvider.js @@ -0,0 +1,198 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/dom-construct", + "dojo/query", + "dojo/_base/window", + "dijit/registry", + "dojo/parser", + "dojo/_base/array", + "dojo/_base/event", + 'dojo/_base/json', + "dojo/store/Memory", + "dijit/form/FilteringSelect", + "dojo/_base/connect", + "dojo/dom-style", + "dojo/string", + "dojox/html/entities", + "dojox/validate/us", + "dojox/validate/web", + "dijit/Dialog", + "dijit/form/CheckBox", + "dijit/form/Textarea", + "dijit/form/TextBox", + "dijit/form/ValidationTextBox", + "dijit/form/Button", + "dijit/form/Form", + "dojox/form/BusyButton", + "dojox/form/CheckedMultiSelect", + "dojox/layout/TableContainer", + "dojo/domReady!"], + function (xhr, dom, construct, query, win, registry, parser, array, event, json, Memory, FilteringSelect, connect, domStyle, string, entities) { + + var addPreferencesProvider = {}; + + var node = construct.create("div", null, win.body(), "last"); + + var convertToPreferencesProvider = function convertToPreferencesProvider(formValues) + { + var newProvider = {}; + + newProvider.name = dijit.byId("preferencesProvider.name").value; + newProvider.type = dijit.byId("preferencesProvider.type").value; + var id = dojo.byId("preferencesProvider.id").value; + if (id) + { + newProvider.id = id; + } + for(var propName in formValues) + { + if(formValues.hasOwnProperty(propName)) + { + if(formValues[ propName ] !== "") { + newProvider[ propName ] = formValues[propName]; + } + + } + } + return newProvider; + } + + var selectPreferencesProviderType = function(type) { + if(type && string.trim(type) != "") + { + require(["qpid/management/authenticationprovider/preferences/" + type.toLowerCase() + "/add"], + function(addType) + { + addType.show(dom.byId("preferencesProvider.fieldsContainer"), addPreferencesProvider.data) + }); + } + } + + xhr.get({url: "addPreferencesProvider.html", + sync: true, + load: function(data) { + node.innerHTML = data; + addPreferencesProvider.dialogNode = dom.byId("addPreferencesProvider"); + parser.instantiate([addPreferencesProvider.dialogNode]); + + var cancelButton = registry.byId("addPreferencesProvider.cancelButton"); + cancelButton.on("click", function(){ + registry.byId("addPreferencesProvider").hide(); + }); + var theForm = registry.byId("formAddPreferencesProvider"); + theForm.on("submit", function(e) { + + event.stop(e); + if(theForm.validate()){ + var newProvider = convertToPreferencesProvider(theForm.getValues()); + var that = this; + var nameWidget = registry.byId("preferencesProvider.name") + xhr.put({url: "rest/preferencesprovider/" +encodeURIComponent(addPreferencesProvider.authenticationProviderName) + "/" + encodeURIComponent(nameWidget.value), + sync: true, handleAs: "json", + headers: { "Content-Type": "application/json"}, + putData: json.toJson(newProvider), + load: function(x) {that.success = true; }, + error: function(error) {that.success = false; that.failureReason = error;}}); + if(this.success === true) + { + registry.byId("addPreferencesProvider").hide(); + } + else + { + alert("Error:" + this.failureReason); + } + return false; + }else{ + alert('Form contains invalid data. Please correct first'); + return false; + } + }); + xhr.get({ + sync: true, + url: "rest/helper?action=ListPreferencesProvidersTypes", + handleAs: "json" + }).then( + function(data) { + var preferencesProvidersTypes = data; + var storeData = []; + for (var i =0 ; i < preferencesProvidersTypes.length; i++) + { + storeData[i]= {id: preferencesProvidersTypes[i], name: preferencesProvidersTypes[i]}; + } + var store = new Memory({ data: storeData }); + var preferencesProviderTypesDiv = dom.byId("addPreferencesProvider.selectPreferencesProviderDiv"); + var input = construct.create("input", {id: "preferencesProviderType", required: true}, preferencesProviderTypesDiv); + addPreferencesProvider.preferencesProviderTypeChooser = new FilteringSelect({ id: "preferencesProvider.type", + name: "type", + store: store, + searchAttr: "name", + required: true, + onChange: selectPreferencesProviderType }, input); + addPreferencesProvider.preferencesProviderTypeChooser.startup(); + }); + }}); + + addPreferencesProvider.show = function(authenticationProviderName, providerName) { + this.authenticationProviderName = authenticationProviderName; + this.data = null; + var that = this; + var theForm = registry.byId("formAddPreferencesProvider"); + theForm.reset(); + dojo.byId("preferencesProvider.id").value=""; + var nameWidget = registry.byId("preferencesProvider.name"); + nameWidget.set("disabled", false); + registry.byId("preferencesProvider.type").set("disabled", false); + if (this.preferencesProviderTypeChooser) + { + this.preferencesProviderTypeChooser.set("disabled", false); + this.preferencesProviderTypeChooser.set("value", null); + } + var dialog = registry.byId("addPreferencesProvider"); + dialog.set("title", (providerName ? "Edit preference provider '" + entities.encode(String(providerName)) + "' " : "Add preferences provider ") + " for authentication provider '" + entities.encode(String(authenticationProviderName)) + "' ") + if (providerName) + { + xhr.get({ + url: "rest/preferencesprovider/" +encodeURIComponent(authenticationProviderName) + "/" + encodeURIComponent(providerName), + sync: false, + handleAs: "json" + }).then( + function(data) { + var provider = data[0]; + var providerType = provider.type; + that.data = provider; + nameWidget.set("value", entities.encode(String(provider.name))); + nameWidget.set("disabled", true); + that.preferencesProviderTypeChooser.set("value", providerType); + that.preferencesProviderTypeChooser.set("disabled", true); + dojo.byId("preferencesProvider.id").value=provider.id; + dialog.show(); + }); + } + else + { + dialog.show(); + } + } + + return addPreferencesProvider; + });
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js index 0a607c71d4..09433b196d 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/PrincipalDatabaseAuthenticationManager.js @@ -30,7 +30,6 @@ define(["dojo/_base/xhr", "dijit/registry", "qpid/common/util", "qpid/common/properties", - "qpid/common/updater", "qpid/common/UpdatableStore", "dojox/grid/EnhancedGrid", "dojox/grid/enhanced/plugins/Pagination", @@ -43,8 +42,8 @@ define(["dojo/_base/xhr", "dijit/form/Form", "dijit/form/DateTextBox", "dojo/domReady!"], - function (xhr, dom, parser, query, construct, connect, win, event, json, registry, util, properties, updater, UpdatableStore, EnhancedGrid) { - function DatabaseAuthManager(containerNode, authProviderObj, controller, authenticationManagerUpdater) { + function (xhr, dom, parser, query, construct, connect, win, event, json, registry, util, properties, UpdatableStore, EnhancedGrid) { + function DatabaseAuthManager(containerNode, authProviderObj, controller) { var node = construct.create("div", null, containerNode, "last"); var that = this; this.name = authProviderObj.name; @@ -53,14 +52,7 @@ define(["dojo/_base/xhr", load: function(data) { node.innerHTML = data; parser.parse(node); - - - that.authDatabaseUpdater= new AuthProviderUpdater(node, authProviderObj, controller, authenticationManagerUpdater); - updater.add( that.authDatabaseUpdater); - - that.authDatabaseUpdater.update(); - - + that.init(node, authProviderObj, controller); }}); } @@ -72,19 +64,12 @@ define(["dojo/_base/xhr", updater.remove( this.authDatabaseUpdater ); }; - function AuthProviderUpdater(node, authProviderObj, controller, authenticationManagerUpdater) + DatabaseAuthManager.prototype.init = function(node, authProviderObj, controller) { this.controller = controller; - this.query = "rest/authenticationprovider?id="+encodeURIComponent(authProviderObj.id); - this.name = authProviderObj.name; - this.authenticationManagerUpdater = authenticationManagerUpdater; var that = this; - xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) - .then(function(data) { - that.authProviderData = data[0]; - that.name = data[0].name - util.flattenStatistics( that.authProviderData ); + that.authProviderData = authProviderObj; var userDiv = query(".users")[0]; @@ -131,10 +116,9 @@ define(["dojo/_base/xhr", event.stop(evt); that.deleteUsers(); }); - }); } - AuthProviderUpdater.prototype.deleteUsers = function() + DatabaseAuthManager.prototype.deleteUsers = function() { var grid = this.usersGrid.grid; var data = grid.selection.getSelected(); @@ -168,24 +152,11 @@ define(["dojo/_base/xhr", } }; - AuthProviderUpdater.prototype.update = function() + DatabaseAuthManager.prototype.update = function(data) { - - var that = this; - - xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}) - .then(function(data) { - that.authProviderData = data[0]; - that.name = data[0].name - util.flattenStatistics( that.authProviderData ); - - that.usersGrid.update(that.authProviderData.users); - - that.authenticationManagerUpdater.authProviderData = data[0]; - that.authenticationManagerUpdater.updateHeader(); - }); - - + this.authProviderData = data; + this.name = data.name + this.usersGrid.update(this.authProviderData.users); }; var addUser = {}; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/preferences/filesystempreferences/add.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/preferences/filesystempreferences/add.js new file mode 100644 index 0000000000..80b50fbbb8 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/preferences/filesystempreferences/add.js @@ -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. + * + */ +define(["dojo/_base/xhr", + "dojo/dom", + "dojo/dom-construct", + "dojo/_base/window", + "dijit/registry", + "dojo/parser", + "dojo/_base/array", + "dojo/_base/event", + "dojo/_base/json", + "dojo/string", + "dojox/html/entities", + "dojo/text!../../../../../authenticationprovider/preferences/filesystempreferences/add.html", + "dojo/domReady!"], + function (xhr, dom, domConstruct, win, registry, parser, array, event, json, string, entities, template) { + return { + show: function(node, data) { + dojo.forEach(dijit.findWidgets(node), function(w) { + w.destroyRecursive(); + }); + node.innerHTML = template; + parser.parse(node); + var pathWidget = registry.byId("preferencesProvider.path") + if (data) + { + pathWidget.set("value", entities.encode(String(data["path"]))); + } + } + }; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/preferences/filesystempreferences/show.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/preferences/filesystempreferences/show.js new file mode 100644 index 0000000000..7521f820b9 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/preferences/filesystempreferences/show.js @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/string", + "dojox/html/entities", + "dojo/query", + "dojo/domReady!"], + function (xhr, parser, json, entities, query) { + + function FileSystemPreferences(containerNode) { + var that = this; + xhr.get({url: "authenticationprovider/preferences/filesystempreferences/show.html", + sync: true, + load: function(template) { + containerNode.innerHTML = template; + parser.parse(containerNode); + that.preferencesProviderPath=query(".fileSystemPreferencesProviderPath", containerNode)[0]; + }}); + } + + FileSystemPreferences.prototype.update=function(data) + { + this.preferencesProviderPath.innerHTML = entities.encode(String(data["path"])); + }; + + return FileSystemPreferences; +}); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js index b7eddbbb77..e8d7bdd9cf 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/controller.js @@ -35,10 +35,12 @@ define(["dojo/dom", "qpid/management/AccessControlProvider", "qpid/management/Port", "qpid/management/Plugin", + "qpid/management/logs/LogViewer", + "qpid/management/PreferencesProvider", "dojo/ready", "dojo/domReady!"], function (dom, registry, ContentPane, entities, Broker, VirtualHost, Exchange, Queue, Connection, AuthProvider, - GroupProvider, Group, KeyStore, TrustStore, AccessControlProvider, Port, Plugin, ready) { + GroupProvider, Group, KeyStore, TrustStore, AccessControlProvider, Port, Plugin, LogViewer, PreferencesProvider, ready) { var controller = {}; var constructors = { broker: Broker, virtualhost: VirtualHost, exchange: Exchange, @@ -46,7 +48,7 @@ define(["dojo/dom", authenticationprovider: AuthProvider, groupprovider: GroupProvider, group: Group, keystore: KeyStore, truststore: TrustStore, accesscontrolprovider: AccessControlProvider, port: Port, - plugin: Plugin}; + plugin: Plugin, logViewer: LogViewer, preferencesprovider: PreferencesProvider}; var tabDiv = dom.byId("managedViews"); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogFileDownloadDialog.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogFileDownloadDialog.js new file mode 100644 index 0000000000..c25fd7c609 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogFileDownloadDialog.js @@ -0,0 +1,175 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define([ + "dojo/_base/declare", + "dojo/_base/event", + "dojo/_base/xhr", + "dojo/_base/connect", + "dojo/dom-construct", + "dojo/query", + "dojo/parser", + "dojo/store/Memory", + "dojo/data/ObjectStore", + "dojo/date/locale", + "dojo/number", + "dijit/registry", + "dijit/Dialog", + "dijit/form/Button", + "dojox/grid/EnhancedGrid", + "dojo/text!../../../logs/showLogFileDownloadDialog.html", + "dojo/domReady!" +], function(declare, event, xhr, connect, domConstruct, query, parser, Memory, ObjectStore, locale, number, + registry, Dialog, Button, EnhancedGrid, template){ + + +return declare("qpid.management.logs.LogFileDownloadDialog", null, { + + templateString: template, + containerNode: null, + widgetsInTemplate: true, + logFileDialog: null, + logFilesGrid: null, + downloadLogsButton: null, + closeButton: null, + + constructor: function(args){ + this.containerNode = domConstruct.create("div", {innerHTML: template}); + parser.parse(this.containerNode); + + this.logFileTreeDiv = query(".logFilesGrid", this.containerNode)[0]; + this.downloadLogsButton = registry.byNode(query(".downloadLogsButton", this.containerNode)[0]); + this.closeButton = registry.byNode(query(".downloadLogsDialogCloseButton", this.containerNode)[0]); + + var self = this; + this.closeButton.on("click", function(e){self._onCloseButtonClick(e);}); + this.downloadLogsButton.on("click", function(e){self._onDownloadButtonClick(e);}); + this.downloadLogsButton.set("disabled", true) + + this.logFileDialog = new Dialog({ + title:"Broker Log Files", + style: "width: 600px", + content: this.containerNode + }); + + var layout = [ + { name: "Appender", field: "appenderName", width: "auto"}, + { name: "Name", field: "name", width: "auto"}, + { name: "Size", field: "size", width: "60px", + formatter: function(val){ + return val > 1024 ? (val > 1048576? number.round(val/1048576) + "MB": number.round(val/1024) + "KB") : val + "bytes"; + } + }, + { name: "Last Modified", field: "lastModified", width: "250px", + formatter: function(val) { + var d = new Date(val); + return locale.format(d, {selector:"date", datePattern: "EEE, MMM d yy, HH:mm:ss z (ZZZZ)"}); + } + } + ]; + + var gridProperties = { + store: new ObjectStore({objectStore: new Memory({data: [], idProperty: "id"}) }), + structure: layout, + autoHeight: true, + plugins: { + pagination: { + pageSizes: [10, 25, 50, 100], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: "bottom" + }, + indirectSelection: { + headerSelector:true, + width:"20px", + styles:"text-align: center;" + } + } + }; + + this.logFilesGrid = new EnhancedGrid(gridProperties, this.logFileTreeDiv); + var self = this; + var downloadButtonToggler = function(rowIndex){ + var data = self.logFilesGrid.selection.getSelected(); + self.downloadLogsButton.set("disabled",!data.length ); + }; + connect.connect(this.logFilesGrid.selection, 'onSelected', downloadButtonToggler); + connect.connect(this.logFilesGrid.selection, 'onDeselected', downloadButtonToggler); + }, + + _onCloseButtonClick: function(evt){ + event.stop(evt); + this.logFileDialog.hide(); + }, + + _onDownloadButtonClick: function(evt){ + event.stop(evt); + var data = this.logFilesGrid.selection.getSelected(); + if (data.length) + { + var query = ""; + for(var i = 0 ; i< data.length; i++) + { + if (i>0) + { + query+="&"; + } + query+="l="+encodeURIComponent(data[i].appenderName +'/' + data[i].name); + } + window.location="rest/logfile?" + query; + this.logFileDialog.hide(); + } + }, + + destroy: function(){ + this.inherited(arguments); + if (this.logFileDialog) + { + this.logFileDialog.destroyRecursive(); + this.logFileDialog = null; + } + }, + + showDialog: function(){ + var self = this; + var requestArguments = {url: "rest/logfiles", sync: true, handleAs: "json"}; + xhr.get(requestArguments).then(function(data){ + try + { + self.logFilesGrid.store.objectStore.setData(data); + self.logFilesGrid.startup(); + self.logFileDialog.startup(); + self.logFileDialog.show(); + self.logFilesGrid._refresh(); + + } + catch(e) + { + console.error(e); + } + }); + } + + }); + +}); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogViewer.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogViewer.js new file mode 100644 index 0000000000..56b37d0167 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/logs/LogViewer.js @@ -0,0 +1,199 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +define(["dojo/_base/xhr", + "dojo/parser", + "dojo/query", + "dojo/date/locale", + "dijit/registry", + "qpid/common/grid/GridUpdater", + "qpid/common/grid/UpdatableGrid", + "qpid/management/logs/LogFileDownloadDialog", + "dojo/text!../../../logs/showLogViewer.html", + "dojo/domReady!"], + function (xhr, parser, query, locale, registry, GridUpdater, UpdatableGrid, LogFileDownloadDialog, markup) { + + var defaulGridRowLimit = 4096; + + function LogViewer(name, parent, controller) { + var self = this; + + this.name = name; + this.lastLogId = 0; + this.contentPane = null; + this.downloadLogsButton = null; + this.downloadLogDialog = null; + } + + LogViewer.prototype.getTitle = function() { + return "Log Viewer"; + }; + + LogViewer.prototype.open = function(contentPane) { + var self = this; + this.contentPane = contentPane; + this.contentPane.containerNode.innerHTML = markup; + + parser.parse(this.contentPane.containerNode); + + this.downloadLogsButton = registry.byNode(query(".downloadLogs", contentPane.containerNode)[0]); + this.downloadLogDialog = new LogFileDownloadDialog(); + + this.downloadLogsButton.on("click", function(evt){ + self.downloadLogDialog.showDialog(); + }); + this._buildGrid(); + }; + + LogViewer.prototype._buildGrid = function() { + var self = this; + + var gridStructure = [ + { + hidden: true, + name: "ID", + field: "id", + width: "50px", + datatype: "number", + filterable: true + }, + { + name: "Date", field: "timestamp", width: "100px", datatype: "date", + formatter: function(val) { + var d = new Date(0); + d.setUTCSeconds(val/1000); + return locale.format(d, {selector:"date", datePattern: "EEE, MMM d yy"}); + }, + dataTypeArgs: { + selector: "date", + datePattern: "EEE MMMM d yyy" + } + }, + { name: "Time", field: "timestamp", width: "150px", datatype: "time", + formatter: function(val) { + var d = new Date(0); + d.setUTCSeconds(val/1000); + return locale.format(d, {selector:"time", timePattern: "HH:mm:ss z (ZZZZ)"}); + }, + dataTypeArgs: { + selector: "time", + timePattern: "HH:mm:ss ZZZZ" + } + }, + { name: "Level", field: "level", width: "50px", datatype: "string", autoComplete: true, hidden: true}, + { name: "Logger", field: "logger", width: "150px", datatype: "string", autoComplete: false, hidden: true}, + { name: "Thread", field: "thread", width: "100px", datatype: "string", hidden: true}, + { name: "Log Message", field: "message", width: "auto", datatype: "string"} + ]; + + var gridNode = query("#broker-logfile", this.contentPane.containerNode)[0]; + try + { + var updater = new GridUpdater({ + updatable: false, + serviceUrl: function() + { + return "rest/logrecords?lastLogId=" + self.lastLogId; + }, + onUpdate: function(items) + { + if (items) + { + var maxId = -1; + for(var i in items) + { + var item = items[i]; + if (item.id > maxId) + { + maxId = item.id + } + } + if (maxId != -1) + { + self.lastLogId = maxId + } + } + }, + append: true, + appendLimit: defaulGridRowLimit + }); + this.grid = new UpdatableGrid(updater.buildUpdatableGridArguments({ + structure: gridStructure, + selectable: true, + selectionMode: "none", + sortInfo: -1, + sortFields: [{attribute: 'timestamp', descending: true}], + plugins:{ + nestedSorting:true, + enhancedFilter:{defaulGridRowLimit: defaulGridRowLimit}, + indirectSelection: false + } + }), gridNode); + var onStyleRow = function(row) + { + var item = self.grid.getItem(row.index); + if(item){ + var level = self.grid.store.getValue(item, "level", null); + var changed = false; + if(level == "ERROR"){ + row.customClasses += " redBackground"; + changed = true; + } else if(level == "WARN"){ + row.customClasses += " yellowBackground"; + changed = true; + } else if(level == "DEBUG"){ + row.customClasses += " grayBackground"; + changed = true; + } + if (changed) + { + self.grid.focus.styleRow(row); + } + } + }; + this.grid.on("styleRow", onStyleRow); + this.grid.startup(); + } + catch(err) + { + console.error(err); + } + }; + + LogViewer.prototype.close = function() { + if (this.grid) + { + this.grid.destroy(); + this.grid = null; + } + if (this.downloadLogDialog) + { + this.downloadLogDialog.destroy(); + this.downloadLogDialog = null; + } + if (this.downloadLogsButton) + { + this.downloadLogsButton.destroy(); + this.downloadLogsButton = null; + } + }; + + return LogViewer; + }); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js index b1ccc0ca07..59822ec535 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js @@ -37,15 +37,10 @@ define(["dojo/_base/xhr", return typeof val === 'string' ? entities.encode(val) : val; } + var populatedFields = []; var showMessage = {}; showMessage.hide = function () { - if(this.populatedFields) { - for(var i = 0 ; i < this.populatedFields.length; i++) { - this.populatedFields[i].innerHTML = ""; - } - this.populatedFields = []; - } registry.byId("showMessage").hide(); }; @@ -65,16 +60,22 @@ define(["dojo/_base/xhr", showMessage.populateShowMessage = function(data) { - this.populatedFields = []; + // clear fields set by previous invocation. + if(populatedFields) { + for(var i = 0 ; i < populatedFields.length; i++) { + populatedFields[i].innerHTML = ""; + } + populatedFields = []; + } for(var attrName in data) { if(data.hasOwnProperty(attrName)) { var fields = query(".message-"+attrName, this.dialogNode); if(fields && fields.length != 0) { var field = fields[0]; - this.populatedFields.push(field); + populatedFields.push(field); var val = data[attrName]; - if(val) { + if(val != null) { if(domClass.contains(field,"map")) { var tableStr = "<table style='border: 1pt'><tr><th style='width: 6em; font-weight: bold'>Header</th><th style='font-weight: bold'>Value</th></tr>"; for(var name in val) { @@ -112,7 +113,7 @@ define(["dojo/_base/xhr", + "/" + encodeURIComponent(showMessage.messageNumber) + "\" target=\"_blank\">Download</a>"; } - this.populatedFields.push(contentField); + populatedFields.push(contentField); registry.byId("showMessage").show(); }; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js index 8dc336b347..8770509c27 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/treeView.js @@ -284,6 +284,8 @@ define(["dojo/_base/xhr", controller.show("accesscontrolprovider", details.accesscontrolprovider, {broker: {type:"broker", name:""}}); } else if (details.type == 'plugin') { controller.show("plugin", details.plugin, {broker: {type:"broker", name:""}}); + } else if (details.type == "preferencesprovider") { + controller.show("preferencesprovider", details.preferencesprovider, { type: "authenticationprovider", name: details.authenticationprovider, parent: {broker: {type:"broker", name:""}}}); } }; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/logs/showLogFileDownloadDialog.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/logs/showLogFileDownloadDialog.html new file mode 100644 index 0000000000..bc633d059a --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/logs/showLogFileDownloadDialog.html @@ -0,0 +1,33 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> +<div> + <div class="contentArea" style="height:320px;overflow:auto"> + <div><b>Select log files to download</b></div> + <div class="logFilesGrid" style='height:300px;width: 580px'></div> + </div> + <div class="dijitDialogPaneActionBar"> + <button value="Download" data-dojo-type="dijit.form.Button" + class="downloadLogsButton" + data-dojo-props="iconClass: 'downloadLogsIcon', label: 'Download' "></button> + <button value="Close" data-dojo-type="dijit.form.Button" data-dojo-props="label: 'Close'" + class="downloadLogsDialogCloseButton"></button> + </div> +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/logs/showLogViewer.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/logs/showLogViewer.html new file mode 100644 index 0000000000..10ac09a406 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/logs/showLogViewer.html @@ -0,0 +1,29 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> +<div class="logViewer"> + + <div id="broker-logfile"></div> + <br/> + <button data-dojo-type="dijit.form.Button" class="downloadLogs" + data-dojo-props="iconClass: 'downloadLogsIcon', title:'Download Log Files', name: 'downloadLogs'">Download</button> + <br/> +</div> + diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html index 5e876fdc1f..aabaee1e9d 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showAuthProvider.html @@ -27,4 +27,11 @@ <br/> <button data-dojo-type="dijit.form.Button" class="editAuthenticationProviderButton">Edit</button> <button data-dojo-type="dijit.form.Button" class="deleteAuthenticationProviderButton">Delete</button> + <br/> + <br/> + <div class="preferencesPanel" data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Preferences Provider', open: true"> + <div class="preferencesProviderDetails"></div> + <button data-dojo-type="dijit.form.Button" class="addPreferencesProviderButton">Add</button> + </div> + <br/> </div>
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html index d9991452af..366ef27c8a 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showBroker.html @@ -190,9 +190,7 @@ <button data-dojo-type="dijit.form.Button" class="deleteAccessControlProvider">Delete Access Control Provider</button> </div> <br/> - <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Log File', open: false"> - <div class="broker-logfile"></div> - </div> - <br/> + <button data-dojo-type="dijit.form.Button" class="logViewer" data-dojo-props="iconClass: 'logViewerIcon'">Log Viewer</button> + <br/><br/> </div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showMessage.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showMessage.html index 0dea508c60..9a6ec55686 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showMessage.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showMessage.html @@ -45,7 +45,7 @@ </tr> <tr style="margin-bottom: 4pt"> <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Expiration:</span></td> - <td><span class="message-expiration datetime"></span></td> + <td><span class="message-expirationTime datetime"></span></td> </tr> <tr style="margin-bottom: 4pt"> <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">MIME Type:</span></td> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showPreferences.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showPreferences.html new file mode 100644 index 0000000000..ede111272a --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showPreferences.html @@ -0,0 +1,83 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> +<div data-dojo-type="dijit/Dialog" data-dojo-props="title:'Preferences'" id="preferences.preferencesDialog"> + <div data-dojo-type="dijit/layout/TabContainer" style="width: 600px; height: 400px"> + <div data-dojo-type="dijit/layout/ContentPane" title="Own Preferences" data-dojo-props="selected:true" id="preferences.preferencesTab"> + <form method="post" data-dojo-type="dijit/form/Form" id="preferences.preferencesForm"> + <table cellpadding="0" cellspacing="2" style="overflow: auto; height: 300px;"> + <tr> + <td><strong>Time zone: </strong></td> + <td> + <span id="preferences.timeZone" data-dojo-type="qpid/common/TimeZoneSelector" data-dojo-props="name: 'timeZone'"></span> + </td> + </tr> + <tr> + <td><strong>Update period:</strong></td> + <td><input id="preferences.updatePeriod" name="updatePeriod" data-dojo-type="dijit/form/NumberSpinner" data-dojo-props=" + invalidMessage: 'Invalid value', + required: false, + smallDelta: 1, + value: 5, + constraints: {min:1,max:65535,places:0, pattern: '#####'}, + "/> + </td> + </tr> + <tr> + <td><strong>Save tabs:</strong></td> + <td><input id="preferences.saveTabs" type="checkbox" data-dojo-type="dijit/form/CheckBox" name="saveTabs"/></td> + </tr> + </table> + <div class="dijitDialogPaneActionBar"> + <input type="submit" value="Save Preferences" data-dojo-type="dijit/form/Button" data-dojo-props="label: 'Save Preferences'" id="preferences.saveButton"/> + <button value="Cancel" data-dojo-type="dijit/form/Button" data-dojo-props="label: 'Cancel'" id="preferences.cancelButton"></button> + </div> + </form> + </div> + <div data-dojo-type="dijit/layout/ContentPane" title="Users with Preferences" id="preferences.usersTab"> + <table id="preferences.users" data-dojo-type="dojox/grid/EnhancedGrid" data-dojo-props=" + label:'Trust Stores:', + plugins:{ + indirectSelection: true, + pagination: { + pageSizes: [10, 25, 50, 100], + description: true, + sizeSwitch: true, + pageStepper: true, + gotoButton: true, + maxPageStep: 4, + position: 'bottom' + } + }, + rowSelector:'0px' + " style="height: 300px;"> + <thead> + <tr> + <th field="name" style="width:50%">User</th> + <th field="authenticationProvider" style="width:50%">Authentication Provider</th> + </tr> + </thead> + </table> + <div class="dijitDialogPaneActionBar"> + <button id="preferences.deletePreeferencesButton" data-dojo-type="dijit/form/Button" data-dojo-props="label:'Delete Preferences', title:'Delete preferences for selected users'">Delete Preferences</button> + </div> + </div> + </div> +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showPreferencesProvider.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showPreferencesProvider.html new file mode 100644 index 0000000000..a1885acddf --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showPreferencesProvider.html @@ -0,0 +1,40 @@ +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> + <div class="preferencesProvider"> + <div class="preferencesProviderAttributes"> + <div style="clear:both"> + <div class="formLabel-labelCell" style="float:left; width: 100px;">Type:</div> + <div class="preferencesProviderType" style="float:left;"></div> + </div> + <div style="clear:both"> + <div class="formLabel-labelCell" style="float:left; width: 100px;">Name:</div> + <div class="preferencesProviderName" style="float:left;"></div> + </div> + <div style="clear:both"> + <div class="formLabel-labelCell" style="float:left; width: 100px;">State:</div> + <div class="preferencesProviderState" style="float:left;"></div> + </div> + <div class="preferencesDetails"></div> + </div> + <br/> + <button data-dojo-type="dijit.form.Button" class="deletePreferencesProviderButton">Delete</button> + <button data-dojo-type="dijit.form.Button" class="editPreferencesProviderButton">Edit</button> +</div>
\ No newline at end of file diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java index 18d774e341..d0a357fd28 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/HttpManagementTest.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.test.utils.QpidTestCase; @@ -88,13 +89,13 @@ public class HttpManagementTest extends QpidTestCase _management.isHttpBasicAuthenticationEnabled()); } - public void testGetSubjectCreator() + public void testGetAuthenticationProvider() { SocketAddress localAddress = InetSocketAddress.createUnresolved("localhost", 8080); - SubjectCreator subjectCreator = mock(SubjectCreator.class); - when(_broker.getSubjectCreator(localAddress)).thenReturn(subjectCreator); - SubjectCreator httpManagementSubjectCreator = _management.getSubjectCreator(localAddress); - assertEquals("Unexpected subject creator", subjectCreator, httpManagementSubjectCreator); + AuthenticationProvider brokerAuthenticationProvider = mock(AuthenticationProvider.class); + when(_broker.getAuthenticationProvider(localAddress)).thenReturn(brokerAuthenticationProvider); + AuthenticationProvider authenticationProvider = _management.getAuthenticationProvider(localAddress); + assertEquals("Unexpected subject creator", brokerAuthenticationProvider, authenticationProvider); } } diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/log/LogFileHelperTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/log/LogFileHelperTest.java new file mode 100644 index 0000000000..608ef28f02 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/log/LogFileHelperTest.java @@ -0,0 +1,339 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.log; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.log4j.Appender; +import org.apache.log4j.DailyRollingFileAppender; +import org.apache.log4j.FileAppender; +import org.apache.log4j.QpidCompositeRollingAppender; +import org.apache.log4j.RollingFileAppender; +import org.apache.log4j.varia.ExternallyRolledFileAppender; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; +import org.apache.qpid.util.FileUtils; + +public class LogFileHelperTest extends QpidTestCase +{ + private Map<String, List<File>> _appendersFiles; + private File _compositeRollingAppenderBackupFolder; + private List<Appender> _appenders; + private LogFileHelper _helper; + + public void setUp() throws Exception + { + super.setUp(); + _appendersFiles = new HashMap<String, List<File>>(); + _compositeRollingAppenderBackupFolder = new File(TMP_FOLDER, "_compositeRollingAppenderBackupFolder"); + _compositeRollingAppenderBackupFolder.mkdirs(); + + _appendersFiles.put(FileAppender.class.getSimpleName(), + Collections.singletonList(TestFileUtils.createTempFile(this, ".log", "FileAppender"))); + _appendersFiles.put(DailyRollingFileAppender.class.getSimpleName(), + Collections.singletonList(TestFileUtils.createTempFile(this, ".log", "DailyRollingFileAppender"))); + _appendersFiles.put(RollingFileAppender.class.getSimpleName(), + Collections.singletonList(TestFileUtils.createTempFile(this, ".log", "RollingFileAppender"))); + _appendersFiles.put(ExternallyRolledFileAppender.class.getSimpleName(), + Collections.singletonList(TestFileUtils.createTempFile(this, ".log", "ExternallyRolledFileAppender"))); + + File file = TestFileUtils.createTempFile(this, ".log", "QpidCompositeRollingAppender"); + File backUpFile = File.createTempFile(file.getName() + ".", ".1." + LogFileHelper.GZIP_EXTENSION); + _appendersFiles.put(QpidCompositeRollingAppender.class.getSimpleName(), Arrays.asList(file, backUpFile)); + + FileAppender fileAppender = new FileAppender(); + DailyRollingFileAppender dailyRollingFileAppender = new DailyRollingFileAppender(); + RollingFileAppender rollingFileAppender = new RollingFileAppender(); + ExternallyRolledFileAppender externallyRolledFileAppender = new ExternallyRolledFileAppender(); + QpidCompositeRollingAppender qpidCompositeRollingAppender = new QpidCompositeRollingAppender(); + qpidCompositeRollingAppender.setbackupFilesToPath(_compositeRollingAppenderBackupFolder.getPath()); + + _appenders = new ArrayList<Appender>(); + _appenders.add(fileAppender); + _appenders.add(dailyRollingFileAppender); + _appenders.add(rollingFileAppender); + _appenders.add(externallyRolledFileAppender); + _appenders.add(qpidCompositeRollingAppender); + + for (Appender appender : _appenders) + { + FileAppender fa = (FileAppender) appender; + fa.setName(fa.getClass().getSimpleName()); + fa.setFile(_appendersFiles.get(fa.getClass().getSimpleName()).get(0).getPath()); + } + + _helper = new LogFileHelper(_appenders); + } + + public void tearDown() throws Exception + { + try + { + for (List<File> files : _appendersFiles.values()) + { + for (File file : files) + { + try + { + FileUtils.delete(file, false); + } + catch (Exception e) + { + // ignore + } + } + } + FileUtils.delete(_compositeRollingAppenderBackupFolder, true); + } + finally + { + super.tearDown(); + } + } + + public void testGetLogFileDetailsWithLocations() throws Exception + { + List<LogFileDetails> details = _helper.getLogFileDetails(true); + + assertLogFiles(details, true); + } + + public void testGetLogFileDetailsWithoutLocations() throws Exception + { + List<LogFileDetails> details = _helper.getLogFileDetails(false); + + assertLogFiles(details, false); + } + + public void testWriteLogFilesForAllLogs() throws Exception + { + List<LogFileDetails> details = _helper.getLogFileDetails(true); + File f = TestFileUtils.createTempFile(this, ".zip"); + + FileOutputStream os = new FileOutputStream(f); + try + { + _helper.writeLogFiles(details, os); + } + finally + { + if (os != null) + { + os.close(); + } + } + + assertWrittenFile(f, details); + } + + public void testWriteLogFile() throws Exception + { + File file = _appendersFiles.get(FileAppender.class.getSimpleName()).get(0); + + File f = TestFileUtils.createTempFile(this, ".log"); + FileOutputStream os = new FileOutputStream(f); + try + { + _helper.writeLogFile(file, os); + } + finally + { + if (os != null) + { + os.close(); + } + } + + assertEquals("Unexpected log content", FileAppender.class.getSimpleName(), FileUtils.readFileAsString(f)); + } + + public void testFindLogFileDetails() + { + String[] logFileDisplayedPaths = new String[6]; + File[] files = new File[logFileDisplayedPaths.length]; + int i = 0; + for (Map.Entry<String, List<File>> entry : _appendersFiles.entrySet()) + { + String appenderName = entry.getKey(); + List<File> appenderFiles = entry.getValue(); + for (File logFile : appenderFiles) + { + logFileDisplayedPaths[i] = appenderName + "/" + logFile.getName(); + files[i++] = logFile; + } + } + + List<LogFileDetails> logFileDetails = _helper.findLogFileDetails(logFileDisplayedPaths); + assertEquals("Unexpected details size", logFileDisplayedPaths.length, logFileDetails.size()); + + boolean gzipFileFound = false; + for (int j = 0; j < logFileDisplayedPaths.length; j++) + { + String displayedPath = logFileDisplayedPaths[j]; + String[] parts = displayedPath.split("/"); + LogFileDetails d = logFileDetails.get(j); + assertEquals("Unexpected name", parts[1], d.getName()); + assertEquals("Unexpected appender", parts[0], d.getAppenderName()); + if (files[j].getName().endsWith(LogFileHelper.GZIP_EXTENSION)) + { + assertEquals("Unexpected mime type for gz file", LogFileHelper.GZIP_MIME_TYPE, d.getMimeType()); + gzipFileFound = true; + } + else + { + assertEquals("Unexpected mime type", LogFileHelper.TEXT_MIME_TYPE, d.getMimeType()); + } + assertEquals("Unexpecte file location", files[j], d.getLocation()); + assertEquals("Unexpecte file size", files[j].length(), d.getSize()); + assertEquals("Unexpecte file last modified date", files[j].lastModified(), d.getLastModified()); + } + assertTrue("Gzip log file is not found", gzipFileFound); + } + + public void testFindLogFileDetailsForNotExistingAppender() + { + String[] logFileDisplayedPaths = { "NotExistingAppender/qpid.log" }; + List<LogFileDetails> details = _helper.findLogFileDetails(logFileDisplayedPaths); + assertTrue("No details should be created for non-existing appender", details.isEmpty()); + } + + public void testFindLogFileDetailsForNotExistingFile() + { + String[] logFileDisplayedPaths = { "FileAppender/qpid-non-existing.log" }; + List<LogFileDetails> details = _helper.findLogFileDetails(logFileDisplayedPaths); + assertTrue("No details should be created for non-existing file", details.isEmpty()); + } + + public void testFindLogFileDetailsForIncorectlySpecifiedLogFilePath() + { + String[] logFileDisplayedPaths = { "FileAppender\\" + _appendersFiles.get("FileAppender").get(0).getName() }; + try + { + _helper.findLogFileDetails(logFileDisplayedPaths); + fail("Exception is expected for incorectly set path to log file"); + } + catch (IllegalArgumentException e) + { + // pass + } + } + + private void assertLogFiles(List<LogFileDetails> details, boolean includeLocation) + { + for (Map.Entry<String, List<File>> appenderData : _appendersFiles.entrySet()) + { + String appenderName = (String) appenderData.getKey(); + List<File> files = appenderData.getValue(); + + for (File logFile : files) + { + String logFileName = logFile.getName(); + LogFileDetails d = findLogFileDetails(logFileName, appenderName, details); + assertNotNull("Log file " + logFileName + " is not found for appender " + appenderName, d); + if (includeLocation) + { + assertEquals("Log file " + logFileName + " is different in appender " + appenderName, d.getLocation(), + logFile); + } + } + } + } + + private LogFileDetails findLogFileDetails(String logFileName, String appenderName, List<LogFileDetails> logFileDetails) + { + LogFileDetails d = null; + for (LogFileDetails lfd : logFileDetails) + { + if (lfd.getName().equals(logFileName) && lfd.getAppenderName().equals(appenderName)) + { + d = lfd; + break; + } + } + return d; + } + + private void assertWrittenFile(File f, List<LogFileDetails> details) throws FileNotFoundException, IOException + { + FileInputStream fis = new FileInputStream(f); + try + { + ZipInputStream zis = new ZipInputStream(fis); + ZipEntry ze = zis.getNextEntry(); + + while (ze != null) + { + String entryName = ze.getName(); + String[] parts = entryName.split("/"); + + String appenderName = parts[0]; + String logFileName = parts[1]; + + LogFileDetails d = findLogFileDetails(logFileName, appenderName, details); + + assertNotNull("Unexpected entry " + entryName, d); + details.remove(d); + + File logFile = d.getLocation(); + String logContent = FileUtils.readFileAsString(logFile); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + while ((len = zis.read(buffer)) > 0) + { + baos.write(buffer, 0, len); + } + baos.close(); + + assertEquals("Unexpected log file content", logContent, baos.toString()); + + ze = zis.getNextEntry(); + } + + zis.closeEntry(); + zis.close(); + + } + finally + { + if (fis != null) + { + fis.close(); + } + } + assertEquals("Not all log files have been output", 0, details.size()); + } + +} diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java index d094134e11..32aac51008 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/JMXManagedObjectRegistry.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.jmx; +import javax.net.ssl.KeyManager; import org.apache.log4j.Logger; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -124,26 +125,19 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry { KeyStore keyStore = _connectorPort.getKeyStore(); - String keyStorePath = (String) keyStore.getAttribute(KeyStore.PATH); - String keyStorePassword = keyStore.getPassword(); - String keyStoreType = (String) keyStore.getAttribute(KeyStore.TYPE); - String keyManagerFactoryAlgorithm = (String) keyStore.getAttribute(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM); - SSLContext sslContext; try { - sslContext = SSLContextFactory.buildServerContext(keyStorePath, keyStorePassword, keyStoreType, keyManagerFactoryAlgorithm); + + sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyStore.getKeyManagers(), null, null); } catch (GeneralSecurityException e) { throw new RuntimeException("Unable to create SSLContext for key store", e); } - catch (IOException e) - { - throw new RuntimeException("Unable to create SSLContext for key store", e); - } - CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(keyStorePath)); + CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(keyStore.getName())); //create the SSL RMI socket factories csf = new SslRMIClientSocketFactory(); diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java index 67ac1bdc7c..2c88f83405 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBean.java @@ -48,6 +48,7 @@ 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.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueArgumentsConverter; @MBeanDescription("This MBean exposes the broker level management features") public class VirtualHostManagerMBean extends AbstractStatisticsGatheringMBean<VirtualHost> implements ManagedBroker @@ -180,7 +181,8 @@ public class VirtualHostManagerMBean extends AbstractStatisticsGatheringMBean<Vi throws IOException, JMException { final Map<String, Object> createArgs = processNewQueueArguments(queueName, owner, originalArguments); - getConfiguredObject().createQueue(queueName, State.ACTIVE, durable, false, LifetimePolicy.PERMANENT, 0l, createArgs); + getConfiguredObject().createQueue(queueName, State.ACTIVE, durable, false, LifetimePolicy.PERMANENT, 0l, + QueueArgumentsConverter.convertWireArgsToModel(createArgs)); } @@ -196,11 +198,11 @@ public class VirtualHostManagerMBean extends AbstractStatisticsGatheringMBean<Vi if (_moveNonExclusiveQueueOwnerToDescription && owner != null) { argumentsCopy = new HashMap<String, Object>(arguments == null ? new HashMap<String, Object>() : arguments); - if (!argumentsCopy.containsKey(AMQQueueFactory.X_QPID_DESCRIPTION)) + if (!argumentsCopy.containsKey(QueueArgumentsConverter.X_QPID_DESCRIPTION)) { - LOGGER.warn("Non-exclusive owner " + owner + " for new queue " + queueName + " moved to " + AMQQueueFactory.X_QPID_DESCRIPTION); + LOGGER.warn("Non-exclusive owner " + owner + " for new queue " + queueName + " moved to " + QueueArgumentsConverter.X_QPID_DESCRIPTION); - argumentsCopy.put(AMQQueueFactory.X_QPID_DESCRIPTION, owner); + argumentsCopy.put(QueueArgumentsConverter.X_QPID_DESCRIPTION, owner); } else { diff --git a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java index e3fac9f711..4240dd5280 100644 --- a/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java +++ b/qpid/java/broker-plugins/management-jmx/src/test/java/org/apache/qpid/server/jmx/mbeans/VirtualHostManagerMBeanTest.java @@ -38,6 +38,7 @@ 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.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueArgumentsConverter; public class VirtualHostManagerMBeanTest extends TestCase { @@ -79,16 +80,16 @@ public class VirtualHostManagerMBeanTest extends TestCase { _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, TEST_OWNER, true); - Map<String, Object> expectedArguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_OWNER); + Map<String, Object> expectedArguments = Collections.singletonMap(Queue.DESCRIPTION, (Object)TEST_OWNER); verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, expectedArguments); } public void testCreateQueueWithOwnerAndDescriptionDiscardsOwner() throws Exception { - Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION); + Map<String, Object> arguments = Collections.singletonMap(QueueArgumentsConverter.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION); _virtualHostManagerMBean.createNewQueue(TEST_QUEUE_NAME, TEST_OWNER, true, arguments); - Map<String, Object> expectedArguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_DESCRIPTION); + Map<String, Object> expectedArguments = Collections.singletonMap(Queue.DESCRIPTION, (Object)TEST_DESCRIPTION); verify(_mockVirtualHost).createQueue(TEST_QUEUE_NAME, State.ACTIVE, true, false, LifetimePolicy.PERMANENT, 0, expectedArguments); } diff --git a/qpid/java/broker-plugins/memory-store/build.xml b/qpid/java/broker-plugins/memory-store/build.xml new file mode 100644 index 0000000000..f265e68e94 --- /dev/null +++ b/qpid/java/broker-plugins/memory-store/build.xml @@ -0,0 +1,32 @@ +<!-- + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + --> +<project name="Qpid Broker-Plugins Memory Store" default="build"> + <property name="module.depends" value="common broker" /> + <property name="module.test.depends" value="common/tests broker/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker=provided"/> + + <property name="broker.plugin" value="true"/> + <property name="broker-plugins-memory-store.libs" value="" /> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> +</project> diff --git a/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java new file mode 100644 index 0000000000..61fef91e83 --- /dev/null +++ b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java @@ -0,0 +1,34 @@ +/* + * + * 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; + + +/** A simple message store that stores the messages in a thread-safe structure in memory. */ +public class MemoryMessageStore extends AbstractMemoryMessageStore +{ + public static final String TYPE = "Memory"; + + @Override + public String getStoreType() + { + return TYPE; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java index 49f823e7ee..49f823e7ee 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java +++ b/qpid/java/broker-plugins/memory-store/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/virtualhost/store/memory/add.js b/qpid/java/broker-plugins/memory-store/src/main/java/resources/js/qpid/management/virtualhost/store/memory/add.js index 3a9b23274d..3a9b23274d 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/virtualhost/store/memory/add.js +++ b/qpid/java/broker-plugins/memory-store/src/main/java/resources/js/qpid/management/virtualhost/store/memory/add.js diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/virtualhost/store/pool/none/add.html b/qpid/java/broker-plugins/memory-store/src/main/java/resources/virtualhost/store/memory/add.html index e69de29bb2..e69de29bb2 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/virtualhost/store/pool/none/add.html +++ b/qpid/java/broker-plugins/memory-store/src/main/java/resources/virtualhost/store/memory/add.html diff --git a/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/broker-plugins/memory-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory index 02f22eb21a..02f22eb21a 100644 --- a/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory +++ b/qpid/java/broker-plugins/memory-store/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory diff --git a/qpid/java/broker/build.xml b/qpid/java/broker/build.xml index 3c83715305..da51e4ffa5 100644 --- a/qpid/java/broker/build.xml +++ b/qpid/java/broker/build.xml @@ -19,15 +19,15 @@ - --> <project name="AMQ Broker" default="build"> - <property name="module.depends" value="management/common common amqp-1-0-common"/> + <property name="module.depends" value="management/common common"/> <property name="module.test.depends" value="common/tests" /> <property name="module.main" value="org.apache.qpid.server.Main"/> <property name="module.genpom" value="true"/> <!-- Add dependencies to the broker pom for the broker-plugins and bdbstore modules --> - <property name="module.maven.depends" value="broker-plugins/management-http broker-plugins/management-jmx broker-plugins/access-control broker-plugins/jdbc-provider-bone bdbstore bdbstore/jmx broker-plugins/jdbc-store broker-plugins/derby-store"/> + <property name="module.maven.depends" value="broker-plugins/access-control broker-plugins/amqp-0-8-protocol broker-plugins/amqp-0-10-protocol broker-plugins/amqp-1-0-protocol broker-plugins/amqp-msg-conv-0-8-to-0-10 broker-plugins/amqp-msg-conv-0-8-to-1-0 broker-plugins/amqp-msg-conv-0-10-to-1-0 broker-plugins/derby-store broker-plugins/jdbc-provider-bone broker-plugins/jdbc-store broker-plugins/management-http broker-plugins/management-jmx broker-plugins/memory-store bdbstore bdbstore/jmx"/> <!-- Make them runtime dependencies, make bdbstore modules optional --> - <property name="module.genpom.args" value="-Sqpid-broker-plugins-management-http=runtime -Sqpid-broker-plugins-management-jmx=runtime -Sqpid-broker-plugins-access-control=runtime -Sqpid-bdbstore=runtime -Oqpid-bdbstore -Sqpid-bdbstore-jmx=runtime -Oqpid-bdbstore-jmx -Sqpid-broker-plugins-jdbc-provider-bone=runtime -Oqpid-broker-plugins-jdbc-provider-bone -Sqpid-broker-plugins-jdbc-store=runtime -Sqpid-broker-plugins-derby-store=runtime"/> + <property name="module.genpom.args" value="-Sqpid-broker-plugins-access-control=runtime -Sqpid-broker-plugins-amqp-0-8-protocol=runtime -Sqpid-broker-plugins-amqp-0-10-protocol=runtime -Sqpid-broker-plugins-amqp-1-0-protocol=runtime -Sqpid-broker-plugins-amqp-msg-conv-0-8-to-0-10=runtime -Sqpid-broker-plugins-amqp-msg-conv-0-8-to-1-0=runtime -Sqpid-broker-plugins-amqp-msg-conv-0-10-to-1-0=runtime -Sqpid-broker-plugins-derby-store=runtime -Sqpid-broker-plugins-jdbc-provider-bone=runtime -Sqpid-broker-plugins-jdbc-store=runtime -Sqpid-broker-plugins-management-http=runtime -Sqpid-broker-plugins-management-jmx=runtime -Sbroker-plugins-memory-store=runtime -Sqpid-bdbstore=runtime -Sqpid-bdbstore-jmx=runtime -Oqpid-bdbstore -Oqpid-bdbstore-jmx"/> <import file="../module.xml"/> @@ -67,9 +67,6 @@ <target name="release-bin-other-bdbstore" depends="check-bdbstore-requested" if="bdbstore-requested" description="copy bdbstore items into module release"> - <copy todir="${module.release}/lib/" failonerror="true"> - <fileset file="${build.lib}/${project.name}-bdbstore-${project.version}.jar"/> - </copy> <copy todir="${module.release}/bin" failonerror="true" flatten="true"> <fileset dir="${basedir}/../bdbstore/bin"/> </copy> diff --git a/qpid/java/broker/etc/broker_example.acl b/qpid/java/broker/etc/broker_example.acl index 6cab707a89..29dca90f15 100644 --- a/qpid/java/broker/etc/broker_example.acl +++ b/qpid/java/broker/etc/broker_example.acl @@ -76,6 +76,9 @@ ACL ALLOW-LOG webadmins UPDATE METHOD # authorise operations changing broker model ACL ALLOW-LOG webadmins CONFIGURE BROKER +# authorise operations to view and download broker logs +ACL ALLOW webadmins ACCESS_LOGS BROKER + # at the moment only the following UPDATE METHOD rules are supported by web management console #ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="moveMessages" #ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="copyMessages" diff --git a/qpid/java/broker/src/main/java/broker.bnd b/qpid/java/broker/src/main/java/broker.bnd index 2edbab79a5..8296764126 100755 --- a/qpid/java/broker/src/main/java/broker.bnd +++ b/qpid/java/broker/src/main/java/broker.bnd @@ -17,7 +17,7 @@ # under the License. # -ver: 0.23.0 +ver: 0.25.0 Bundle-SymbolicName: qpid-broker Bundle-Version: ${ver} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java index 703162a609..7de0ebe1de 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java @@ -67,17 +67,11 @@ public class Broker } finally { - try - { - if (_applicationRegistry != null) - { - _applicationRegistry.close(); - } - } - finally + if (_applicationRegistry != null) { - clearAMQShortStringCache(); + _applicationRegistry.close(); } + } } @@ -96,14 +90,8 @@ public class Broker } finally { - try - { - CurrentActor.remove(); - } - finally - { - clearAMQShortStringCache(); - } + CurrentActor.remove(); + } } @@ -269,15 +257,6 @@ public class Broker LOGGER.debug("Skipping shutdown hook removal as there either isnt one, or we are it."); } } - /** - * Workaround that prevents AMQShortStrings cache from being left in the thread local. This is important - * when embedding the Broker in containers where the starting thread may not belong to Qpid. - * The long term solution here is to stop our use of AMQShortString outside the AMQP transport layer. - */ - private void clearAMQShortStringCache() - { - AMQShortString.clearLocalCache(); - } public org.apache.qpid.server.model.Broker getBroker() { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerProperties.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerProperties.java index 0b31f5b81a..fb382a8ca9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerProperties.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/BrokerProperties.java @@ -54,6 +54,7 @@ public class BrokerProperties public static final String PROPERTY_QPID_HOME = "QPID_HOME"; public static final String PROPERTY_QPID_WORK = "QPID_WORK"; + public static final String PROPERTY_LOG_RECORDS_BUFFER_SIZE = "qpid.broker_log_records_buffer_size"; private BrokerProperties() { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java index f37d06f117..25466d9c55 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java @@ -117,7 +117,7 @@ public class QueueConfiguration extends AbstractConfiguration public String getExchange() { - return getStringValue("exchange", ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString()); + return getStringValue("exchange", ExchangeDefaults.DEFAULT_EXCHANGE_NAME); } public List getRoutingKeys() diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java index 041ccf1f50..189f5916e0 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java @@ -26,7 +26,6 @@ import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.configuration.plugins.AbstractConfiguration; import org.apache.qpid.server.model.Broker; -import org.apache.qpid.server.store.MemoryMessageStore; import java.io.File; import java.util.HashMap; @@ -129,7 +128,7 @@ public class VirtualHostConfiguration extends AbstractConfiguration public String getMessageStoreClass() { - return getStringValue("store.class", MemoryMessageStore.class.getName()); + return getStringValue("store.class", null); } public void setMessageStoreClass(String storeFactoryClass) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java index 2bf0cdbab3..8eec88d556 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecoverer.java @@ -20,23 +20,29 @@ */ package org.apache.qpid.server.configuration.startup; +import java.util.Collection; import java.util.Map; import org.apache.qpid.server.configuration.ConfigurationEntry; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; public class AuthenticationProviderRecoverer implements ConfiguredObjectRecoverer<AuthenticationProvider> { private final AuthenticationProviderFactory _authenticationProviderFactory; + private final StoreConfigurationChangeListener _storeChangeListener; - public AuthenticationProviderRecoverer(AuthenticationProviderFactory authenticationProviderFactory) + public AuthenticationProviderRecoverer(AuthenticationProviderFactory authenticationProviderFactory, StoreConfigurationChangeListener storeChangeListener) { _authenticationProviderFactory = authenticationProviderFactory; + _storeChangeListener = storeChangeListener; } @Override @@ -46,6 +52,44 @@ public class AuthenticationProviderRecoverer implements ConfiguredObjectRecovere Map<String, Object> attributes = configurationEntry.getAttributes(); AuthenticationProvider authenticationProvider = _authenticationProviderFactory.recover(configurationEntry.getId(), attributes, broker); + Map<String, Collection<ConfigurationEntry>> childEntries = configurationEntry.getChildren(); + + for (String type : childEntries.keySet()) + { + recoverType(recovererProvider, _storeChangeListener, authenticationProvider, childEntries, type); + } + return authenticationProvider; } + + private void recoverType(RecovererProvider recovererProvider, + StoreConfigurationChangeListener storeChangeListener, + AuthenticationProvider authenticationProvider, + Map<String, Collection<ConfigurationEntry>> childEntries, + String type) + { + ConfiguredObjectRecoverer<?> recoverer = recovererProvider.getRecoverer(type); + if (recoverer == null) + { + throw new IllegalConfigurationException("Cannot recover entry for the type '" + type + "' from broker"); + } + Collection<ConfigurationEntry> entries = childEntries.get(type); + for (ConfigurationEntry childEntry : entries) + { + ConfiguredObject object = recoverer.create(recovererProvider, childEntry, authenticationProvider); + if (object == null) + { + throw new IllegalConfigurationException("Cannot create configured object for the entry " + childEntry); + } + if (object instanceof PreferencesProvider) + { + authenticationProvider.setPreferencesProvider((PreferencesProvider)object); + } + else + { + throw new IllegalConfigurationException("Cannot associate " + object + " with authentication provider " + authenticationProvider); + } + object.addChangeListener(storeChangeListener); + } + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java index ae7e699264..4923565e26 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/BrokerRecoverer.java @@ -47,6 +47,7 @@ import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; import org.apache.qpid.server.model.adapter.BrokerAdapter; import org.apache.qpid.server.model.adapter.GroupProviderFactory; import org.apache.qpid.server.model.adapter.PortFactory; +import org.apache.qpid.server.model.adapter.PreferencesProviderCreator; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.util.MapValueConverter; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; @@ -65,10 +66,13 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> private final TaskExecutor _taskExecutor; private final BrokerOptions _brokerOptions; private final GroupProviderFactory _groupProviderFactory; + private final StoreConfigurationChangeListener _storeChangeListener; + private final PreferencesProviderCreator _preferencesProviderCreator; public BrokerRecoverer(AuthenticationProviderFactory authenticationProviderFactory, GroupProviderFactory groupProviderFactory, - AccessControlProviderFactory accessControlProviderFactory, PortFactory portFactory, StatisticsGatherer statisticsGatherer, - VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) + AccessControlProviderFactory accessControlProviderFactory, PortFactory portFactory, PreferencesProviderCreator preferencesProviderFactory, StatisticsGatherer statisticsGatherer, + VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, + BrokerOptions brokerOptions, StoreConfigurationChangeListener storeChangeListener) { _groupProviderFactory = groupProviderFactory; _portFactory = portFactory; @@ -80,6 +84,8 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> _rootMessageLogger = rootMessageLogger; _taskExecutor = taskExecutor; _brokerOptions = brokerOptions; + _storeChangeListener = storeChangeListener; + _preferencesProviderCreator = preferencesProviderFactory; } @Override @@ -90,12 +96,11 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> attributesCopy.put(Broker.MODEL_VERSION, Model.MODEL_VERSION); - StoreConfigurationChangeListener storeChangeListener = new StoreConfigurationChangeListener(entry.getStore()); BrokerAdapter broker = new BrokerAdapter(entry.getId(), attributesCopy, _statisticsGatherer, _virtualHostRegistry, - _logRecorder, _rootMessageLogger, _authenticationProviderFactory, _groupProviderFactory, _accessControlProviderFactory, - _portFactory, _taskExecutor, entry.getStore(), _brokerOptions); + _logRecorder, _rootMessageLogger, _authenticationProviderFactory,_groupProviderFactory, _accessControlProviderFactory, + _portFactory , _preferencesProviderCreator, _taskExecutor, entry.getStore(), _brokerOptions); - broker.addChangeListener(storeChangeListener); + broker.addChangeListener(_storeChangeListener); //Recover the SSL keystores / truststores first, then others that depend on them Map<String, Collection<ConfigurationEntry>> childEntries = new HashMap<String, Collection<ConfigurationEntry>>(entry.getChildren()); @@ -117,11 +122,11 @@ public class BrokerRecoverer implements ConfiguredObjectRecoverer<Broker> for (String type : priorityChildEntries.keySet()) { - recoverType(recovererProvider, storeChangeListener, broker, priorityChildEntries, type); + recoverType(recovererProvider, _storeChangeListener, broker, priorityChildEntries, type); } for (String type : childEntries.keySet()) { - recoverType(recovererProvider, storeChangeListener, broker, childEntries, type); + recoverType(recovererProvider, _storeChangeListener, broker, childEntries, type); } return broker; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java index 2de454c34f..67268c9854 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProvider.java @@ -32,12 +32,15 @@ import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.adapter.AccessControlProviderFactory; import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; import org.apache.qpid.server.model.adapter.GroupProviderFactory; import org.apache.qpid.server.model.adapter.PortFactory; +import org.apache.qpid.server.model.adapter.PreferencesProviderCreator; +import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.plugin.AccessControlFactory; import org.apache.qpid.server.plugin.AuthenticationManagerFactory; @@ -61,11 +64,14 @@ public class DefaultRecovererProvider implements RecovererProvider private final QpidServiceLoader<PluginFactory> _pluginFactoryServiceLoader; private final TaskExecutor _taskExecutor; private final BrokerOptions _brokerOptions; + private final StoreConfigurationChangeListener _storeChangeListener; + private final PreferencesProviderCreator _preferencesProviderCreator; public DefaultRecovererProvider(StatisticsGatherer brokerStatisticsGatherer, VirtualHostRegistry virtualHostRegistry, - LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions) + LogRecorder logRecorder, RootMessageLogger rootMessageLogger, TaskExecutor taskExecutor, BrokerOptions brokerOptions, StoreConfigurationChangeListener storeChangeListener) { - _authenticationProviderFactory = new AuthenticationProviderFactory(new QpidServiceLoader<AuthenticationManagerFactory>()); + _preferencesProviderCreator = new PreferencesProviderCreator(); + _authenticationProviderFactory = new AuthenticationProviderFactory(new QpidServiceLoader<AuthenticationManagerFactory>(), _preferencesProviderCreator); _accessControlProviderFactory = new AccessControlProviderFactory(new QpidServiceLoader<AccessControlFactory>()); _groupProviderFactory = new GroupProviderFactory(new QpidServiceLoader<GroupManagerFactory>()); _portFactory = new PortFactory(); @@ -76,6 +82,7 @@ public class DefaultRecovererProvider implements RecovererProvider _pluginFactoryServiceLoader = new QpidServiceLoader<PluginFactory>(); _taskExecutor = taskExecutor; _brokerOptions = brokerOptions; + _storeChangeListener = storeChangeListener; } @Override @@ -83,8 +90,8 @@ public class DefaultRecovererProvider implements RecovererProvider { if (Broker.class.getSimpleName().equals(type)) { - return new BrokerRecoverer(_authenticationProviderFactory, _groupProviderFactory, _accessControlProviderFactory, _portFactory, _brokerStatisticsGatherer, - _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, _brokerOptions); + return new BrokerRecoverer(_authenticationProviderFactory, _groupProviderFactory, _accessControlProviderFactory, _portFactory, _preferencesProviderCreator, + _brokerStatisticsGatherer, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, _brokerOptions, _storeChangeListener); } else if(VirtualHost.class.getSimpleName().equals(type)) { @@ -96,7 +103,7 @@ public class DefaultRecovererProvider implements RecovererProvider } else if(AuthenticationProvider.class.getSimpleName().equals(type)) { - return new AuthenticationProviderRecoverer(_authenticationProviderFactory); + return new AuthenticationProviderRecoverer(_authenticationProviderFactory, _storeChangeListener); } else if(Port.class.getSimpleName().equals(type)) { @@ -114,6 +121,10 @@ public class DefaultRecovererProvider implements RecovererProvider { return new TrustStoreRecoverer(); } + else if(PreferencesProvider.class.getSimpleName().equals(type)) + { + return new PreferencesProviderRecoverer(_preferencesProviderCreator); + } else if(Plugin.class.getSimpleName().equals(type)) { return new PluginRecoverer(_pluginFactoryServiceLoader); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecoverer.java new file mode 100644 index 0000000000..a455a61fee --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecoverer.java @@ -0,0 +1,41 @@ +package org.apache.qpid.server.configuration.startup; + +import org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.adapter.PreferencesProviderCreator; + +public class PreferencesProviderRecoverer implements ConfiguredObjectRecoverer<PreferencesProvider> +{ + + private PreferencesProviderCreator _preferencesProviderCreator; + + public PreferencesProviderRecoverer(PreferencesProviderCreator preferencesProviderCreator) + { + _preferencesProviderCreator = preferencesProviderCreator; + } + + @Override + public PreferencesProvider create(RecovererProvider recovererProvider, ConfigurationEntry entry, + ConfiguredObject... parents) + { + if (parents == null || parents.length == 0) + { + throw new IllegalArgumentException("AuthenticationProvider parent is not passed!"); + } + if (parents.length != 1) + { + throw new IllegalArgumentException("Only one parent is expected!"); + } + if (!(parents[0] instanceof AuthenticationProvider)) + { + throw new IllegalArgumentException("Parent is not a AuthenticationProvider"); + } + AuthenticationProvider authenticationProvider = (AuthenticationProvider)parents[0]; + return _preferencesProviderCreator.recover(entry.getId(), entry.getAttributes(), authenticationProvider); + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java index 2b9c5ad290..92d170fad9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/store/MemoryConfigurationEntryStore.java @@ -180,7 +180,12 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore return _entries.get(id); } - @Override + /** + * Copies the store into the given location + * + * @param target location to copy store into + * @throws IllegalConfigurationException if store cannot be copied into given location + */ public void copyTo(String copyLocation) { File file = new File(copyLocation); @@ -286,7 +291,7 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore + " can not be loaded by store of version " + STORE_VERSION); } - ConfigurationEntry brokerEntry = toEntry(node, Broker.class, _entries); + ConfigurationEntry brokerEntry = toEntry(node, Broker.class, _entries, null); _rootId = brokerEntry.getId(); } catch (IOException e) @@ -365,7 +370,7 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore byte[] bytes = json.getBytes("UTF-8"); bais = new ByteArrayInputStream(bytes); JsonNode node = loadJsonNodes(bais, _objectMapper); - ConfigurationEntry brokerEntry = toEntry(node, Broker.class, _entries); + ConfigurationEntry brokerEntry = toEntry(node, Broker.class, _entries, null); _rootId = brokerEntry.getId(); } catch(Exception e) @@ -485,7 +490,7 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore return root; } - private ConfigurationEntry toEntry(JsonNode parent, Class<? extends ConfiguredObject> expectedConfiguredObjectClass, Map<UUID, ConfigurationEntry> entries) + private ConfigurationEntry toEntry(JsonNode parent, Class<? extends ConfiguredObject> expectedConfiguredObjectClass, Map<UUID, ConfigurationEntry> entries, Class<? extends ConfiguredObject> parentClass) { Map<String, Object> attributes = null; Set<UUID> childrenIds = new TreeSet<UUID>(); @@ -515,8 +520,22 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore if (element.isObject()) { Class<? extends ConfiguredObject> expectedChildConfiguredObjectClass = _relationshipClasses.get(fieldName); + if (expectedChildConfiguredObjectClass == null && expectedConfiguredObjectClass != null) + { + Collection<Class<? extends ConfiguredObject>> childTypes = Model.getInstance().getChildTypes(expectedConfiguredObjectClass); + for (Class<? extends ConfiguredObject> childType : childTypes) + { + String relationship = childType.getSimpleName().toLowerCase(); + relationship += relationship.endsWith("s") ? "es": "s"; + if (fieldName.equals(relationship)) + { + expectedChildConfiguredObjectClass = childType; + break; + } + } + } // assuming it is a child node - ConfigurationEntry entry = toEntry(element, expectedChildConfiguredObjectClass, entries); + ConfigurationEntry entry = toEntry(element, expectedChildConfiguredObjectClass, entries, expectedConfiguredObjectClass); childrenIds.add(entry.getId()); } else @@ -531,6 +550,10 @@ public class MemoryConfigurationEntryStore implements ConfigurationEntryStore if (fieldValues != null) { Object[] array = fieldValues.toArray(new Object[fieldValues.size()]); + if (attributes == null) + { + attributes = new HashMap<String, Object>(); + } attributes.put(fieldName, array); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index 53dd6df599..c30ebe17be 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java @@ -26,7 +26,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -39,7 +38,6 @@ import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.store.DurableConfigurationStoreHelper; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -57,7 +55,7 @@ import java.util.concurrent.atomic.AtomicLong; public abstract class AbstractExchange implements Exchange { private static final Logger _logger = Logger.getLogger(AbstractExchange.class); - private AMQShortString _name; + private String _name; private final AtomicBoolean _closed = new AtomicBoolean(); private Exchange _alternateExchange; @@ -98,19 +96,15 @@ public abstract class AbstractExchange implements Exchange _type = type; } - public AMQShortString getNameShortString() - { - return _name; - } - - public final AMQShortString getTypeShortString() + @Override + public String getTypeName() { - return _type.getName(); + return _type.getType(); } public void initialise(UUID id, VirtualHost host, - AMQShortString name, + String name, boolean durable, boolean autoDelete) throws AMQException @@ -124,7 +118,7 @@ public abstract class AbstractExchange implements Exchange _logSubject = new ExchangeLogSubject(this, this.getVirtualHost()); // Log Exchange creation - CurrentActor.get().message(ExchangeMessages.CREATED(String.valueOf(getTypeShortString()), String.valueOf(name), durable)); + CurrentActor.get().message(ExchangeMessages.CREATED(getType().getType(), name, durable)); } public boolean isDurable() @@ -159,7 +153,7 @@ public abstract class AbstractExchange implements Exchange public String toString() { - return getClass().getSimpleName() + "[" + getNameShortString() +"]"; + return getClass().getSimpleName() + "[" + getName() +"]"; } public VirtualHost getVirtualHost() @@ -167,16 +161,6 @@ public abstract class AbstractExchange implements Exchange return _virtualHost; } - public QueueRegistry getQueueRegistry() - { - return getVirtualHost().getQueueRegistry(); - } - - public final boolean isBound(AMQShortString routingKey, FieldTable ft, AMQQueue queue) - { - return isBound(routingKey == null ? "" : routingKey.asString(), FieldTable.convertToMap(ft), queue); - } - public final boolean isBound(String bindingKey, Map<String,Object> arguments, AMQQueue queue) { for(Binding b : _bindings) @@ -191,11 +175,6 @@ public abstract class AbstractExchange implements Exchange return false; } - public final boolean isBound(AMQShortString routingKey, AMQQueue queue) - { - return isBound(routingKey==null ? "" : routingKey.asString(), queue); - } - public final boolean isBound(String bindingKey, AMQQueue queue) { for(Binding b : _bindings) @@ -208,11 +187,6 @@ public abstract class AbstractExchange implements Exchange return false; } - public final boolean isBound(AMQShortString routingKey) - { - return isBound(routingKey == null ? "" : routingKey.asString()); - } - public final boolean isBound(String bindingKey) { for(Binding b : _bindings) @@ -420,7 +394,7 @@ public abstract class AbstractExchange implements Exchange } if(_logger.isDebugEnabled()) { - _logger.debug("Exchange: " + getName() + " - attempt to enqueue message onto deleted queue " + String.valueOf(q.getNameShortString())); + _logger.debug("Exchange: " + getName() + " - attempt to enqueue message onto deleted queue " + q.getName()); } queues.remove(q); } @@ -536,7 +510,7 @@ public abstract class AbstractExchange implements Exchange // all operations on it to succeed. It is up to the broker to prevent illegal // attempts at binding to this exchange, not the ACLs. // Check access - if (!_virtualHost.getSecurityManager().authoriseUnbind(this, new AMQShortString(bindingKey), queue)) + if (!_virtualHost.getSecurityManager().authoriseUnbind(this, bindingKey, queue)) { throw new AMQSecurityException("Permission denied: unbinding " + bindingKey); } @@ -601,7 +575,7 @@ public abstract class AbstractExchange implements Exchange } //Perform ACLs - if (!_virtualHost.getSecurityManager().authoriseBind(AbstractExchange.this, queue, new AMQShortString(bindingKey))) + if (!_virtualHost.getSecurityManager().authoriseBind(AbstractExchange.this, queue, bindingKey)) { throw new AMQSecurityException("Permission denied: binding " + bindingKey); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java index 2873eb31e8..aed2ddb8cf 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java @@ -32,7 +32,6 @@ import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -47,6 +46,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost; public class DefaultExchange implements Exchange { + private final QueueRegistry _queueRegistry; private UUID _id; private VirtualHost _virtualHost; private static final Logger _logger = Logger.getLogger(DefaultExchange.class); @@ -55,11 +55,16 @@ public class DefaultExchange implements Exchange private LogSubject _logSubject; private Map<ExchangeReferrer,Object> _referrers = new ConcurrentHashMap<ExchangeReferrer,Object>(); + public DefaultExchange(QueueRegistry queueRegistry) + { + _queueRegistry = queueRegistry; + } + @Override public void initialise(UUID id, VirtualHost host, - AMQShortString name, + String name, boolean durable, boolean autoDelete) throws AMQException { @@ -70,7 +75,7 @@ public class DefaultExchange implements Exchange @Override public String getName() { - return ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(); + return ExchangeDefaults.DEFAULT_EXCHANGE_NAME; } @Override @@ -82,7 +87,7 @@ public class DefaultExchange implements Exchange @Override public long getBindingCount() { - return _virtualHost.getQueueRegistry().getQueues().size(); + return _virtualHost.getQueues().size(); } @Override @@ -146,7 +151,7 @@ public class DefaultExchange implements Exchange @Override public Binding getBinding(String bindingKey, AMQQueue queue, Map<String, Object> arguments) { - if(_virtualHost.getQueueRegistry().getQueue(bindingKey) == queue && (arguments == null || arguments.isEmpty())) + if(_virtualHost.getQueue(bindingKey) == queue && (arguments == null || arguments.isEmpty())) { return convertToBinding(queue); } @@ -161,7 +166,7 @@ public class DefaultExchange implements Exchange { String queueName = queue.getName(); - UUID exchangeId = UUIDGenerator.generateBindingUUID(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(), + UUID exchangeId = UUIDGenerator.generateBindingUUID(ExchangeDefaults.DEFAULT_EXCHANGE_NAME, queueName, queueName, _virtualHost.getName()); @@ -170,15 +175,9 @@ public class DefaultExchange implements Exchange } @Override - public AMQShortString getNameShortString() - { - return AMQShortString.EMPTY_STRING; - } - - @Override - public AMQShortString getTypeShortString() + public String getTypeName() { - return getType().getName(); + return getType().getType(); } @Override @@ -207,7 +206,7 @@ public class DefaultExchange implements Exchange @Override public List<AMQQueue> route(InboundMessage message) { - AMQQueue q = _virtualHost.getQueueRegistry().getQueue(message.getRoutingKey()); + AMQQueue q = _virtualHost.getQueue(message.getRoutingKey()); if(q == null) { List<AMQQueue> noQueues = Collections.emptyList(); @@ -221,27 +220,9 @@ public class DefaultExchange implements Exchange } @Override - public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue) - { - return isBound(routingKey, queue) && (arguments == null || arguments.isEmpty()); - } - - @Override - public boolean isBound(AMQShortString routingKey, AMQQueue queue) - { - return isBound(routingKey) && isBound(queue) && queue.getNameShortString().equals(routingKey); //To change body of implemented methods use File | Settings | File Templates. - } - - @Override - public boolean isBound(AMQShortString routingKey) - { - return _virtualHost.getQueueRegistry().getQueue(routingKey) != null; - } - - @Override public boolean isBound(AMQQueue queue) { - return _virtualHost.getQueueRegistry().getQueue(queue.getName()) == queue; + return _virtualHost.getQueue(queue.getName()) == queue; } @Override @@ -283,7 +264,7 @@ public class DefaultExchange implements Exchange @Override public boolean isBound(String bindingKey) { - return _virtualHost.getQueueRegistry().getQueue(bindingKey) != null; + return _virtualHost.getQueue(bindingKey) != null; } @Override @@ -320,7 +301,7 @@ public class DefaultExchange implements Exchange public Collection<Binding> getBindings() { List<Binding> bindings = new ArrayList<Binding>(); - for(AMQQueue q : _virtualHost.getQueueRegistry().getQueues()) + for(AMQQueue q : _virtualHost.getQueues()) { bindings.add(convertToBinding(q)); } @@ -330,7 +311,7 @@ public class DefaultExchange implements Exchange @Override public void addBindingListener(BindingListener listener) { - _virtualHost.getQueueRegistry().addRegistryChangeListener(convertListener(listener));//To change body of implemented methods use File | Settings | File Templates. + _queueRegistry.addRegistryChangeListener(convertListener(listener)); } private QueueRegistry.RegistryChangeListener convertListener(final BindingListener listener) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java index a0b80a601c..612fa855a4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java @@ -44,14 +44,14 @@ public class DefaultExchangeFactory implements ExchangeFactory private static final Logger LOGGER = Logger.getLogger(DefaultExchangeFactory.class); - private static final AMQShortString[] BASE_EXCHANGE_TYPES = - new AMQShortString[]{ExchangeDefaults.DIRECT_EXCHANGE_CLASS, - ExchangeDefaults.FANOUT_EXCHANGE_CLASS, - ExchangeDefaults.HEADERS_EXCHANGE_CLASS, - ExchangeDefaults.TOPIC_EXCHANGE_CLASS}; + private static final String[] BASE_EXCHANGE_TYPES = + new String[]{ExchangeDefaults.DIRECT_EXCHANGE_CLASS, + ExchangeDefaults.FANOUT_EXCHANGE_CLASS, + ExchangeDefaults.HEADERS_EXCHANGE_CLASS, + ExchangeDefaults.TOPIC_EXCHANGE_CLASS}; private final VirtualHost _host; - private Map<AMQShortString, ExchangeType<? extends Exchange>> _exchangeClassMap = new HashMap<AMQShortString, ExchangeType<? extends Exchange>>(); + private Map<String, ExchangeType<? extends Exchange>> _exchangeClassMap = new HashMap<String, ExchangeType<? extends Exchange>>(); public DefaultExchangeFactory(VirtualHost host) { @@ -61,7 +61,7 @@ public class DefaultExchangeFactory implements ExchangeFactory Iterable<ExchangeType> exchangeTypes = loadExchangeTypes(); for (ExchangeType<?> exchangeType : exchangeTypes) { - AMQShortString typeName = exchangeType.getName(); + String typeName = exchangeType.getType(); if(LOGGER.isDebugEnabled()) { @@ -80,11 +80,11 @@ public class DefaultExchangeFactory implements ExchangeFactory _exchangeClassMap.put(typeName, exchangeType); } - for(AMQShortString type : BASE_EXCHANGE_TYPES) + for(String type : BASE_EXCHANGE_TYPES) { if(!_exchangeClassMap.containsKey(type)) { - throw new IllegalStateException("Did not find expected exchange type: " + type.asString()); + throw new IllegalStateException("Did not find expected exchange type: " + type); } } } @@ -114,19 +114,12 @@ public class DefaultExchangeFactory implements ExchangeFactory { UUID id = UUIDGenerator.generateExchangeUUID(exchange, _host.getName()); - return createExchange(id, new AMQShortString(exchange), new AMQShortString(type), durable, autoDelete); + return createExchange(id, exchange, type, durable, autoDelete); } public Exchange createExchange(UUID id, String exchange, String type, boolean durable, boolean autoDelete) throws AMQException { - return createExchange(id, new AMQShortString(exchange), new AMQShortString(type), durable, autoDelete); - } - - private Exchange createExchange(UUID id, AMQShortString exchange, AMQShortString type, boolean durable, - boolean autoDelete) - throws AMQException - { // Check access if (!_host.getSecurityManager().authoriseCreateExchange(autoDelete, durable, exchange, null, null, null, type)) { @@ -143,4 +136,10 @@ public class DefaultExchangeFactory implements ExchangeFactory Exchange e = exchType.newInstance(id, _host, exchange, durable, autoDelete); return e; } + + @Override + public Exchange restoreExchange(UUID id, String exchange, String type, boolean autoDelete) throws AMQException + { + return createExchange(id, exchange, type, true, autoDelete); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java index 75c489c731..b54f995b5e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java @@ -27,6 +27,7 @@ import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -40,20 +41,23 @@ import java.util.concurrent.ConcurrentMap; public class DefaultExchangeRegistry implements ExchangeRegistry { private static final Logger LOGGER = Logger.getLogger(DefaultExchangeRegistry.class); - /** * Maps from exchange name to exchange instance */ private ConcurrentMap<String, Exchange> _exchangeMap = new ConcurrentHashMap<String, Exchange>(); private Exchange _defaultExchange; - private VirtualHost _host; + + private final VirtualHost _host; + private final QueueRegistry _queueRegistry; + private final Collection<RegistryChangeListener> _listeners = Collections.synchronizedCollection(new ArrayList<RegistryChangeListener>()); - public DefaultExchangeRegistry(VirtualHost host) + public DefaultExchangeRegistry(VirtualHost host, QueueRegistry queueRegistry) { _host = host; + _queueRegistry = queueRegistry; } public void initialise(ExchangeFactory exchangeFactory) throws AMQException @@ -61,10 +65,10 @@ public class DefaultExchangeRegistry implements ExchangeRegistry //create 'standard' exchanges: new ExchangeInitialiser().initialise(exchangeFactory, this, getDurableConfigurationStore()); - _defaultExchange = new DefaultExchange(); + _defaultExchange = new DefaultExchange(_queueRegistry); UUID defaultExchangeId = - UUIDGenerator.generateExchangeUUID(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString(), _host.getName()); + UUIDGenerator.generateExchangeUUID(ExchangeDefaults.DEFAULT_EXCHANGE_NAME, _host.getName()); _defaultExchange.initialise(defaultExchangeId, _host, ExchangeDefaults.DEFAULT_EXCHANGE_NAME,false, false); @@ -77,7 +81,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry public void registerExchange(Exchange exchange) throws AMQException { - _exchangeMap.put(exchange.getNameShortString().toString(), exchange); + _exchangeMap.put(exchange.getName(), exchange); synchronized (_listeners) { for(RegistryChangeListener listener : _listeners) @@ -197,7 +201,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry public boolean isReservedExchangeName(String name) { - if (name == null || ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(name) + if (name == null || ExchangeDefaults.DEFAULT_EXCHANGE_NAME.equals(name) || name.startsWith("amq.") || name.startsWith("qpid.")) { return true; @@ -205,7 +209,7 @@ public class DefaultExchangeRegistry implements ExchangeRegistry Collection<ExchangeType<? extends Exchange>> registeredTypes = _host.getExchangeTypes(); for (ExchangeType<? extends Exchange> type : registeredTypes) { - if (type.getDefaultExchangeName().toString().equals(name)) + if (type.getDefaultExchangeName().equals(name)) { return true; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java index 2e2a93d638..1e022c994e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java @@ -180,10 +180,9 @@ public class DirectExchange extends AbstractExchange { String bindingKey = binding.getBindingKey(); AMQQueue queue = binding.getQueue(); - AMQShortString routingKey = AMQShortString.valueOf(bindingKey); assert queue != null; - assert routingKey != null; + assert bindingKey != null; BindingSet bindings = _bindingsByKey.get(bindingKey); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java index afe00e1b60..d61d10155e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java @@ -33,16 +33,11 @@ public class DirectExchangeType implements ExchangeType<DirectExchange> @Override public String getType() { - return getName().toString(); - } - - public AMQShortString getName() - { return ExchangeDefaults.DIRECT_EXCHANGE_CLASS; } public DirectExchange newInstance(UUID id, VirtualHost host, - AMQShortString name, + String name, boolean durable, boolean autoDelete) throws AMQException { @@ -51,7 +46,7 @@ public class DirectExchangeType implements ExchangeType<DirectExchange> return exch; } - public AMQShortString getDefaultExchangeName() + public String getDefaultExchangeName() { return ExchangeDefaults.DIRECT_EXCHANGE_NAME; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java index 735072cc82..d05e731daa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java @@ -23,8 +23,6 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.plugin.ExchangeType; @@ -39,7 +37,7 @@ import java.util.UUID; public interface Exchange extends ExchangeReferrer { - void initialise(UUID id, VirtualHost host, AMQShortString name, boolean durable, boolean autoDelete) + void initialise(UUID id, VirtualHost host, String name, boolean durable, boolean autoDelete) throws AMQException; @@ -47,11 +45,9 @@ public interface Exchange extends ExchangeReferrer String getName(); - AMQShortString getNameShortString(); - ExchangeType getType(); - AMQShortString getTypeShortString(); + String getTypeName(); boolean isDurable(); @@ -107,30 +103,32 @@ public interface Exchange extends ExchangeReferrer /** * Determines whether a message would be isBound to a particular queue using a specific routing key and arguments - * @param routingKey + * @param bindingKey * @param arguments * @param queue * @return * @throws AMQException */ - boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue); + + boolean isBound(String bindingKey, Map<String,Object> arguments, AMQQueue queue); /** * Determines whether a message would be isBound to a particular queue using a specific routing key - * @param routingKey + * @param bindingKey * @param queue * @return * @throws AMQException */ - boolean isBound(AMQShortString routingKey, AMQQueue queue); + + boolean isBound(String bindingKey, AMQQueue queue); /** * Determines whether a message is routing to any queue using a specific _routing key - * @param routingKey + * @param bindingKey * @return * @throws AMQException */ - boolean isBound(AMQShortString routingKey); + boolean isBound(String bindingKey); /** * Returns true if this exchange has at least one binding associated with it. @@ -141,20 +139,14 @@ public interface Exchange extends ExchangeReferrer Collection<Binding> getBindings(); - boolean isBound(String bindingKey); - boolean isBound(AMQQueue queue); boolean isBound(Map<String, Object> arguments); - boolean isBound(String bindingKey, AMQQueue queue); - boolean isBound(String bindingKey, Map<String, Object> arguments); boolean isBound(Map<String, Object> arguments, AMQQueue queue); - boolean isBound(String bindingKey, Map<String,Object> arguments, AMQQueue queue); - void removeReference(ExchangeReferrer exchange); void addReference(ExchangeReferrer exchange); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java index 3ccfa51499..f364691666 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java @@ -38,5 +38,6 @@ public interface ExchangeFactory Exchange createExchange(String exchange, String type, boolean durable, boolean autoDelete) throws AMQException; Exchange createExchange(UUID id, String exchange, String type, boolean durable, boolean autoDelete) throws AMQException; + Exchange restoreExchange(UUID id, String exchange, String type, boolean autoDelete) throws AMQException; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java index fd7c6a7fe0..6dbc1d54d1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeInitialiser.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.store.DurableConfigurationStoreHelper; import org.apache.qpid.server.store.DurableConfigurationStore; @@ -33,7 +32,7 @@ public class ExchangeInitialiser { for (ExchangeType<? extends Exchange> type : factory.getRegisteredTypes()) { - define (registry, factory, type.getDefaultExchangeName().toString(), type.getName().toString(), store); + define (registry, factory, type.getDefaultExchangeName(), type.getType(), store); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java index 43276d8eca..ac864df02c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java @@ -33,15 +33,10 @@ public class FanoutExchangeType implements ExchangeType<FanoutExchange> @Override public String getType() { - return getName().toString(); - } - - public AMQShortString getName() - { return ExchangeDefaults.FANOUT_EXCHANGE_CLASS; } - public FanoutExchange newInstance(UUID id, VirtualHost host, AMQShortString name, + public FanoutExchange newInstance(UUID id, VirtualHost host, String name, boolean durable, boolean autoDelete) throws AMQException { @@ -50,7 +45,7 @@ public class FanoutExchangeType implements ExchangeType<FanoutExchange> return exch; } - public AMQShortString getDefaultExchangeName() + public String getDefaultExchangeName() { return ExchangeDefaults.FANOUT_EXCHANGE_NAME; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FilterSupport.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FilterSupport.java index e0d1ac8695..e78516cf69 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FilterSupport.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FilterSupport.java @@ -43,13 +43,6 @@ public class FilterSupport private static final Map<String, WeakReference<JMSSelectorFilter>> _selectorCache = Collections.synchronizedMap(new WeakHashMap<String, WeakReference<JMSSelectorFilter>>()); - static MessageFilter createJMSSelectorFilter(FieldTable args) throws AMQInvalidArgumentException - { - final String selectorString = args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue()); - return getMessageFilter(selectorString); - } - - static MessageFilter createJMSSelectorFilter(Map<String, Object> args) throws AMQInvalidArgumentException { final String selectorString = (String) args.get(AMQPFilterTypes.JMS_SELECTOR.toString()); @@ -85,18 +78,20 @@ public class FilterSupport return selector; } - static boolean argumentsContainFilter(final FieldTable args) + public static boolean argumentsContainFilter(final Map<String, Object> args) { return argumentsContainNoLocal(args) || argumentsContainJMSSelector(args); } - static boolean argumentsContainFilter(final Map<String, Object> args) + public static void removeFilters(final Map<String, Object> args) { - return argumentsContainNoLocal(args) || argumentsContainJMSSelector(args); + args.remove(AMQPFilterTypes.JMS_SELECTOR.toString()); + args.remove(AMQPFilterTypes.NO_LOCAL.toString()); } + static boolean argumentsContainNoLocal(final Map<String, Object> args) { return args != null @@ -104,29 +99,12 @@ public class FilterSupport && Boolean.TRUE.equals(args.get(AMQPFilterTypes.NO_LOCAL.toString())); } - - static boolean argumentsContainNoLocal(final FieldTable args) - { - return args != null - && args.containsKey(AMQPFilterTypes.NO_LOCAL.getValue()) - && Boolean.TRUE.equals(args.get(AMQPFilterTypes.NO_LOCAL.getValue())); - } - - static boolean argumentsContainJMSSelector(final Map<String,Object> args) { return args != null && (args.get(AMQPFilterTypes.JMS_SELECTOR.toString()) instanceof String) && ((String)args.get(AMQPFilterTypes.JMS_SELECTOR.toString())).trim().length() != 0; } - - static boolean argumentsContainJMSSelector(final FieldTable args) - { - return args != null && (args.containsKey(AMQPFilterTypes.JMS_SELECTOR.getValue()) - && args.getString(AMQPFilterTypes.JMS_SELECTOR.getValue()).trim().length() != 0); - } - - static MessageFilter createMessageFilter(final Map<String,Object> args, AMQQueue queue) throws AMQInvalidArgumentException { if(argumentsContainNoLocal(args)) @@ -145,24 +123,6 @@ public class FilterSupport } } - static MessageFilter createMessageFilter(final FieldTable args, AMQQueue queue) throws AMQInvalidArgumentException - { - if(argumentsContainNoLocal(args)) - { - MessageFilter filter = new NoLocalFilter(queue); - - if(argumentsContainJMSSelector(args)) - { - filter = new CompoundFilter(filter, createJMSSelectorFilter(args)); - } - return filter; - } - else - { - return createJMSSelectorFilter(args); - } - } - static final class NoLocalFilter implements MessageFilter { private final AMQQueue _queue; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java index 9fb745d553..41dd7e010c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java @@ -89,7 +89,7 @@ public class HeadersExchange extends AbstractExchange { if (_logger.isDebugEnabled()) { - _logger.debug("Exchange " + getNameShortString() + ": routing message with headers " + payload.getMessageHeader()); + _logger.debug("Exchange " + getName() + ": routing message with headers " + payload.getMessageHeader()); } LinkedHashSet<BaseQueue> queues = new LinkedHashSet<BaseQueue>(); @@ -104,8 +104,8 @@ public class HeadersExchange extends AbstractExchange if (_logger.isDebugEnabled()) { - _logger.debug("Exchange " + getNameShortString() + ": delivering message with headers " + - payload.getMessageHeader() + " to " + b.getQueue().getNameShortString()); + _logger.debug("Exchange " + getName() + ": delivering message with headers " + + payload.getMessageHeader() + " to " + b.getQueue().getName()); } queues.add(b.getQueue()); } @@ -118,11 +118,10 @@ public class HeadersExchange extends AbstractExchange { String bindingKey = binding.getBindingKey(); AMQQueue queue = binding.getQueue(); - AMQShortString routingKey = AMQShortString.valueOf(bindingKey); Map<String,Object> args = binding.getArguments(); assert queue != null; - assert routingKey != null; + assert bindingKey != null; CopyOnWriteArraySet<Binding> bindings = _bindingsByKey.get(bindingKey); @@ -138,7 +137,7 @@ public class HeadersExchange extends AbstractExchange if(_logger.isDebugEnabled()) { - _logger.debug("Exchange " + getNameShortString() + ": Binding " + queue.getNameShortString() + + _logger.debug("Exchange " + getName() + ": Binding " + queue.getName() + " with binding key '" +bindingKey + "' and args: " + args); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java index 324a4b9e51..42d04f5a97 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java @@ -33,15 +33,10 @@ public class HeadersExchangeType implements ExchangeType<HeadersExchange> @Override public String getType() { - return getName().toString(); - } - - public AMQShortString getName() - { return ExchangeDefaults.HEADERS_EXCHANGE_CLASS; } - public HeadersExchange newInstance(UUID id, VirtualHost host, AMQShortString name, boolean durable, + public HeadersExchange newInstance(UUID id, VirtualHost host, String name, boolean durable, boolean autoDelete) throws AMQException { HeadersExchange exch = new HeadersExchange(); @@ -50,7 +45,7 @@ public class HeadersExchangeType implements ExchangeType<HeadersExchange> return exch; } - public AMQShortString getDefaultExchangeName() + public String getDefaultExchangeName() { return ExchangeDefaults.HEADERS_EXCHANGE_NAME; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java index 9d41856dc0..6b8b84f5dd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java @@ -50,10 +50,10 @@ public class TopicExchange extends AbstractExchange private final TopicParser _parser = new TopicParser(); - private final Map<AMQShortString, TopicExchangeResult> _topicExchangeResults = - new ConcurrentHashMap<AMQShortString, TopicExchangeResult>(); + private final Map<String, TopicExchangeResult> _topicExchangeResults = + new ConcurrentHashMap<String, TopicExchangeResult>(); - private final Map<Binding, FieldTable> _bindings = new HashMap<Binding, FieldTable>(); + private final Map<Binding, Map<String,Object>> _bindings = new HashMap<Binding, Map<String,Object>>(); public TopicExchange() { @@ -62,21 +62,21 @@ public class TopicExchange extends AbstractExchange protected synchronized void registerQueue(final Binding binding) throws AMQInvalidArgumentException { - AMQShortString rKey = new AMQShortString(binding.getBindingKey()) ; + final String bindingKey = binding.getBindingKey(); AMQQueue queue = binding.getQueue(); - FieldTable args = FieldTable.convertToFieldTable(binding.getArguments()); + Map<String,Object> args = binding.getArguments(); assert queue != null; - assert rKey != null; + assert bindingKey != null; - _logger.debug("Registering queue " + queue.getNameShortString() + " with routing key " + rKey); + _logger.debug("Registering queue " + queue.getName() + " with routing key " + bindingKey); - AMQShortString routingKey = TopicNormalizer.normalize(rKey); + String routingKey = TopicNormalizer.normalize(bindingKey); if(_bindings.containsKey(binding)) { - FieldTable oldArgs = _bindings.get(binding); + Map<String,Object> oldArgs = _bindings.get(binding); TopicExchangeResult result = _topicExchangeResults.get(routingKey); if(FilterSupport.argumentsContainFilter(args)) @@ -150,9 +150,9 @@ public class TopicExchange extends AbstractExchange public ArrayList<BaseQueue> doRoute(InboundMessage payload) { - final AMQShortString routingKey = payload.getRoutingKeyShortString() == null - ? AMQShortString.EMPTY_STRING - : payload.getRoutingKeyShortString(); + final String routingKey = payload.getRoutingKey() == null + ? "" + : payload.getRoutingKey(); final Collection<AMQQueue> matchedQueues = getMatchedQueues(payload, routingKey); @@ -181,8 +181,8 @@ public class TopicExchange extends AbstractExchange { if(_bindings.containsKey(binding)) { - FieldTable bindingArgs = _bindings.remove(binding); - AMQShortString bindingKey = TopicNormalizer.normalize(new AMQShortString(binding.getBindingKey())); + Map<String,Object> bindingArgs = _bindings.remove(binding); + String bindingKey = TopicNormalizer.normalize(binding.getBindingKey()); TopicExchangeResult result = _topicExchangeResults.get(bindingKey); result.removeBinding(binding); @@ -211,7 +211,7 @@ public class TopicExchange extends AbstractExchange } } - private Collection<AMQQueue> getMatchedQueues(InboundMessage message, AMQShortString routingKey) + private Collection<AMQQueue> getMatchedQueues(InboundMessage message, String routingKey) { Collection<TopicMatcherResult> results = _parser.parse(routingKey); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java index 5882d0cdc6..3bbae700be 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java @@ -33,16 +33,11 @@ public class TopicExchangeType implements ExchangeType<TopicExchange> @Override public String getType() { - return getName().toString(); - } - - public AMQShortString getName() - { return ExchangeDefaults.TOPIC_EXCHANGE_CLASS; } public TopicExchange newInstance(UUID id, VirtualHost host, - AMQShortString name, + String name, boolean durable, boolean autoDelete) throws AMQException { @@ -51,7 +46,7 @@ public class TopicExchangeType implements ExchangeType<TopicExchange> return exch; } - public AMQShortString getDefaultExchangeName() + public String getDefaultExchangeName() { return ExchangeDefaults.TOPIC_EXCHANGE_NAME; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java index dad951c3ca..85338c0760 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java @@ -20,8 +20,8 @@ */ package org.apache.qpid.server.exchange.topic; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.AMQShortStringTokenizer; +import java.util.Arrays; +import java.util.Iterator; import java.util.ArrayList; import java.util.Collection; @@ -44,7 +44,7 @@ public class TopicMatcherDFAState private final Collection<TopicMatcherResult> _results; private final Map<TopicWord, TopicMatcherDFAState> _nextStateMap; - private static final byte TOPIC_DELIMITTER = (byte)'.'; + private static final String TOPIC_DELIMITTER = "\\."; public TopicMatcherDFAState(Map<TopicWord, TopicMatcherDFAState> nextStateMap, @@ -67,19 +67,19 @@ public class TopicMatcherDFAState } - public Collection<TopicMatcherResult> parse(TopicWordDictionary dictionary, AMQShortString routingKey) + public Collection<TopicMatcherResult> parse(TopicWordDictionary dictionary, String routingKey) { - return parse(dictionary, routingKey.tokenize(TOPIC_DELIMITTER)); + return parse(dictionary, Arrays.asList(routingKey.split(TOPIC_DELIMITTER)).iterator()); } private Collection<TopicMatcherResult> parse(final TopicWordDictionary dictionary, - final AMQShortStringTokenizer tokens) + final Iterator<String> tokens) { - if(!tokens.hasMoreTokens()) + if(!tokens.hasNext()) { return _results; } - TopicWord word = dictionary.getWord(tokens.nextToken()); + TopicWord word = dictionary.getWord(tokens.next()); TopicMatcherDFAState nextState = _nextStateMap.get(word); if(nextState == null && word != TopicWord.ANY_WORD) { @@ -96,7 +96,7 @@ public class TopicMatcherDFAState } return nextState.parse(dictionary, tokens); - + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicNormalizer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicNormalizer.java index aac696ae2d..e45d6a539d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicNormalizer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicNormalizer.java @@ -20,46 +20,36 @@ */ package org.apache.qpid.server.exchange.topic; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.AMQShortStringTokenizer; - +import java.util.Arrays; +import java.util.Iterator; import java.util.ArrayList; import java.util.List; public class TopicNormalizer { - private static final byte TOPIC_SEPARATOR = (byte)'.'; - private static final byte HASH_BYTE = (byte)'#'; - private static final byte STAR_BYTE = (byte)'*'; - private static final AMQShortString TOPIC_SEPARATOR_AS_SHORTSTRING = new AMQShortString("."); - private static final AMQShortString AMQP_STAR_TOKEN = new AMQShortString("*"); - private static final AMQShortString AMQP_HASH_TOKEN = new AMQShortString("#"); + private static final String STAR_TOKEN = "*"; + private static final String HASH_TOKEN = "#"; + private static final String SEPARATOR = "."; + private TopicNormalizer() { } - public static AMQShortString normalize(AMQShortString routingKey) + public static String normalize(String routingKey) { if(routingKey == null) { - return AMQShortString.EMPTY_STRING; + return ""; } - else if(!(routingKey.contains(HASH_BYTE) || routingKey.contains(STAR_BYTE))) + else if(!(routingKey.contains(HASH_TOKEN) || !routingKey.contains(STAR_TOKEN))) { return routingKey; } else { - AMQShortStringTokenizer routingTokens = routingKey.tokenize(TOPIC_SEPARATOR); - - List<AMQShortString> subscriptionList = new ArrayList<AMQShortString>(); - - while (routingTokens.hasMoreTokens()) - { - subscriptionList.add(routingTokens.nextToken()); - } + List<String> subscriptionList = new ArrayList<String>(Arrays.asList(routingKey.split("\\."))); int size = subscriptionList.size(); @@ -68,9 +58,9 @@ public class TopicNormalizer // if there are more levels if ((index + 1) < size) { - if (subscriptionList.get(index).equals(AMQP_HASH_TOKEN)) + if (subscriptionList.get(index).equals(HASH_TOKEN)) { - if (subscriptionList.get(index + 1).equals(AMQP_HASH_TOKEN)) + if (subscriptionList.get(index + 1).equals(HASH_TOKEN)) { // we don't need #.# delete this one subscriptionList.remove(index); @@ -79,7 +69,7 @@ public class TopicNormalizer index--; } - if (subscriptionList.get(index + 1).equals(AMQP_STAR_TOKEN)) + if (subscriptionList.get(index + 1).equals(STAR_TOKEN)) { // we don't want #.* swap to *.# // remove it and put it in at index + 1 @@ -89,11 +79,14 @@ public class TopicNormalizer } // if we have more levels } - - - AMQShortString normalizedString = AMQShortString.join(subscriptionList, TOPIC_SEPARATOR_AS_SHORTSTRING); - - return normalizedString; + Iterator<String> iter = subscriptionList.iterator(); + StringBuilder builder = new StringBuilder(iter.next()); + while(iter.hasNext()) + { + builder.append(SEPARATOR).append(iter.next()); + } + return builder.toString(); } } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java index 6f47e4e7f2..214ca23b49 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java @@ -20,9 +20,6 @@ */ package org.apache.qpid.server.exchange.topic; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.AMQShortStringTokenizer; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -35,7 +32,7 @@ import java.util.concurrent.atomic.AtomicReference; public class TopicParser { - private static final byte TOPIC_DELIMITER = (byte)'.'; + private static final String TOPIC_DELIMITER = "\\."; private final TopicWordDictionary _dictionary = new TopicWordDictionary(); private final AtomicReference<TopicMatcherDFAState> _stateMachine = new AtomicReference<TopicMatcherDFAState>(); @@ -98,7 +95,7 @@ public class TopicParser } - public void addBinding(AMQShortString bindingKey, TopicMatcherResult result) + public void addBinding(String bindingKey, TopicMatcherResult result) { TopicMatcherDFAState startingStateMachine; @@ -121,7 +118,7 @@ public class TopicParser } - public Collection<TopicMatcherResult> parse(AMQShortString routingKey) + public Collection<TopicMatcherResult> parse(String routingKey) { TopicMatcherDFAState stateMachine = _stateMachine.get(); if(stateMachine == null) @@ -135,7 +132,7 @@ public class TopicParser } - TopicMatcherDFAState createStateMachine(AMQShortString bindingKey, TopicMatcherResult result) + TopicMatcherDFAState createStateMachine(String bindingKey, TopicMatcherResult result) { List<TopicWord> wordList = createTopicWordList(bindingKey); int wildCards = 0; @@ -422,16 +419,16 @@ public class TopicParser } - private List<TopicWord> createTopicWordList(final AMQShortString bindingKey) + private List<TopicWord> createTopicWordList(final String bindingKey) { - AMQShortStringTokenizer tokens = bindingKey.tokenize(TOPIC_DELIMITER); + String[] tokens = bindingKey.split(TOPIC_DELIMITER); TopicWord previousWord = null; List<TopicWord> wordList = new ArrayList<TopicWord>(); - while(tokens.hasMoreTokens()) + for(String token : tokens) { - TopicWord nextWord = _dictionary.getOrCreateWord(tokens.nextToken()); + TopicWord nextWord = _dictionary.getOrCreateWord(token); if(previousWord == TopicWord.WILDCARD_WORD) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java index 7345d30a0a..c905299733 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java @@ -21,29 +21,17 @@ package org.apache.qpid.server.exchange.topic; -import org.apache.qpid.framing.AMQShortString; - public final class TopicWord { public static final TopicWord ANY_WORD = new TopicWord("*"); public static final TopicWord WILDCARD_WORD = new TopicWord("#"); private String _word; - public TopicWord() - { - - } - public TopicWord(String s) { _word = s; } - public TopicWord(final AMQShortString name) - { - _word = name.toString(); - } - public String toString() { return _word; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java index 181c26dd66..24c41ee7da 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java @@ -20,27 +20,20 @@ */ package org.apache.qpid.server.exchange.topic; -import org.apache.qpid.framing.AMQShortString; - import java.util.concurrent.ConcurrentHashMap; public class TopicWordDictionary { - private final ConcurrentHashMap<AMQShortString,TopicWord> _dictionary = - new ConcurrentHashMap<AMQShortString,TopicWord>(); - - + private final ConcurrentHashMap<String,TopicWord> _dictionary = + new ConcurrentHashMap<String,TopicWord>(); public TopicWordDictionary() { - _dictionary.put(new AMQShortString("*"), TopicWord.ANY_WORD); - _dictionary.put(new AMQShortString("#"), TopicWord.WILDCARD_WORD); + _dictionary.put("*", TopicWord.ANY_WORD); + _dictionary.put("#", TopicWord.WILDCARD_WORD); } - - - - public TopicWord getOrCreateWord(AMQShortString name) + public TopicWord getOrCreateWord(String name) { TopicWord word = _dictionary.putIfAbsent(name, new TopicWord(name)); if(word == null) @@ -51,7 +44,7 @@ public class TopicWordDictionary } - public TopicWord getWord(AMQShortString name) + public TopicWord getWord(String name) { TopicWord word = _dictionary.get(name); if(word == null) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java index 56f0a6e08d..07049a6c97 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java @@ -14,9 +14,9 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.filter; @@ -35,7 +35,7 @@ import java.util.Map; public class FilterManagerFactory { - + private final static Logger _logger = Logger.getLogger(FilterManagerFactory.class); private FilterManagerFactory() @@ -44,25 +44,23 @@ public class FilterManagerFactory //fixme move to a common class so it can be refered to from client code. - public static FilterManager createManager(FieldTable filters) throws AMQException + public static FilterManager createManager(Map<String,Object> filters) throws AMQException { FilterManager manager = null; if (filters != null) { - - - if(filters.containsKey(AMQPFilterTypes.JMS_SELECTOR.getValue())) + if(filters.containsKey(AMQPFilterTypes.JMS_SELECTOR.toString())) { - String selector = filters.getString(AMQPFilterTypes.JMS_SELECTOR.getValue()); + Object selector = filters.get(AMQPFilterTypes.JMS_SELECTOR.toString()); - if (selector != null && !selector.equals("")) + if (selector instanceof String && !selector.equals("")) { manager = new SimpleFilterManager(); try { - manager.add(new JMSSelectorFilter(selector)); + manager.add(new JMSSelectorFilter((String)selector)); } catch (ParseException e) { @@ -91,9 +89,5 @@ public class FilterManagerFactory return manager; } - - public static FilterManager createManager(Map<String,Object> map) throws AMQException - { - return createManager(FieldTable.convertToFieldTable(map)); - } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java deleted file mode 100644 index 035bf25e04..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java +++ /dev/null @@ -1,249 +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.handler; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.QueueDeclareBody; -import org.apache.qpid.framing.QueueDeclareOkBody; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.state.AMQStateManager; -import org.apache.qpid.server.state.StateAwareMethodListener; -import org.apache.qpid.server.store.DurableConfigurationStoreHelper; -import org.apache.qpid.server.store.DurableConfigurationStore; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import java.util.Map; -import java.util.UUID; - -public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclareBody> -{ - private static final Logger _logger = Logger.getLogger(QueueDeclareHandler.class); - - private static final QueueDeclareHandler _instance = new QueueDeclareHandler(); - - public static QueueDeclareHandler getInstance() - { - return _instance; - } - - public void methodReceived(AMQStateManager stateManager, QueueDeclareBody body, int channelId) throws AMQException - { - final AMQProtocolSession protocolConnection = stateManager.getProtocolSession(); - final AMQSessionModel session = protocolConnection.getChannel(channelId); - VirtualHost virtualHost = protocolConnection.getVirtualHost(); - QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - DurableConfigurationStore store = virtualHost.getDurableConfigurationStore(); - - final AMQShortString queueName; - - // if we aren't given a queue name, we create one which we return to the client - if ((body.getQueue() == null) || (body.getQueue().length() == 0)) - { - queueName = createName(); - } - else - { - queueName = body.getQueue().intern(); - } - - AMQQueue queue; - - //TODO: do we need to check that the queue already exists with exactly the same "configuration"? - - AMQChannel channel = protocolConnection.getChannel(channelId); - - if (channel == null) - { - throw body.getChannelNotFoundException(channelId); - } - - synchronized (queueRegistry) - { - queue = queueRegistry.getQueue(queueName); - - AMQSessionModel owningSession = null; - - if (queue != null) - { - owningSession = queue.getExclusiveOwningSession(); - } - - if (queue == null) - { - if (body.getPassive()) - { - String msg = "Queue: " + queueName + " not found on VirtualHost(" + virtualHost + ")."; - throw body.getChannelException(AMQConstant.NOT_FOUND, msg); - } - else - { - queue = createQueue(queueName, body, virtualHost, protocolConnection); - queue.setAuthorizationHolder(protocolConnection); - if (queue.isDurable() && !queue.isAutoDelete()) - { - DurableConfigurationStoreHelper.createQueue(store, queue, body.getArguments()); - } - if(body.getAutoDelete()) - { - queue.setDeleteOnNoConsumers(true); - } - queueRegistry.registerQueue(queue); - if (body.getExclusive()) - { - queue.setExclusiveOwningSession(protocolConnection.getChannel(channelId)); - queue.setAuthorizationHolder(protocolConnection); - - if(!body.getDurable()) - { - final AMQQueue q = queue; - final AMQProtocolSession.Task sessionCloseTask = new AMQProtocolSession.Task() - { - public void doTask(AMQProtocolSession session) throws AMQException - { - q.setExclusiveOwningSession(null); - } - }; - protocolConnection.addSessionCloseTask(sessionCloseTask); - queue.addQueueDeleteTask(new AMQQueue.Task() { - public void doTask(AMQQueue queue) throws AMQException - { - protocolConnection.removeSessionCloseTask(sessionCloseTask); - } - }); - } - } - } - } - else if (queue.isExclusive() && !queue.isDurable() && (owningSession == null || owningSession.getConnectionModel() != protocolConnection)) - { - throw body.getConnectionException(AMQConstant.NOT_ALLOWED, - "Queue " + queue.getNameShortString() + " is exclusive, but not created on this Connection."); - } - else if(!body.getPassive() && ((queue.isExclusive()) != body.getExclusive())) - { - - throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getNameShortString() + "' with different exclusivity (was: " - + queue.isExclusive() + " requested " + body.getExclusive() + ")"); - } - else if (!body.getPassive() && body.getExclusive() && !(queue.isDurable() ? String.valueOf(queue.getOwner()).equals(session.getClientID()) : (owningSession == null || owningSession.getConnectionModel() == protocolConnection))) - { - throw body.getChannelException(AMQConstant.ALREADY_EXISTS, "Cannot declare queue('" + queueName + "'), " - + "as exclusive queue with same name " - + "declared on another client ID('" - + queue.getOwner() + "') your clientID('" + session.getClientID() + "')"); - - } - else if(!body.getPassive() && queue.isAutoDelete() != body.getAutoDelete()) - { - throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getNameShortString() + "' with different auto-delete (was: " - + queue.isAutoDelete() + " requested " + body.getAutoDelete() + ")"); - } - else if(!body.getPassive() && queue.isDurable() != body.getDurable()) - { - throw body.getChannelException(AMQConstant.ALREADY_EXISTS, - "Cannot re-declare queue '" + queue.getNameShortString() + "' with different durability (was: " - + queue.isDurable() + " requested " + body.getDurable() + ")"); - } - - - - //set this as the default queue on the channel: - channel.setDefaultQueue(queue); - } - - if (!body.getNowait()) - { - channel.sync(); - MethodRegistry methodRegistry = protocolConnection.getMethodRegistry(); - QueueDeclareOkBody responseBody = - methodRegistry.createQueueDeclareOkBody(queueName, - queue.getMessageCount(), - queue.getConsumerCount()); - protocolConnection.writeFrame(responseBody.generateFrame(channelId)); - - _logger.info("Queue " + queueName + " declared successfully"); - } - } - - protected AMQShortString createName() - { - return new AMQShortString("tmp_" + UUID.randomUUID()); - } - - protected AMQQueue createQueue(final AMQShortString queueName, - QueueDeclareBody body, - VirtualHost virtualHost, - final AMQProtocolSession session) - throws AMQException - { - final QueueRegistry registry = virtualHost.getQueueRegistry(); - String owner = body.getExclusive() ? AMQShortString.toString(session.getContextKey()) : null; - - Map<String, Object> arguments = FieldTable.convertToMap(body.getArguments()); - String queueNameString = AMQShortString.toString(queueName); - - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueNameString, virtualHost.getName()), - queueNameString, body.getDurable(), owner, body.getAutoDelete(), - body.getExclusive(),virtualHost, arguments); - - if (body.getExclusive() && !body.getDurable()) - { - final AMQProtocolSession.Task deleteQueueTask = - new AMQProtocolSession.Task() - { - public void doTask(AMQProtocolSession session) throws AMQException - { - if (registry.getQueue(queueName) == queue) - { - queue.delete(); - } - } - }; - - session.addSessionCloseTask(deleteQueueTask); - - queue.addQueueDeleteTask(new AMQQueue.Task() - { - public void doTask(AMQQueue queue) - { - session.removeSessionCloseTask(deleteQueueTask); - } - }); - } - - return queue; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java index 5528a05360..dfffbdbb5f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java @@ -25,15 +25,17 @@ import org.apache.log4j.spi.ErrorHandler; import org.apache.log4j.spi.Filter; import org.apache.log4j.spi.LoggingEvent; import org.apache.log4j.spi.ThrowableInformation; +import org.apache.qpid.server.configuration.BrokerProperties; public class LogRecorder implements Appender, Iterable<LogRecorder.Record> { + private static final int DEFAULT_BUFFER_SIZE = 4096; private ErrorHandler _errorHandler; private Filter _filter; private String _name; private long _recordId; - private final int _bufferSize = 4096; + private final int _bufferSize = Integer.getInteger(BrokerProperties.PROPERTY_LOG_RECORDS_BUFFER_SIZE, DEFAULT_BUFFER_SIZE); private final int _mask = _bufferSize - 1; private Record[] _records = new Record[_bufferSize]; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java index 50a7e67583..d23122ac5d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPChannelActor.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.logging.actors; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.subjects.ChannelLogSubject; @@ -45,7 +45,7 @@ public class AMQPChannelActor extends AbstractActor * @param channel The Channel for this LogActor * @param rootLogger The root Logger that this LogActor should use */ - public AMQPChannelActor(AMQChannel channel, RootMessageLogger rootLogger) + public AMQPChannelActor(AMQSessionModel channel, RootMessageLogger rootLogger) { super(rootLogger); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java index 1b4bc91bc1..99e11bf9ae 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/actors/AMQPConnectionActor.java @@ -14,16 +14,15 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.logging.actors; import org.apache.qpid.server.logging.RootMessageLogger; import org.apache.qpid.server.logging.subjects.ConnectionLogSubject; -import org.apache.qpid.server.protocol.AMQProtocolSession; - +import org.apache.qpid.server.protocol.AMQConnectionModel; /** @@ -39,7 +38,7 @@ public class AMQPConnectionActor extends AbstractActor { private ConnectionLogSubject _logSubject; - public AMQPConnectionActor(AMQProtocolSession session, RootMessageLogger rootLogger) + public AMQPConnectionActor(AMQConnectionModel session, RootMessageLogger rootLogger) { super(rootLogger); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java index 6f18cbcc6b..a633162e85 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/BindingLogSubject.java @@ -42,9 +42,9 @@ public class BindingLogSubject extends AbstractLogSubject { setLogStringWithFormat(BINDING_FORMAT, queue.getVirtualHost().getName(), - exchange.getTypeShortString(), - exchange.getNameShortString(), - queue.getNameShortString(), + exchange.getType().getType(), + exchange.getName(), + queue.getName(), routingKey); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java index bcb9cb2ac4..5b0e34b73e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java @@ -20,20 +20,16 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.transport.ServerConnection; -import org.apache.qpid.server.transport.ServerSession; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.AMQSessionModel; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT; public class ChannelLogSubject extends AbstractLogSubject { - public ChannelLogSubject(AMQChannel channel) + public ChannelLogSubject(AMQSessionModel session) { - AMQProtocolSession session = channel.getProtocolSession(); - /** * LOG FORMAT used by the AMQPConnectorActor follows * ChannelLogSubject.CHANNEL_FORMAT : con:{0}({1}@{2}/{3})/ch:{4}. @@ -47,39 +43,14 @@ public class ChannelLogSubject extends AbstractLogSubject * 3 - Virtualhost * 4 - Channel ID */ + AMQConnectionModel connection = session.getConnectionModel(); setLogStringWithFormat(CHANNEL_FORMAT, - session.getSessionID(), - session.getAuthorizedPrincipal().getName(), - session.getRemoteAddress(), - session.getVirtualHost().getName(), - channel.getChannelId()); - } + connection == null ? -1L : connection.getConnectionId(), + (connection == null || connection.getPrincipalAsString() == null) ? "?" : connection.getPrincipalAsString(), + (connection == null || connection.getRemoteAddressString() == null) ? "?" : connection.getRemoteAddressString(), + (connection == null || connection.getVirtualHostName() == null) ? "?" : connection.getVirtualHostName(), + session.getChannelId()); - public ChannelLogSubject(ServerSession session) - { - /** - * LOG FORMAT used by the AMQPConnectorActor follows - * ChannelLogSubject.CHANNEL_FORMAT : con:{0}({1}@{2}/{3})/ch:{4}. - * - * Uses a MessageFormat call to insert the required values according to - * these indices: - * - * 0 - Connection ID - * 1 - User ID - * 2 - IP - * 3 - Virtualhost - * 4 - Channel ID - */ - if(session.getConnection() instanceof ServerConnection) - { - ServerConnection connection = (ServerConnection) session.getConnection(); - setLogStringWithFormat(CHANNEL_FORMAT, - connection == null ? -1L : connection.getConnectionId(), - session.getAuthorizedPrincipal() == null ? "?" : session.getAuthorizedPrincipal().getName(), - (connection == null || connection.getRemoteAddressString() == null) ? "?" : connection.getRemoteAddressString(), - session.getVirtualHost().getName(), - session.getChannel()); - } } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java index 3b08a172b6..87c2377e0f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java @@ -20,34 +20,33 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import java.text.MessageFormat; +import org.apache.qpid.server.protocol.AMQConnectionModel; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT; -import java.text.MessageFormat; - /** The Connection LogSubject */ public class ConnectionLogSubject extends AbstractLogSubject { - public ConnectionLogSubject(AMQProtocolSession session) + // The Session this Actor is representing + private AMQConnectionModel _session; + + public ConnectionLogSubject(AMQConnectionModel session) { _session = session; } - // The Session this Actor is representing - private AMQProtocolSession _session; - // Used to stop re-creating the _logString when we reach our final format private boolean _upToDate = false; /** * Update the LogString as the Connection process proceeds. - * + * * When the Session has an authorized ID add that to the string. - * + * * When the Session then gains a Vhost add that to the string, at this point * we can set upToDate = true as the _logString will not need to be updated * from this point onwards. @@ -56,44 +55,44 @@ public class ConnectionLogSubject extends AbstractLogSubject { if (!_upToDate) { - if (_session.getAuthorizedPrincipal() != null) + if (_session.getPrincipalAsString() != null) { - if (_session.getVirtualHost() != null) + if (_session.getVirtualHostName() != null) { /** * LOG FORMAT used by the AMQPConnectorActor follows * ConnectionLogSubject.CONNECTION_FORMAT : * con:{0}({1}@{2}/{3}) - * + * * Uses a MessageFormat call to insert the required values * according to these indices: - * + * * 0 - Connection ID 1 - User ID 2 - IP 3 - Virtualhost */ setLogString("[" + MessageFormat.format(CONNECTION_FORMAT, - _session.getSessionID(), - _session.getAuthorizedPrincipal().getName(), - _session.getRemoteAddress(), - _session.getVirtualHost().getName()) + _session.getConnectionId(), + _session.getPrincipalAsString(), + _session.getRemoteAddressString(), + _session.getVirtualHostName()) + "] "); _upToDate = true; - } + } else { setLogString("[" + MessageFormat.format(USER_FORMAT, - _session.getSessionID(), - _session.getAuthorizedPrincipal().getName(), - _session.getRemoteAddress()) + _session.getConnectionId(), + _session.getPrincipalAsString(), + _session.getRemoteAddressString()) + "] "); } - } + } else { setLogString("[" + MessageFormat.format(SOCKET_FORMAT, - _session.getSessionID(), - _session.getRemoteAddress()) + _session.getConnectionId(), + _session.getRemoteAddressString()) + "] "); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubject.java index 99a54cc6d0..5affafad75 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ExchangeLogSubject.java @@ -32,6 +32,6 @@ public class ExchangeLogSubject extends AbstractLogSubject public ExchangeLogSubject(Exchange exchange, VirtualHost vhost) { setLogStringWithFormat(EXCHANGE_FORMAT, vhost.getName(), - exchange.getTypeShortString(), exchange.getNameShortString()); + exchange.getType().getType(), exchange.getName()); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java index 08963bd8f1..ed989d764f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubject.java @@ -28,8 +28,10 @@ public class MessageStoreLogSubject extends AbstractLogSubject { /** Create an MessageStoreLogSubject that Logs in the following format. */ - public MessageStoreLogSubject(VirtualHost vhost, String messageStoreName) + public MessageStoreLogSubject(String vhostName, String messageStoreName) { - setLogStringWithFormat(STORE_FORMAT, vhost.getName(), messageStoreName); + setLogStringWithFormat(STORE_FORMAT, vhostName, messageStoreName); } + + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java index c6dbb49061..1b3fdb1870 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/InboundMessage.java @@ -21,13 +21,11 @@ package org.apache.qpid.server.message; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.queue.Filterable; public interface InboundMessage extends Filterable { String getRoutingKey(); - AMQShortString getRoutingKeyShortString(); AMQMessageHeader getMessageHeader(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java index 61ceae9cf0..f75d0211cb 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java @@ -66,4 +66,15 @@ public interface AuthenticationProvider extends ConfiguredObject */ SubjectCreator getSubjectCreator(); + /** + * Returns the preferences provider associated with this authentication provider + * @return PreferencesProvider + */ + PreferencesProvider getPreferencesProvider(); + + /** + * Sets the preferences provider + * @param preferencesProvider + */ + void setPreferencesProvider(PreferencesProvider preferencesProvider); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java index 8f565362b4..0c1a6de58b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java @@ -45,6 +45,7 @@ public interface Broker extends ConfiguredObject String SUPPORTED_VIRTUALHOST_TYPES = "supportedVirtualHostTypes"; String SUPPORTED_VIRTUALHOST_STORE_TYPES = "supportedVirtualHostStoreTypes"; String SUPPORTED_AUTHENTICATION_PROVIDERS = "supportedAuthenticationProviders"; + String SUPPORTED_PREFERENCES_PROVIDERS_TYPES = "supportedPreferencesProviderTypes"; String CREATED = "created"; String DURABLE = "durable"; String ID = "id"; @@ -93,6 +94,7 @@ public interface Broker extends ConfiguredObject SUPPORTED_BROKER_STORE_TYPES, SUPPORTED_VIRTUALHOST_STORE_TYPES, SUPPORTED_AUTHENTICATION_PROVIDERS, + SUPPORTED_PREFERENCES_PROVIDERS_TYPES, CREATED, DURABLE, ID, @@ -183,4 +185,6 @@ public interface Broker extends ConfiguredObject TaskExecutor getTaskExecutor(); boolean isManagementMode(); + + AuthenticationProvider getAuthenticationProvider(SocketAddress localAddress); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java index 74a7469ffb..ab909390bd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/KeyStore.java @@ -20,9 +20,11 @@ */ package org.apache.qpid.server.model; +import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import javax.net.ssl.KeyManager; public interface KeyStore extends ConfiguredObject { @@ -64,4 +66,7 @@ public interface KeyStore extends ConfiguredObject public String getPassword(); public void setPassword(String password); + + public KeyManager[] getKeyManagers() throws GeneralSecurityException; + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java index 9120a27976..45fadbdbcb 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java @@ -70,6 +70,7 @@ public class Model addRelationship(VirtualHost.class, VirtualHostAlias.class); addRelationship(AuthenticationProvider.class, User.class); + addRelationship(AuthenticationProvider.class, PreferencesProvider.class); addRelationship(User.class, GroupMember.class); addRelationship(GroupProvider.class, Group.class); @@ -77,12 +78,12 @@ public class Model addRelationship(Connection.class, Session.class); - addRelationship(Exchange.class, Binding.class); - addRelationship(Exchange.class, Publisher.class); - addRelationship(Queue.class, Binding.class); addRelationship(Queue.class, Consumer.class); + addRelationship(Exchange.class, Binding.class); + addRelationship(Exchange.class, Publisher.class); + addRelationship(Session.class, Consumer.class); addRelationship(Session.class, Publisher.class); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java new file mode 100644 index 0000000000..96d02b2ef6 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PreferencesProvider.java @@ -0,0 +1,89 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +public interface PreferencesProvider extends ConfiguredObject +{ + String ID = "id"; + String NAME = "name"; + String TYPE = "type"; + String CREATED = "created"; + String UPDATED = "updated"; + String DURABLE = "durable"; + String LIFETIME_POLICY = "lifetimePolicy"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + + Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + TYPE, + CREATED, + UPDATED, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE + )); + + /** + * Returns preferences {@link Map} for a given user ID + * @param userId user ID to retrieve preferences for + * @return preferences {@link Map} + */ + Map<String, Object> getPreferences(String userId); + + /** + * Set user preferences as specified in a given {@link Map} + * @param userId user ID to set preferences for + * @param preferences new preferences + * @return existing user preferences + */ + Map<String, Object> setPreferences(String userId, Map<String, Object> preferences); + + /** + * Delete preferences for a given user ID + * @param userId user ID to delete preferences for + * @return user preferences before the deletion + */ + Map<String, Object> deletePreferences(String userId); + + /** + * Returns set of the user IDs having preferences set + * @return user IDs + */ + Set<String> listUserIDs(); + + /** + * Returns authentication provider associated with this preferences provider + * @return authentication provider + */ + AuthenticationProvider getAuthenticationProvider(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java index 6fe0607ab2..ae2031bd71 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java @@ -89,6 +89,7 @@ public interface Queue extends ConfiguredObject public static final String EXCLUSIVE = "exclusive"; public static final String MESSAGE_GROUP_KEY = "messageGroupKey"; public static final String MESSAGE_GROUP_SHARED_GROUPS = "messageGroupSharedGroups"; + public static final String MESSAGE_GROUP_DEFAULT_GROUP = "messageGroupDefaultGroup"; public static final String LVQ_KEY = "lvqKey"; public static final String MAXIMUM_DELIVERY_ATTEMPTS = "maximumDeliveryAttempts"; public static final String NO_LOCAL = "noLocal"; @@ -100,6 +101,10 @@ public interface Queue extends ConfiguredObject public static final String TYPE = "type"; public static final String PRIORITIES = "priorities"; + public static final String CREATE_DLQ_ON_CREATION = "x-qpid-dlq-enabled"; // TODO - this value should change + + public static final String FEDERATION_EXCLUDES = "federationExcludes"; + public static final String FEDERATION_ID = "federationId"; public static final Collection<String> AVAILABLE_ATTRIBUTES = @@ -134,6 +139,7 @@ public interface Queue extends ConfiguredObject PRIORITIES )); + //children Collection<Binding> getBindings(); Collection<Consumer> getConsumers(); @@ -144,6 +150,6 @@ public interface Queue extends ConfiguredObject void visit(QueueEntryVisitor visitor); void delete(); - + void setNotificationListener(QueueNotificationListener listener); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java index c686e7bd50..d313e1832f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/TrustStore.java @@ -20,9 +20,11 @@ */ package org.apache.qpid.server.model; +import java.security.GeneralSecurityException; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import javax.net.ssl.TrustManager; public interface TrustStore extends ConfiguredObject { @@ -64,4 +66,8 @@ public interface TrustStore extends ConfiguredObject public String getPassword(); public void setPassword(String password); + + public TrustManager[] getTrustManagers() throws GeneralSecurityException; + + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java index bcedd91596..7def89025d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java @@ -92,4 +92,9 @@ public class UUIDGenerator { return createUUID(type, childName); } + + public static UUID generatePreferencesProviderUUID(String preferencesProviderName, String authenticationProviderName) + { + return createUUID(PreferencesProvider.class.getName(), authenticationProviderName, preferencesProviderName); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java index 675dc8f0d3..f9d6f17ffd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java @@ -24,6 +24,7 @@ package org.apache.qpid.server.model; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Map; public interface User extends ConfiguredObject { @@ -54,4 +55,11 @@ public interface User extends ConfiguredObject public void setPassword(String password); + public Map<String, Object> getPreferences(); + + public Object getPreference(String name); + + public Map<String, Object> setPreferences(Map<String, Object> preferences); + + public Map<String, Object> replacePreferences(Map<String, Object> newPreferences); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java index 08e9c5ca5c..ae07005679 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java @@ -74,6 +74,8 @@ public interface VirtualHost extends ConfiguredObject String STORE_TRANSACTION_OPEN_TIMEOUT_WARN = "storeTransactionOpenTimeoutWarn"; String STORE_TYPE = "storeType"; String STORE_PATH = "storePath"; + String CONFIG_STORE_TYPE = "configStoreType"; + String CONFIG_STORE_PATH = "configStorePath"; String SUPPORTED_EXCHANGE_TYPES = "supportedExchangeTypes"; String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes"; String CREATED = "created"; @@ -107,6 +109,8 @@ public interface VirtualHost extends ConfiguredObject QUEUE_MAXIMUM_DELIVERY_ATTEMPTS, QUEUE_FLOW_CONTROL_SIZE_BYTES, QUEUE_FLOW_RESUME_SIZE_BYTES, + CONFIG_STORE_TYPE, + CONFIG_STORE_PATH, STORE_TYPE, STORE_PATH, STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, @@ -120,6 +124,8 @@ public interface VirtualHost extends ConfiguredObject QUEUE_ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, CONFIG_PATH)); + int CURRENT_CONFIG_VERSION = 3; + //children Collection<VirtualHostAlias> getAliases(); Collection<Connection> getConnections(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java index 7ff8c88331..9ac2cb00a3 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java @@ -39,7 +39,7 @@ import org.apache.qpid.server.configuration.updater.CreateChildTask; import org.apache.qpid.server.configuration.updater.SetAttributeTask; import org.apache.qpid.server.configuration.updater.TaskExecutor; -abstract class AbstractAdapter implements ConfiguredObject +public abstract class AbstractAdapter implements ConfiguredObject { private static final Object ID = "id"; private final Map<String,Object> _attributes = new HashMap<String, Object>(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java index 02ff98fb0e..a4ce95e5aa 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java @@ -21,18 +21,21 @@ package org.apache.qpid.server.model.adapter; import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; -import java.io.IOException; import java.net.InetSocketAddress; import java.security.GeneralSecurityException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; +import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -46,10 +49,9 @@ import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.protocol.AmqpProtocolVersion; import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; -import org.apache.qpid.server.util.MapValueConverter; -import org.apache.qpid.ssl.SSLContextFactory; import org.apache.qpid.transport.NetworkTransportConfiguration; import org.apache.qpid.transport.network.IncomingNetworkTransport; +import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; public class AmqpPortAdapter extends PortAdapter { @@ -136,8 +138,8 @@ public class AmqpPortAdapter extends PortAdapter private SSLContext createSslContext() { KeyStore keyStore = getKeyStore(); - Collection<TrustStore> trustStores = getTrustStores(); + boolean needClientCert = (Boolean)getAttribute(NEED_CLIENT_AUTH) || (Boolean)getAttribute(WANT_CLIENT_AUTH); if (needClientCert && trustStores.isEmpty()) { @@ -145,44 +147,58 @@ public class AmqpPortAdapter extends PortAdapter + this.getName() + "' but no trust store defined"); } - String keystorePath = (String)keyStore.getAttribute(KeyStore.PATH); - String keystorePassword = keyStore.getPassword(); - String keystoreType = (String)keyStore.getAttribute(KeyStore.TYPE); - String keyManagerFactoryAlgorithm = (String)keyStore.getAttribute(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM); - String certAlias = (String)keyStore.getAttribute(KeyStore.CERTIFICATE_ALIAS); - - final SSLContext sslContext; try { - if(! trustStores.isEmpty()) + SSLContext sslContext = SSLContext.getInstance("TLS"); + KeyManager[] keyManagers = keyStore.getKeyManagers(); + + TrustManager[] trustManagers; + if(trustStores == null || trustStores.isEmpty()) { - Collection<SSLContextFactory.TrustStoreWrapper> trstWrappers = new ArrayList<SSLContextFactory.TrustStoreWrapper>(); - for (TrustStore trustStore : trustStores) - { - trstWrappers.add(new SSLContextFactory.TrustStoreWrapper((String)trustStore.getAttribute(TrustStore.PATH), - trustStore.getPassword(), - (String)trustStore.getAttribute(TrustStore.TYPE), - (Boolean) trustStore.getAttribute(TrustStore.PEERS_ONLY), - (String)trustStore.getAttribute(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM))); - } - sslContext = SSLContextFactory.buildClientContext(trstWrappers, keystorePath, - keystorePassword, keystoreType, - keyManagerFactoryAlgorithm, certAlias); + trustManagers = null; + } + else if(trustStores.size() == 1) + { + trustManagers = trustStores.iterator().next().getTrustManagers(); } else { - sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keystoreType, keyManagerFactoryAlgorithm); + Collection<TrustManager> trustManagerList = new ArrayList<TrustManager>(); + final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager(); + + for(TrustStore ts : trustStores) + { + TrustManager[] managers = ts.getTrustManagers(); + if(managers != null) + { + for(TrustManager manager : managers) + { + if(manager instanceof X509TrustManager) + { + mulTrustManager.addTrustManager((X509TrustManager)manager); + } + else + { + trustManagerList.add(manager); + } + } + } + } + if(!mulTrustManager.isEmpty()) + { + trustManagerList.add(mulTrustManager); + } + trustManagers = trustManagerList.toArray(new TrustManager[trustManagerList.size()]); } + sslContext.init(keyManagers, trustManagers, null); + + return sslContext; + } catch (GeneralSecurityException e) { throw new RuntimeException("Unable to create SSLContext for key or trust store", e); } - catch (IOException e) - { - throw new RuntimeException("Unable to create SSLContext - unable to load key/trust store", e); - } - return sslContext; } private AmqpProtocolVersion getDefaultAmqpSupportedReply() diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java index 5c4c8a53cd..cbf8e1ba30 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java @@ -43,6 +43,7 @@ import org.apache.qpid.server.model.IntegrityViolationException; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.PasswordCredentialManagingAuthenticationProvider; import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.model.UUIDGenerator; @@ -51,11 +52,11 @@ import org.apache.qpid.server.model.VirtualHostAlias; import org.apache.qpid.server.plugin.AuthenticationManagerFactory; import org.apache.qpid.server.plugin.QpidServiceLoader; import org.apache.qpid.server.configuration.IllegalConfigurationException; -import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.security.SubjectCreator; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.UsernamePrincipal; import org.apache.qpid.server.security.auth.database.PrincipalDatabase; +import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; import org.apache.qpid.server.security.SecurityManager; @@ -70,9 +71,11 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana protected Collection<String> _supportedAttributes; protected Map<String, AuthenticationManagerFactory> _factories; - private AtomicReference<State> _state; + private final AtomicReference<State> _state; + private PreferencesProviderCreator _preferencesProviderCreator; + private PreferencesProvider _preferencesProvider; - private AuthenticationProviderAdapter(UUID id, Broker broker, final T authManager, Map<String, Object> attributes, Collection<String> attributeNames) + private AuthenticationProviderAdapter(UUID id, Broker broker, final T authManager, Map<String, Object> attributes, Collection<String> attributeNames, PreferencesProviderCreator preferencesProviderCreator) { super(id, null, null, broker.getTaskExecutor()); _authManager = authManager; @@ -84,6 +87,8 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana _state = new AtomicReference<State>(state); addParent(Broker.class, broker); + _preferencesProviderCreator = preferencesProviderCreator; + // set attributes now after all attribute names are known if (attributes != null) { @@ -210,9 +215,14 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana return super.getAttribute(name); } + @SuppressWarnings("unchecked") @Override public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) { + if (clazz == PreferencesProvider.class && _preferencesProvider != null) + { + return (Collection<C>)Collections.<PreferencesProvider>singleton(_preferencesProvider); + } return Collections.emptySet(); } @@ -240,6 +250,10 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana { _authManager.close(); _authManager.onDelete(); + if (_preferencesProvider != null) + { + _preferencesProvider.setDesiredState(_preferencesProvider.getActualState(), State.DELETED); + } return true; } else @@ -254,6 +268,10 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana try { _authManager.initialise(); + if (_preferencesProvider != null) + { + _preferencesProvider.setDesiredState(_preferencesProvider.getActualState(), State.ACTIVE); + } return true; } catch(RuntimeException e) @@ -286,6 +304,10 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana if (_state.compareAndSet(state, State.STOPPED)) { _authManager.close(); + if (_preferencesProvider != null) + { + _preferencesProvider.setDesiredState(_preferencesProvider.getActualState(), State.STOPPED); + } return true; } else @@ -397,24 +419,43 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana } } - public static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter<AuthenticationManager> + public PreferencesProvider getPreferencesProvider() { + return _preferencesProvider; + } - public SimpleAuthenticationProviderAdapter( - UUID id, Broker broker, AuthenticationManager authManager, Map<String, Object> attributes, Collection<String> attributeNames) + public void setPreferencesProvider(PreferencesProvider provider) + { + if (AnonymousAuthenticationManagerFactory.PROVIDER_TYPE.equals(getAttribute(TYPE))) { - super(id, broker,authManager, attributes, attributeNames); + throw new IllegalConfigurationException("Cannot set preferences provider for anonymous authentication provider"); } + _preferencesProvider = provider; + } - @Override - public <C extends ConfiguredObject> C createChild(Class<C> childClass, - Map<String, Object> attributes, - ConfiguredObject... otherParents) + @SuppressWarnings("unchecked") + @Override + public <C extends ConfiguredObject> C addChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + if(childClass == PreferencesProvider.class) { - throw new UnsupportedOperationException(); + String name = MapValueConverter.getStringAttribute(PreferencesProvider.NAME, attributes); + PreferencesProvider pp = _preferencesProviderCreator.create(UUIDGenerator.generatePreferencesProviderUUID(name, getName()), attributes, this); + pp.setDesiredState(State.INITIALISING, State.ACTIVE); + _preferencesProvider = pp; + return (C)pp; } + throw new IllegalArgumentException("Cannot create child of class " + childClass.getSimpleName()); + } + public static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter<AuthenticationManager> + { + public SimpleAuthenticationProviderAdapter( + UUID id, Broker broker, AuthenticationManager authManager, Map<String, Object> attributes, Collection<String> attributeNames, PreferencesProviderCreator preferencesProviderCreator) + { + super(id, broker,authManager, attributes, attributeNames, preferencesProviderCreator); + } } public static class PrincipalDatabaseAuthenticationManagerAdapter @@ -422,9 +463,9 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana implements PasswordCredentialManagingAuthenticationProvider { public PrincipalDatabaseAuthenticationManagerAdapter( - UUID id, Broker broker, PrincipalDatabaseAuthenticationManager authManager, Map<String, Object> attributes, Collection<String> attributeNames) + UUID id, Broker broker, PrincipalDatabaseAuthenticationManager authManager, Map<String, Object> attributes, Collection<String> attributeNames, PreferencesProviderCreator preferencesProviderCreator) { - super(id, broker, authManager, attributes, attributeNames); + super(id, broker, authManager, attributes, attributeNames, preferencesProviderCreator); } @Override @@ -507,7 +548,7 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana if(createUser(username, password,null)) { @SuppressWarnings("unchecked") - C pricipalAdapter = (C) new PrincipalAdapter(p, getTaskExecutor()); + C pricipalAdapter = (C) new PrincipalAdapter(p); return pricipalAdapter; } else @@ -529,7 +570,7 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana Collection<User> principals = new ArrayList<User>(users.size()); for(Principal user : users) { - principals.add(new PrincipalAdapter(user, getTaskExecutor())); + principals.add(new PrincipalAdapter(user)); } @SuppressWarnings("unchecked") Collection<C> unmodifiablePrincipals = (Collection<C>) Collections.unmodifiableCollection(principals); @@ -544,22 +585,33 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana @Override protected void childAdded(ConfiguredObject child) { - // no-op, prevent storing users in the broker store + if (child instanceof User) + { + // no-op, prevent storing users in the broker store + return; + } + super.childAdded(child); } @Override protected void childRemoved(ConfiguredObject child) { - // no-op, as per above, users are not in the store + if (child instanceof User) + { + // no-op, as per above, users are not in the store + return; + } + super.childRemoved(child); } private class PrincipalAdapter extends AbstractAdapter implements User { private final Principal _user; - public PrincipalAdapter(Principal user, TaskExecutor taskExecutor) + public PrincipalAdapter(Principal user) { - super(UUIDGenerator.generateUserUUID(PrincipalDatabaseAuthenticationManagerAdapter.this.getName(), user.getName()), taskExecutor); + super(UUIDGenerator.generateUserUUID(PrincipalDatabaseAuthenticationManagerAdapter.this.getName(), user.getName()), + PrincipalDatabaseAuthenticationManagerAdapter.this.getTaskExecutor()); _user = user; } @@ -699,7 +751,13 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana { try { - deleteUser(_user.getName()); + String userName = _user.getName(); + deleteUser(userName); + PreferencesProvider preferencesProvider = getPreferencesProvider(); + if (preferencesProvider != null) + { + preferencesProvider.deletePreferences(userName); + } } catch (AccountNotFoundException e) { @@ -709,6 +767,60 @@ public abstract class AuthenticationProviderAdapter<T extends AuthenticationMana } return false; } + + @Override + public Map<String, Object> getPreferences() + { + PreferencesProvider preferencesProvider = getPreferencesProvider(); + if (preferencesProvider == null) + { + return null; + } + return preferencesProvider.getPreferences(this.getName()); + } + + @Override + public Object getPreference(String name) + { + Map<String, Object> preferences = getPreferences(); + if (preferences == null) + { + return null; + } + return preferences.get(name); + } + + @Override + public Map<String, Object> setPreferences(Map<String, Object> preferences) + { + PreferencesProvider preferencesProvider = getPreferencesProvider(); + if (preferencesProvider == null) + { + return null; + } + return preferencesProvider.setPreferences(this.getName(), preferences); + } + + @Override + public Map<String, Object> replacePreferences(Map<String, Object> newPreferences) + { + PreferencesProvider preferencesProvider = getPreferencesProvider(); + if (preferencesProvider == null) + { + return null; + } + Map<String, Object> preferences = preferencesProvider.deletePreferences(this.getName()); + preferencesProvider.setPreferences(this.getName(), newPreferences); + return preferences; + } + + private PreferencesProvider getPreferencesProvider() + { + return PrincipalDatabaseAuthenticationManagerAdapter.this.getPreferencesProvider(); + } + } + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactory.java index 7efb71d78b..71bc3c631d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactory.java @@ -42,9 +42,11 @@ public class AuthenticationProviderFactory { private final Iterable<AuthenticationManagerFactory> _factories; private Collection<String> _supportedAuthenticationProviders; + private final PreferencesProviderCreator _preferencesProviderCreator; - public AuthenticationProviderFactory(QpidServiceLoader<AuthenticationManagerFactory> authManagerFactoryServiceLoader) + public AuthenticationProviderFactory(QpidServiceLoader<AuthenticationManagerFactory> authManagerFactoryServiceLoader, PreferencesProviderCreator preferencesProviderCreator) { + _preferencesProviderCreator = preferencesProviderCreator; _factories = authManagerFactoryServiceLoader.atLeastOneInstanceOf(AuthenticationManagerFactory.class); List<String> supportedAuthenticationProviders = new ArrayList<String>(); for (AuthenticationManagerFactory factory : _factories) @@ -89,11 +91,11 @@ public class AuthenticationProviderFactory if (manager instanceof PrincipalDatabaseAuthenticationManager) { authenticationProvider = new PrincipalDatabaseAuthenticationManagerAdapter(id, broker, - (PrincipalDatabaseAuthenticationManager) manager, attributes, factory.getAttributeNames()); + (PrincipalDatabaseAuthenticationManager) manager, attributes, factory.getAttributeNames(), _preferencesProviderCreator); } else { - authenticationProvider = new SimpleAuthenticationProviderAdapter(id, broker, manager, attributes, factory.getAttributeNames()); + authenticationProvider = new SimpleAuthenticationProviderAdapter(id, broker, manager, attributes, factory.getAttributeNames(), _preferencesProviderCreator); } return authenticationProvider; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java index ff9cac9a21..aec78ba414 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -178,7 +178,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat private final GroupProviderFactory _groupProviderFactory; private final AuthenticationProviderFactory _authenticationProviderFactory; private final AccessControlProviderFactory _accessControlProviderFactory; - + private final PreferencesProviderCreator _preferencesProviderCreator; private final PortFactory _portFactory; private final SecurityManager _securityManager; @@ -191,8 +191,8 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat public BrokerAdapter(UUID id, Map<String, Object> attributes, StatisticsGatherer statisticsGatherer, VirtualHostRegistry virtualHostRegistry, LogRecorder logRecorder, RootMessageLogger rootMessageLogger, AuthenticationProviderFactory authenticationProviderFactory, - GroupProviderFactory groupProviderFactory, AccessControlProviderFactory accessControlProviderFactory, PortFactory portFactory, TaskExecutor taskExecutor, - ConfigurationEntryStore brokerStore, BrokerOptions brokerOptions) + GroupProviderFactory groupProviderFactory, AccessControlProviderFactory accessControlProviderFactory, PortFactory portFactory, + PreferencesProviderCreator preferencesProviderCreatory, TaskExecutor taskExecutor, ConfigurationEntryStore brokerStore, BrokerOptions brokerOptions) { super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); _statisticsGatherer = statisticsGatherer; @@ -201,6 +201,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat _rootMessageLogger = rootMessageLogger; _statistics = new StatisticsAdapter(statisticsGatherer); _authenticationProviderFactory = authenticationProviderFactory; + _preferencesProviderCreator = preferencesProviderCreatory; _groupProviderFactory = groupProviderFactory; _accessControlProviderFactory = accessControlProviderFactory; _portFactory = portFactory; @@ -213,7 +214,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { AuthenticationManager authManager = new SimpleAuthenticationManager(BrokerOptions.MANAGEMENT_MODE_USER_NAME, _brokerOptions.getManagementModePassword()); AuthenticationProvider authenticationProvider = new SimpleAuthenticationProviderAdapter(UUID.randomUUID(), this, - authManager, Collections.<String, Object> emptyMap(), Collections.<String> emptySet()); + authManager, Collections.<String, Object> emptyMap(), Collections.<String> emptySet(), _preferencesProviderCreator); _managementAuthenticationProvider = authenticationProvider; } } @@ -783,6 +784,10 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat { return _authenticationProviderFactory.getSupportedAuthenticationProviders(); } + else if (SUPPORTED_PREFERENCES_PROVIDERS_TYPES.equals(name)) + { + return _preferencesProviderCreator.getSupportedPreferencesProviders(); + } else if (MODEL_VERSION.equals(name)) { return Model.MODEL_VERSION; @@ -1086,6 +1091,19 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat @Override public SubjectCreator getSubjectCreator(SocketAddress localAddress) { + AuthenticationProvider provider = getAuthenticationProvider(localAddress); + + if(provider == null) + { + throw new IllegalConfigurationException("Unable to determine authentication provider for address: " + localAddress); + } + + return provider.getSubjectCreator(); + } + + @Override + public AuthenticationProvider getAuthenticationProvider(SocketAddress localAddress) + { InetSocketAddress inetSocketAddress = (InetSocketAddress)localAddress; AuthenticationProvider provider = null; Collection<Port> ports = getPorts(); @@ -1097,13 +1115,7 @@ public class BrokerAdapter extends AbstractAdapter implements Broker, Configurat break; } } - - if(provider == null) - { - throw new IllegalConfigurationException("Unable to determine authentication provider for address: " + localAddress); - } - - return provider.getSubjectCreator(); + return provider; } @Override diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java index aaa6f460d2..e8bacb2712 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java @@ -190,7 +190,7 @@ final class ConnectionAdapter extends AbstractAdapter implements Connection } else if(name.equals(INCOMING)) { - + return true; } else if(name.equals(LOCAL_ADDRESS)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java index 07083fc661..8efce39ea2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java @@ -30,9 +30,7 @@ import java.util.Map; import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Exchange; import org.apache.qpid.server.model.LifetimePolicy; @@ -42,7 +40,6 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.util.MapValueConverter; -import org.apache.qpid.server.virtualhost.ExchangeIsAlternateException; import org.apache.qpid.server.virtualhost.RequiredExchangeException; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -90,7 +87,7 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa public String getExchangeType() { - return _exchange.getType().getName().toString(); + return _exchange.getType().getType(); } public Collection<org.apache.qpid.server.model.Binding> getBindings() @@ -357,7 +354,7 @@ final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apa } else if(TYPE.equals(name)) { - return _exchange.getType().getName().asString(); + return _exchange.getTypeName(); } return super.getAttribute(name); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java new file mode 100644 index 0000000000..f7560a0dfa --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProvider.java @@ -0,0 +1,592 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.model.adapter; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.RandomAccessFile; +import java.lang.reflect.Type; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.OverlappingFileLockException; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.log4j.Logger; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.IllegalStateTransitionException; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.util.MapValueConverter; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.type.TypeReference; + +public class FileSystemPreferencesProvider extends AbstractAdapter implements PreferencesProvider +{ + private static final Logger LOGGER = Logger.getLogger(FileSystemPreferencesProvider.class); + public static String PATH = "path"; + public static final String PROVIDER_TYPE = "FileSystemPreferences"; + + // TODO: use resolver to resolve path from + // '${qpid.work_dir}/preferences/${authenticationProviderName}' + @SuppressWarnings("serial") + private static final Map<String, Object> DEFAULTS = Collections.unmodifiableMap(new HashMap<String, Object>() + {{ + put(PATH, System.getProperty("user.home") + File.separator + ".qpid" + File.separator + "preferences.json"); + put(TYPE, FileSystemPreferencesProvider.class.getSimpleName()); + }}); + + @SuppressWarnings("serial") + private static final Map<String, Type> ATTRIBUTE_TYPES = Collections.unmodifiableMap(new HashMap<String, Type>() + {{ + put(NAME, String.class); + put(PATH, String.class); + put(TYPE, String.class); + }}); + + @SuppressWarnings("serial") + private static Collection<String> AVAILABLE_ATTRIBUTES = Collections.unmodifiableList(new ArrayList<String>( + PreferencesProvider.AVAILABLE_ATTRIBUTES) + {{ + add(PATH); + }}); + + private final AuthenticationProvider _authenticationProvider; + private AtomicReference<State> _state; + + private final ObjectMapper _objectMapper; + private final Map<String, Map<String, Object>> _preferences; + private File _preferencesLocation; + private FileLock _fileLock; + + protected FileSystemPreferencesProvider(UUID id, Map<String, Object> attributes, AuthenticationProvider authenticationProvider, TaskExecutor taskExecutor) + { + super(id, DEFAULTS, MapValueConverter.convert(attributes, ATTRIBUTE_TYPES), taskExecutor); + State state = MapValueConverter.getEnumAttribute(State.class, STATE, attributes, State.INITIALISING); + _state = new AtomicReference<State>(state); + addParent(AuthenticationProvider.class, authenticationProvider); + _authenticationProvider = authenticationProvider; + _objectMapper = new ObjectMapper(); + _objectMapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + _objectMapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true); + _preferences = new TreeMap<String, Map<String, Object>>(); + _preferencesLocation = new File(MapValueConverter.getStringAttribute(PATH, attributes)); + _preferences.putAll(load(_objectMapper, _preferencesLocation)); + } + + @Override + public Collection<String> getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + @Override + public String getName() + { + return (String) getAttribute(AuthenticationProvider.NAME); + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + throw new UnsupportedOperationException(); + } + + @Override + public State getActualState() + { + return _state.get(); + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) throws IllegalStateException, + AccessControlException, IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) throws IllegalStateException, AccessControlException, + IllegalArgumentException + { + throw new UnsupportedOperationException(); + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + return Collections.emptySet(); + } + + @Override + public Object getAttribute(String name) + { + if (CREATED.equals(name)) + { + // TODO + } + else if (DURABLE.equals(name)) + { + return true; + } + else if (ID.equals(name)) + { + return getId(); + } + else if (LIFETIME_POLICY.equals(name)) + { + return LifetimePolicy.PERMANENT; + } + else if (STATE.equals(name)) + { + return getActualState(); + } + else if (TIME_TO_LIVE.equals(name)) + { + // TODO + } + else if (UPDATED.equals(name)) + { + // TODO + } + return super.getAttribute(name); + } + + @Override + public boolean setState(State currentState, State desiredState) throws IllegalStateTransitionException, + AccessControlException + { + State state = _state.get(); + if (desiredState == State.DELETED) + { + if ((state == State.INITIALISING || state == State.ACTIVE || state == State.STOPPED || state == State.QUIESCED || state == State.ERRORED) + && _state.compareAndSet(state, State.DELETED)) + { + try + { + close(); + } + finally + { + _preferencesLocation.delete(); + _authenticationProvider.setPreferencesProvider(null); + } + return true; + } + else + { + throw new IllegalStateException("Cannot delete preferences provider in state: " + state); + } + } + else if (desiredState == State.ACTIVE) + { + if ((state == State.INITIALISING || state == State.QUIESCED || state == State.STOPPED) + && _state.compareAndSet(state, State.ACTIVE)) + { + try + { + getFileLock(); + Map<String, Map<String, Object>> preferences = load(_objectMapper, _preferencesLocation); + setPreferences(preferences); + return true; + } + catch (Exception e) + { + _state.compareAndSet(State.ACTIVE, State.ERRORED); + Broker broker = getAuthenticationProvider().getParent(Broker.class); + if (broker != null && broker.isManagementMode()) + { + LOGGER.warn("Failed to activate preferences provider: " + getName(), e); + } + else + { + throw new RuntimeException(e); + } + } + } + else + { + throw new IllegalStateException("Cannot activate preferences provider in state: " + state); + } + } + else if (desiredState == State.QUIESCED) + { + if (state == State.INITIALISING && _state.compareAndSet(state, State.QUIESCED)) + { + close(); + return true; + } + } + else if (desiredState == State.STOPPED) + { + if (_state.compareAndSet(state, State.STOPPED)) + { + close(); + return true; + } + else + { + throw new IllegalStateException("Cannot stop authentication preferences in state: " + state); + } + } + + return false; + } + + @Override + public Map<String, Object> getPreferences(String userId) + { + Map<String, Object> userPreferences = null; + synchronized (_preferences) + { + userPreferences = _preferences.get(userId); + } + if (userPreferences != null) + { + return new HashMap<String, Object>(userPreferences); + } + return Collections.emptyMap(); + } + + @Override + public Map<String, Object> setPreferences(String userId, Map<String, Object> preferences) + { + Map<String, Object> userPreferences = null; + synchronized (_preferences) + { + userPreferences = _preferences.get(userId); + if (userPreferences == null) + { + userPreferences = new HashMap<String, Object>(preferences); + _preferences.put(userId, userPreferences); + } + else + { + userPreferences.putAll(preferences); + } + savePreferences(); + } + return userPreferences; + } + + @Override + public Map<String, Object> deletePreferences(String userId) + { + Map<String, Object> userPreferences = null; + synchronized (_preferences) + { + if (_preferences.containsKey(userId)) + { + userPreferences = _preferences.remove(userId); + savePreferences(); + } + } + return userPreferences; + } + + @Override + public Set<String> listUserIDs() + { + synchronized (_preferences) + { + return Collections.unmodifiableSet(_preferences.keySet()); + } + } + + public AuthenticationProvider getAuthenticationProvider() + { + return _authenticationProvider; + } + + @Override + protected void changeAttributes(Map<String, Object> attributes) + { + Map<String, Object> effectiveAttributes = MapValueConverter.convert(super.generateEffectiveAttributes(attributes), + ATTRIBUTE_TYPES); + validateAttributes(effectiveAttributes); + String effectivePath = (String) effectiveAttributes.get(PATH); + String currentPath = (String) getAttribute(PATH); + Map<String, Map<String, Object>> newPreferences = null; + File storeFile = new File(effectivePath); + if (!effectivePath.equals(currentPath)) + { + if (!storeFile.exists()) + { + throw new IllegalConfigurationException("Path to preferences file does not exist!"); + } + newPreferences = load(_objectMapper, storeFile); + } + super.changeAttributes(attributes); + + if (newPreferences != null) + { + setPreferences(newPreferences); + _preferencesLocation = storeFile; + } + + // if provider was previously in ERRORED state then set its state to + // ACTIVE + _state.compareAndSet(State.ERRORED, State.ACTIVE); + } + + private void setPreferences(Map<String, Map<String, Object>> preferences) + { + synchronized (_preferences) + { + _preferences.clear(); + _preferences.putAll(preferences); + } + } + + private void validateAttributes(Map<String, Object> attributes) + { + super.validateChangeAttributes(attributes); + + String newName = (String) attributes.get(NAME); + String currentName = getName(); + if (!currentName.equals(newName)) + { + throw new IllegalConfigurationException("Changing the name of preferences provider is not supported"); + } + String newType = (String) attributes.get(TYPE); + String currentType = (String) getAttribute(TYPE); + if (!currentType.equals(newType)) + { + throw new IllegalConfigurationException("Changing the type of preferences provider is not supported"); + } + String path = (String) attributes.get(PATH); + if (path == null || path.equals("") || !(path instanceof String)) + { + throw new IllegalConfigurationException("Path to preferences file is not specified"); + } + } + + public File createStoreIfNotExist() + { + String path = (String)getAttribute(PATH); + File preferencesLocation = new File(path); + if (!preferencesLocation.exists()) + { + File parent = preferencesLocation.getParentFile(); + if (!parent.exists() && !parent.mkdirs()) + { + throw new IllegalConfigurationException("Cannot store preferences at " + path); + } + try + { + preferencesLocation.createNewFile(); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot store preferences at " + path); + } + } + return preferencesLocation; + } + + private Map<String, Map<String, Object>> load(ObjectMapper mapper, File file) + { + if (!file.exists() || file.length() == 0) + { + return Collections.emptyMap(); + } + + try + { + return mapper.readValue(file, new TypeReference<Map<String, Map<String, Object>>>() + { + }); + } + catch (JsonProcessingException e) + { + throw new IllegalConfigurationException("Cannot parse json", e); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot read json", e); + } + } + + private void savePreferences() + { + save(_objectMapper, _preferencesLocation, _preferences); + } + + private void save(ObjectMapper mapper, File file, Map<String, Map<String, Object>> preferences) + { + try + { + RandomAccessFile raf = new RandomAccessFile(file, "rw"); + try + { + FileChannel channel = raf.getChannel(); + try + { + FileLock lock = null; + try + { + lock = channel.tryLock(); + if (lock == null) + { + throw new IllegalConfigurationException("Cannot aquire exclusive lock on preferences file for " + + getName()); + } + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + mapper.writeValue(baos, preferences); + channel.write(ByteBuffer.wrap(baos.toByteArray())); + } + catch (OverlappingFileLockException e) + { + throw new IllegalConfigurationException("Cannot aquire exclusive lock on preferences file for " + + getName(), e); + } + finally + { + if (lock != null) + { + lock.release(); + } + } + } + finally + { + channel.close(); + } + } + finally + { + raf.close(); + } + } + catch (FileNotFoundException e) + { + throw new IllegalConfigurationException("Cannot find preferences file for " + getName(), e); + } + catch (IOException e) + { + throw new IllegalConfigurationException("Cannot store preferences file for " + getName(), e); + } + } + + private void getFileLock() throws IOException, AMQStoreException + { + File lockFile = new File(getLockFileName()); + lockFile.createNewFile(); + + FileOutputStream out = new FileOutputStream(lockFile); + FileChannel channel = out.getChannel(); + try + { + _fileLock = channel.tryLock(); + } + catch(OverlappingFileLockException e) + { + _fileLock = null; + } + if(_fileLock == null) + { + throw new AMQStoreException("Cannot get lock on file " + lockFile.getAbsolutePath() + " is another instance running?"); + } + lockFile.deleteOnExit(); + } + + private String getLockFileName() + { + return _preferencesLocation.getAbsolutePath() + ".lck"; + } + + public void close() + { + try + { + releaseFileLock(); + } + catch(IOException e) + { + LOGGER.error("Cannot close file system preferences provider", e); + } + finally + { + new File(getLockFileName()).delete(); + _fileLock = null; + _preferences.clear(); + } + } + + private void releaseFileLock() throws IOException + { + _fileLock.release(); + _fileLock.channel().close(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactory.java new file mode 100644 index 0000000000..32ee910973 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactory.java @@ -0,0 +1,53 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.model.adapter; + +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.plugin.PreferencesProviderFactory; + +public class FileSystemPreferencesProviderFactory implements PreferencesProviderFactory +{ + + @Override + public String getType() + { + return FileSystemPreferencesProvider.PROVIDER_TYPE; + } + + @Override + public PreferencesProvider createInstance(UUID id, Map<String, Object> attributes, + AuthenticationProvider authenticationProvider) + { + Broker broker = authenticationProvider.getParent(Broker.class); + FileSystemPreferencesProvider provider = new FileSystemPreferencesProvider(id, attributes, authenticationProvider, broker.getTaskExecutor()); + + // create store if such does not exist + provider.createStoreIfNotExist(); + return provider; + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java index 4d4d3bb31d..1101232c96 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/KeyStoreAdapter.java @@ -20,8 +20,10 @@ */ package org.apache.qpid.server.model.adapter; +import java.io.IOException; import java.lang.reflect.Type; import java.security.AccessControlException; +import java.security.GeneralSecurityException; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.Certificate; @@ -32,6 +34,7 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import javax.net.ssl.KeyManager; import javax.net.ssl.KeyManagerFactory; import org.apache.qpid.server.configuration.IllegalConfigurationException; @@ -42,6 +45,7 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.State; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.MapValueConverter; +import org.apache.qpid.transport.network.security.ssl.QpidClientX509KeyManager; import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class KeyStoreAdapter extends AbstractKeyStoreAdapter implements KeyStore @@ -210,4 +214,41 @@ public class KeyStoreAdapter extends AbstractKeyStoreAdapter implements KeyStore + keyManagerFactoryAlgorithm); } } + + public KeyManager[] getKeyManagers() throws GeneralSecurityException + { + String keyStorePath = (String)getAttribute(KeyStore.PATH); + String keyStorePassword = getPassword(); + String keyStoreType = (String)getAttribute(KeyStore.TYPE); + String keyManagerFactoryAlgorithm = (String)getAttribute(KeyStore.KEY_MANAGER_FACTORY_ALGORITHM); + String certAlias = (String)getAttribute(KeyStore.CERTIFICATE_ALIAS); + + try + { + if (certAlias != null) + { + return new KeyManager[] { + new QpidClientX509KeyManager( certAlias, keyStorePath, keyStoreType, keyStorePassword, + keyManagerFactoryAlgorithm) + }; + + } + else + { + final java.security.KeyStore ks = SSLUtil.getInitializedKeyStore(keyStorePath, keyStorePassword, keyStoreType); + + char[] keyStoreCharPassword = keyStorePassword == null ? null : keyStorePassword.toCharArray(); + + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerFactoryAlgorithm); + + kmf.init(ks, keyStoreCharPassword); + + return kmf.getKeyManagers(); + } + } + catch (IOException e) + { + throw new GeneralSecurityException(e); + } + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PreferencesProviderCreator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PreferencesProviderCreator.java new file mode 100644 index 0000000000..4bcca0e300 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PreferencesProviderCreator.java @@ -0,0 +1,66 @@ +package org.apache.qpid.server.model.adapter; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.plugin.PreferencesProviderFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class PreferencesProviderCreator +{ + private final Map<String, PreferencesProviderFactory> _factories; + private Collection<String> _supportedPreferencesProviders; + + public PreferencesProviderCreator() + { + QpidServiceLoader<PreferencesProviderFactory> preferencesProviderFactoriess = new QpidServiceLoader<PreferencesProviderFactory>(); + + Iterable<PreferencesProviderFactory> factories = preferencesProviderFactoriess + .instancesOf(PreferencesProviderFactory.class); + + Map<String, PreferencesProviderFactory> registeredPreferencesProviderFactories = new HashMap<String, PreferencesProviderFactory>(); + for (PreferencesProviderFactory factory : factories) + { + PreferencesProviderFactory existingFactory = registeredPreferencesProviderFactories.put(factory.getType(), + factory); + if (existingFactory != null) + { + throw new IllegalConfigurationException("Preferences provider factory of the same type '" + + factory.getType() + "' is already registered using class '" + existingFactory.getClass().getName() + + "', can not register class '" + factory.getClass().getName() + "'"); + } + } + _factories = registeredPreferencesProviderFactories; + _supportedPreferencesProviders = Collections.unmodifiableCollection(registeredPreferencesProviderFactories.keySet()); + } + + public Collection<String> getSupportedPreferencesProviders() + { + return _supportedPreferencesProviders; + } + + public PreferencesProvider create(UUID id, Map<String, Object> attributes, AuthenticationProvider authenticationProvider) + { + return createPreferencesProvider(id, attributes, authenticationProvider); + } + + public PreferencesProvider recover(UUID id, Map<String, Object> attributes, AuthenticationProvider authenticationProviderr) + { + return createPreferencesProvider(id, attributes, authenticationProviderr); + } + + private PreferencesProvider createPreferencesProvider(UUID id, Map<String, Object> attributes, AuthenticationProvider authenticationProvider) + { + for (PreferencesProviderFactory factory : _factories.values()) + { + return factory.createInstance(id, attributes, authenticationProvider); + } + throw new IllegalConfigurationException("No group provider factory found for configuration attributes " + attributes); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java index 157b97cc07..074f7c243b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java @@ -66,25 +66,6 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs put(DESCRIPTION, String.class); }}); - static final Map<String, String> ATTRIBUTE_MAPPINGS = new HashMap<String, String>(); - static - { - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_REPEAT_GAP, AMQQueueFactory.X_QPID_MINIMUM_ALERT_REPEAT_GAP); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_AGE); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_SIZE); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_COUNT); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, AMQQueueFactory.X_QPID_MAXIMUM_QUEUE_DEPTH); - - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT); - - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, AMQQueueFactory.X_QPID_CAPACITY); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, AMQQueueFactory.X_QPID_FLOW_RESUME_CAPACITY); - - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.SORT_KEY, AMQQueueFactory.QPID_QUEUE_SORT_KEY); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_LAST_VALUE_QUEUE_KEY); - QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.PRIORITIES, AMQQueueFactory.X_QPID_PRIORITIES); - } - private final AMQQueue _queue; private final Map<Binding, BindingAdapter> _bindingAdapters = new HashMap<Binding, BindingAdapter>(); @@ -190,15 +171,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs { try { - QueueRegistry queueRegistry = _queue.getVirtualHost().getQueueRegistry(); - synchronized(queueRegistry) - { - _queue.delete(); - if (_queue.isDurable()) - { - DurableConfigurationStoreHelper.removeQueue(_queue.getVirtualHost().getDurableConfigurationStore(), _queue); - } - } + _queue.getVirtualHost().removeQueue(_queue); } catch(AMQException e) { @@ -414,13 +387,12 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs } else if(MESSAGE_GROUP_KEY.equals(name)) { - return _queue.getArguments().get(SimpleAMQQueue.QPID_GROUP_HEADER_KEY); + return _queue.getAttribute(MESSAGE_GROUP_KEY); } else if(MESSAGE_GROUP_SHARED_GROUPS.equals(name)) { //We only return the boolean value if message groups are actually in use - return getAttribute(MESSAGE_GROUP_KEY) == null ? null : - SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE.equals(_queue.getArguments().get(SimpleAMQQueue.QPID_SHARED_MSG_GROUP)); + return getAttribute(MESSAGE_GROUP_KEY) == null ? null : _queue.getAttribute(MESSAGE_GROUP_SHARED_GROUPS); } else if(LVQ_KEY.equals(name)) { @@ -439,7 +411,7 @@ final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.Subs } else if(OWNER.equals(name)) { - return _queue.getOwner() == null ? null : _queue.getOwner().asString(); + return _queue.getOwner(); } else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java index 06089e43c6..5e7bfff4de 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/TrustStoreAdapter.java @@ -20,8 +20,11 @@ */ package org.apache.qpid.server.model.adapter; +import java.io.IOException; import java.lang.reflect.Type; import java.security.AccessControlException; +import java.security.GeneralSecurityException; +import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; @@ -30,8 +33,10 @@ import java.util.HashMap; import java.util.Map; import java.util.UUID; +import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.IntegrityViolationException; @@ -40,6 +45,8 @@ import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.util.MapValueConverter; +import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; +import org.apache.qpid.transport.network.security.ssl.QpidPeersOnlyTrustManager; import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class TrustStoreAdapter extends AbstractKeyStoreAdapter implements TrustStore @@ -189,4 +196,60 @@ public class TrustStoreAdapter extends AbstractKeyStoreAdapter implements TrustS throw new IllegalConfigurationException("Unknown trustManagerFactoryAlgorithm: " + trustManagerFactoryAlgorithm); } } + + public TrustManager[] getTrustManagers() throws GeneralSecurityException + { + String trustStorePath = (String)getAttribute(TrustStore.PATH); + String trustStorePassword = getPassword(); + String trustStoreType = (String)getAttribute(TrustStore.TYPE); + String trustManagerFactoryAlgorithm = (String)getAttribute(TrustStore.TRUST_MANAGER_FACTORY_ALGORITHM); + + try + { + KeyStore ts = SSLUtil.getInitializedKeyStore(trustStorePath, trustStorePassword, trustStoreType); + final TrustManagerFactory tmf = TrustManagerFactory + .getInstance(trustManagerFactoryAlgorithm); + tmf.init(ts); + final Collection<TrustManager> trustManagersCol = new ArrayList<TrustManager>(); + final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager(); + TrustManager[] delegateManagers = tmf.getTrustManagers(); + for (TrustManager tm : delegateManagers) + { + if (tm instanceof X509TrustManager) + { + if (Boolean.TRUE.equals(getAttribute(PEERS_ONLY))) + { + // truststore is supposed to trust only clients which peers certificates + // are directly in the store. CA signing will not be considered. + mulTrustManager.addTrustManager(new QpidPeersOnlyTrustManager(ts, (X509TrustManager) tm)); + } + else + { + mulTrustManager.addTrustManager((X509TrustManager) tm); + } + } + else + { + trustManagersCol.add(tm); + } + } + if (! mulTrustManager.isEmpty()) + { + trustManagersCol.add(mulTrustManager); + } + + if (trustManagersCol.isEmpty()) + { + return null; + } + else + { + return trustManagersCol.toArray(new TrustManager[trustManagersCol.size()]); + } + } + catch (IOException e) + { + throw new GeneralSecurityException(e); + } + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java index c09dd9449e..58b0b76735 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -41,12 +41,9 @@ import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.commons.configuration.SystemConfiguration; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.configuration.XmlConfigurationUtilities.MyConfiguration; -import org.apache.qpid.server.connection.IConnectionRegistry; -import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.ConfiguredObject; @@ -68,14 +65,13 @@ import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.access.Operation; import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.DurableConfigurationStoreHelper; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.txn.ServerTransaction; @@ -86,6 +82,7 @@ import org.apache.qpid.server.virtualhost.ReservedExchangeNameException; import org.apache.qpid.server.virtualhost.UnknownExchangeException; import org.apache.qpid.server.virtualhost.VirtualHostListener; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; +import org.apache.qpid.server.virtualhost.plugins.QueueExistsException; public final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, VirtualHostListener { @@ -203,7 +200,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual private void populateQueues() { - Collection<AMQQueue> actualQueues = _virtualHost.getQueueRegistry().getQueues(); + Collection<AMQQueue> actualQueues = _virtualHost.getQueues(); if ( actualQueues != null ) { synchronized(_queueAdapters) @@ -399,7 +396,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual } if (queueType == QueueType.LVQ && attributes.get(Queue.LVQ_KEY) == null) { - attributes.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_LVQ_KEY); + attributes.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_DEFAULT_LVQ_KEY); } else if (queueType == QueueType.PRIORITY && attributes.get(Queue.PRIORITIES) == null) { @@ -415,7 +412,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { String key = MapValueConverter.getStringAttribute(Queue.MESSAGE_GROUP_KEY, attributes); attributes.remove(Queue.MESSAGE_GROUP_KEY); - attributes.put(SimpleAMQQueue.QPID_GROUP_HEADER_KEY, key); + attributes.put(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY, key); } if (attributes.containsKey(Queue.MESSAGE_GROUP_SHARED_GROUPS)) @@ -423,7 +420,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual if(MapValueConverter.getBooleanAttribute(Queue.MESSAGE_GROUP_SHARED_GROUPS, attributes)) { attributes.remove(Queue.MESSAGE_GROUP_SHARED_GROUPS); - attributes.put(SimpleAMQQueue.QPID_SHARED_MSG_GROUP, SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE); + attributes.put(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP, SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE); } } @@ -440,15 +437,6 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual attributes.remove(Queue.LIFETIME_POLICY); attributes.remove(Queue.TIME_TO_LIVE); - List<String> attrNames = new ArrayList<String>(attributes.keySet()); - for(String attr : attrNames) - { - if(QueueAdapter.ATTRIBUTE_MAPPINGS.containsKey(attr)) - { - attributes.put(QueueAdapter.ATTRIBUTE_MAPPINGS.get(attr),attributes.remove(attr)); - } - } - return createQueue(name, state, durable, exclusive, lifetime, ttl, attributes); } @@ -472,33 +460,26 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual owner = authenticatedPrincipal.getName(); } } + + final boolean autoDelete = lifetime == LifetimePolicy.AUTO_DELETE; + try { - QueueRegistry queueRegistry = _virtualHost.getQueueRegistry(); - synchronized (queueRegistry) - { - if(_virtualHost.getQueueRegistry().getQueue(name)!=null) - { - throw new IllegalArgumentException("Queue with name "+name+" already exists"); - } - AMQQueue queue = - AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(name, _virtualHost.getName()), name, - durable, owner, lifetime == LifetimePolicy.AUTO_DELETE, - exclusive, _virtualHost, attributes); - if(durable) - { - DurableConfigurationStoreHelper.createQueue(_virtualHost.getDurableConfigurationStore(), - queue, - FieldTable.convertToFieldTable(attributes)); - } - synchronized (_queueAdapters) - { - return _queueAdapters.get(queue); - } + AMQQueue queue = + _virtualHost.createQueue(UUIDGenerator.generateQueueUUID(name, _virtualHost.getName()), name, + durable, owner, autoDelete, exclusive, autoDelete && exclusive, attributes); + + synchronized (_queueAdapters) + { + return _queueAdapters.get(queue); } } + catch(QueueExistsException qe) + { + throw new IllegalArgumentException("Queue with name "+name+" already exists"); + } catch(AMQException e) { throw new IllegalArgumentException(e); @@ -784,7 +765,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual for(ExchangeType<? extends org.apache.qpid.server.exchange.Exchange> type : types) { - exchangeTypes.add(type.getName().asString()); + exchangeTypes.add(type.getType()); } return Collections.unmodifiableCollection(exchangeTypes); } @@ -938,7 +919,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual List<String> types = new ArrayList<String>(); for(@SuppressWarnings("rawtypes") ExchangeType type : _virtualHost.getExchangeTypes()) { - types.add(type.getName().asString()); + types.add(type.getType()); } return Collections.unmodifiableCollection(types); } @@ -1057,7 +1038,7 @@ public final class VirtualHostAdapter extends AbstractAdapter implements Virtual { if(VirtualHost.QUEUE_COUNT.equals(name)) { - return _vhost.getQueueRegistry().getQueues().size(); + return _vhost.getQueues().size(); } else if(VirtualHost.EXCHANGE_COUNT.equals(name)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java deleted file mode 100755 index 0c14c06624..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/output/HeaderPropertiesConverter.java +++ /dev/null @@ -1,149 +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.output; - -import org.apache.qpid.AMQPInvalidClassException; -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.DeliveryProperties; -import org.apache.qpid.transport.Header; -import org.apache.qpid.transport.MessageDeliveryMode; -import org.apache.qpid.transport.MessageProperties; -import org.apache.qpid.transport.ReplyTo; - -import java.util.HashMap; -import java.util.Map; - -public class HeaderPropertiesConverter -{ - private HeaderPropertiesConverter() - { - } - - public static BasicContentHeaderProperties convert(MessageTransferMessage messageTransferMessage, VirtualHost vhost) - { - BasicContentHeaderProperties props = new BasicContentHeaderProperties(); - - Header header = messageTransferMessage.getHeader(); - DeliveryProperties deliveryProps = header.getDeliveryProperties(); - MessageProperties messageProps = header.getMessageProperties(); - - if(deliveryProps != null) - { - if(deliveryProps.hasDeliveryMode()) - { - props.setDeliveryMode((byte)(deliveryProps.getDeliveryMode() == MessageDeliveryMode.PERSISTENT ? BasicContentHeaderProperties.PERSISTENT : BasicContentHeaderProperties.NON_PERSISTENT)); - } - if(deliveryProps.hasExpiration()) - { - props.setExpiration(deliveryProps.getExpiration()); - } - if(deliveryProps.hasPriority()) - { - props.setPriority((byte)deliveryProps.getPriority().getValue()); - } - if(deliveryProps.hasTimestamp()) - { - props.setTimestamp(deliveryProps.getTimestamp()); - } - } - if(messageProps != null) - { - if(messageProps.hasAppId()) - { - props.setAppId(new AMQShortString(messageProps.getAppId())); - } - if(messageProps.hasContentType()) - { - props.setContentType(messageProps.getContentType()); - } - if(messageProps.hasCorrelationId()) - { - props.setCorrelationId(new AMQShortString(messageProps.getCorrelationId())); - } - if(messageProps.hasContentEncoding()) - { - props.setEncoding(messageProps.getContentEncoding()); - } - if(messageProps.hasMessageId()) - { - props.setMessageId("ID:" + messageProps.getMessageId().toString()); - } - if(messageProps.hasReplyTo()) - { - ReplyTo replyTo = messageProps.getReplyTo(); - String exchangeName = replyTo.getExchange(); - String routingKey = replyTo.getRoutingKey(); - if(exchangeName == null) - { - exchangeName = ""; - } - - Exchange exchange = vhost.getExchange(exchangeName); - String exchangeClass = exchange == null ? ExchangeDefaults.DIRECT_EXCHANGE_CLASS.asString() : exchange.getType().getName().asString(); - props.setReplyTo(exchangeClass + "://"+exchangeName+"//?routingkey='"+(routingKey==null ? "" : routingKey+"'")); - - } - if(messageProps.hasUserId()) - { - props.setUserId(new AMQShortString(messageProps.getUserId())); - } - - if(messageProps.hasApplicationHeaders()) - { - Map<String, Object> appHeaders = new HashMap<String, Object>(messageProps.getApplicationHeaders()); - if(messageProps.getApplicationHeaders().containsKey("x-jms-type")) - { - props.setType(String.valueOf(appHeaders.remove("x-jms-type"))); - } - - FieldTable ft = new FieldTable(); - for(Map.Entry<String, Object> entry : appHeaders.entrySet()) - { - try - { - ft.put(new AMQShortString(entry.getKey()), entry.getValue()); - } - catch(AMQPInvalidClassException e) - { - // TODO - // log here, but ignore - just can;t convert - } - } - props.setHeaders(ft); - - } - } - - - - - - - - return props; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java new file mode 100644 index 0000000000..94a029ced3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/DurableConfigurationStoreFactory.java @@ -0,0 +1,35 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.plugin; + +import java.util.Map; +import org.apache.commons.configuration.Configuration; +import org.apache.qpid.server.store.DurableConfigurationStore; +import org.apache.qpid.server.store.MessageStore; + +public interface DurableConfigurationStoreFactory extends Pluggable +{ + String getType(); + + DurableConfigurationStore createDurableConfigurationStore(); + + void validateAttributes(Map<String, Object> attributes); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java index 8093ed3d16..ab19fa196e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java @@ -30,8 +30,9 @@ import org.apache.qpid.server.virtualhost.VirtualHost; public interface ExchangeType<T extends Exchange> extends Pluggable { public String getType(); - public AMQShortString getName(); - public T newInstance(UUID id, VirtualHost host, AMQShortString name, + + public T newInstance(UUID id, VirtualHost host, String name, boolean durable, boolean autoDelete) throws AMQException; - public AMQShortString getDefaultExchangeName(); + + public String getDefaultExchangeName(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/MessageConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/MessageConverter.java new file mode 100644 index 0000000000..cf3860ba92 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/MessageConverter.java @@ -0,0 +1,32 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.plugin; + +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public interface MessageConverter<M extends ServerMessage, N extends ServerMessage> extends Pluggable +{ + Class<M> getInputClass(); + Class<N> getOutputClass(); + + N convert(M message, VirtualHost vhost); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/MessageMetaDataType.java index 0fab60b6f3..ee89782307 100755..100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataType.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/MessageMetaDataType.java @@ -18,27 +18,25 @@ * under the License. * */ -package org.apache.qpid.server.store; - -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.message.MessageMetaData_0_10; -import org.apache.qpid.server.message.MessageMetaData_1_0; +package org.apache.qpid.server.plugin; import java.nio.ByteBuffer; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.store.StorableMessageMetaData; +import org.apache.qpid.server.store.StoredMessage; -public enum MessageMetaDataType +public interface MessageMetaDataType<M extends StorableMessageMetaData> extends Pluggable { - META_DATA_0_8 { public Factory<MessageMetaData> getFactory() { return MessageMetaData.FACTORY; } }, - META_DATA_0_10 { public Factory<MessageMetaData_0_10> getFactory() { return MessageMetaData_0_10.FACTORY; } }, - META_DATA_1_0 { public Factory<MessageMetaData_1_0> getFactory() { return MessageMetaData_1_0.FACTORY; } }; - - public static interface Factory<M extends StorableMessageMetaData> { M createMetaData(ByteBuffer buf); } - abstract public Factory<? extends StorableMessageMetaData> getFactory(); + public int ordinal(); + + public M createMetaData(ByteBuffer buf); + + public ServerMessage<M> createMessage(StoredMessage<M> msg); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/PreferencesProviderFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/PreferencesProviderFactory.java new file mode 100644 index 0000000000..5a95b88591 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/PreferencesProviderFactory.java @@ -0,0 +1,12 @@ +package org.apache.qpid.server.plugin; + +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.PreferencesProvider; + +public interface PreferencesProviderFactory extends Pluggable +{ + PreferencesProvider createInstance(UUID id, Map<String, Object> attributes, AuthenticationProvider authenticationProvider); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ProtocolEngineCreator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ProtocolEngineCreator.java new file mode 100644 index 0000000000..2fa9084b8b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugin/ProtocolEngineCreator.java @@ -0,0 +1,35 @@ +package org.apache.qpid.server.plugin;/* + * + * 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. + * + */ + +import org.apache.qpid.protocol.ServerProtocolEngine; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.transport.network.NetworkConnection; + +public interface ProtocolEngineCreator extends Pluggable +{ + AmqpProtocolVersion getVersion(); + byte[] getHeaderIdentifier(); + ServerProtocolEngine newProtocolEngine(Broker broker, NetworkConnection network, Port port, Transport transport, long id); +} + diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java index e757898b69..19c5d03e0c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java @@ -92,4 +92,6 @@ public interface AMQConnectionModel extends StatisticsGatherer void stop(); boolean isStopped(); + + String getVirtualHostName(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/LinkModel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/LinkModel.java new file mode 100644 index 0000000000..16120a3523 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/LinkModel.java @@ -0,0 +1,25 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.protocol; + +public interface LinkModel +{ +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/LinkRegistry.java index 0bb9a15968..67d6e9f8d1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/LinkRegistry.java @@ -18,22 +18,22 @@ * under the License. * */ -package org.apache.qpid.server.protocol.v1_0; +package org.apache.qpid.server.protocol; import java.util.HashMap; import java.util.Map; public class LinkRegistry { - private final Map<String, SendingLink_1_0> _sendingLinks = new HashMap<String, SendingLink_1_0>(); - private final Map<String, ReceivingLink_1_0> _receivingLinks = new HashMap<String, ReceivingLink_1_0>(); + private final Map<String, LinkModel> _sendingLinks = new HashMap<String, LinkModel>(); + private final Map<String, LinkModel> _receivingLinks = new HashMap<String, LinkModel>(); - public synchronized SendingLink_1_0 getDurableSendingLink(String name) + public synchronized LinkModel getDurableSendingLink(String name) { return _sendingLinks.get(name); } - public synchronized boolean registerSendingLink(String name, SendingLink_1_0 link) + public synchronized boolean registerSendingLink(String name, LinkModel link) { if(_sendingLinks.containsKey(name)) { @@ -59,12 +59,12 @@ public class LinkRegistry } } - public synchronized ReceivingLink_1_0 getDurableReceivingLink(String name) + public synchronized LinkModel getDurableReceivingLink(String name) { return _receivingLinks.get(name); } - public synchronized boolean registerReceivingLink(String name, ReceivingLink_1_0 link) + public synchronized boolean registerReceivingLink(String name, LinkModel link) { if(_receivingLinks.containsKey(name)) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MessageConverterRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MessageConverterRegistry.java new file mode 100644 index 0000000000..81e5af179d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MessageConverterRegistry.java @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.protocol; + +import java.util.HashMap; +import java.util.Map; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.plugin.MessageConverter; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class MessageConverterRegistry +{ + private static Map<Class<? extends ServerMessage>, Map<Class<? extends ServerMessage>, MessageConverter>> _converters = + new HashMap<Class<? extends ServerMessage>, Map<Class<? extends ServerMessage>, MessageConverter>>(); + + static + { + + for(MessageConverter<? extends ServerMessage, ? extends ServerMessage> converter : (new QpidServiceLoader<MessageConverter>()).instancesOf(MessageConverter.class)) + { + Map<Class<? extends ServerMessage>, MessageConverter> map = _converters.get(converter.getInputClass()); + if(map == null) + { + map = new HashMap<Class<? extends ServerMessage>, MessageConverter>(); + _converters.put(converter.getInputClass(), map); + } + map.put(converter.getOutputClass(),converter); + } + } + + public static <M extends ServerMessage,N extends ServerMessage> MessageConverter<M, N> getConverter(Class<M> from, Class<N> to) + { + Map<Class<? extends ServerMessage>, MessageConverter> map = _converters.get(from); + if(map == null) + { + map = _converters.get(ServerMessage.class); + } + return map == null ? null : map.get(to); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 3834d22180..47b578c4ef 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -37,8 +37,7 @@ import org.apache.qpid.server.logging.messages.ConnectionMessages; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; -import org.apache.qpid.server.transport.ServerConnection; -import org.apache.qpid.transport.ConnectionDelegate; +import org.apache.qpid.server.plugin.ProtocolEngineCreator; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.transport.network.security.SSLStatus; @@ -55,6 +54,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine private final boolean _needClientAuth; private final Port _port; private final Transport _transport; + private final ProtocolEngineCreator[] _creators; private Set<AmqpProtocolVersion> _supported; private String _fqdn; @@ -69,7 +69,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine SSLContext sslContext, boolean wantClientAuth, boolean needClientAuth, final Set<AmqpProtocolVersion> supported, final AmqpProtocolVersion defaultSupportedReply, - Port port, Transport transport, final long id) + Port port, Transport transport, final long id, ProtocolEngineCreator[] creators) { if(defaultSupportedReply != null && !supported.contains(defaultSupportedReply)) { @@ -86,6 +86,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine _needClientAuth = needClientAuth; _port = port; _transport = transport; + _creators = creators; } @@ -142,73 +143,6 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine private static final int MINIMUM_REQUIRED_HEADER_BYTES = 8; - private static final byte[] AMQP_0_8_HEADER = - new byte[] { (byte) 'A', - (byte) 'M', - (byte) 'Q', - (byte) 'P', - (byte) 1, - (byte) 1, - (byte) 8, - (byte) 0 - }; - - private static final byte[] AMQP_0_9_HEADER = - new byte[] { (byte) 'A', - (byte) 'M', - (byte) 'Q', - (byte) 'P', - (byte) 1, - (byte) 1, - (byte) 0, - (byte) 9 - }; - - private static final byte[] AMQP_0_9_1_HEADER = - new byte[] { (byte) 'A', - (byte) 'M', - (byte) 'Q', - (byte) 'P', - (byte) 0, - (byte) 0, - (byte) 9, - (byte) 1 - }; - - - private static final byte[] AMQP_0_10_HEADER = - new byte[] { (byte) 'A', - (byte) 'M', - (byte) 'Q', - (byte) 'P', - (byte) 1, - (byte) 1, - (byte) 0, - (byte) 10 - }; - - private static final byte[] AMQP_1_0_0_HEADER = - new byte[] { (byte) 'A', - (byte) 'M', - (byte) 'Q', - (byte) 'P', - (byte) 0, - (byte) 1, - (byte) 0, - (byte) 0 - }; - - private static final byte[] AMQP_SASL_1_0_0_HEADER = - new byte[] { (byte) 'A', - (byte) 'M', - (byte) 'Q', - (byte) 'P', - (byte) 3, - (byte) 1, - (byte) 0, - (byte) 0 - }; - public void setNetworkConnection(NetworkConnection networkConnection) { setNetworkConnection(networkConnection, networkConnection.getSender()); @@ -242,144 +176,6 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine } - private static interface DelegateCreator - { - AmqpProtocolVersion getVersion(); - byte[] getHeaderIdentifier(); - ServerProtocolEngine getProtocolEngine(); - } - - private DelegateCreator creator_0_8 = new DelegateCreator() - { - - public AmqpProtocolVersion getVersion() - { - return AmqpProtocolVersion.v0_8; - } - - public byte[] getHeaderIdentifier() - { - return AMQP_0_8_HEADER; - } - - public ServerProtocolEngine getProtocolEngine() - { - return new AMQProtocolEngine(_broker, _network, _id, _port, _transport); - } - }; - - private DelegateCreator creator_0_9 = new DelegateCreator() - { - - public AmqpProtocolVersion getVersion() - { - return AmqpProtocolVersion.v0_9; - } - - - public byte[] getHeaderIdentifier() - { - return AMQP_0_9_HEADER; - } - - public ServerProtocolEngine getProtocolEngine() - { - return new AMQProtocolEngine(_broker, _network, _id, _port, _transport); - } - }; - - private DelegateCreator creator_0_9_1 = new DelegateCreator() - { - - public AmqpProtocolVersion getVersion() - { - return AmqpProtocolVersion.v0_9_1; - } - - - public byte[] getHeaderIdentifier() - { - return AMQP_0_9_1_HEADER; - } - - public ServerProtocolEngine getProtocolEngine() - { - return new AMQProtocolEngine(_broker, _network, _id, _port, _transport); - } - }; - - - private DelegateCreator creator_0_10 = new DelegateCreator() - { - - public AmqpProtocolVersion getVersion() - { - return AmqpProtocolVersion.v0_10; - } - - - public byte[] getHeaderIdentifier() - { - return AMQP_0_10_HEADER; - } - - public ServerProtocolEngine getProtocolEngine() - { - final ConnectionDelegate connDelegate = new org.apache.qpid.server.transport.ServerConnectionDelegate(_broker, - _fqdn, _broker.getSubjectCreator(getLocalAddress())); - - ServerConnection conn = new ServerConnection(_id); - - conn.setConnectionDelegate(connDelegate); - conn.setRemoteAddress(_network.getRemoteAddress()); - conn.setLocalAddress(_network.getLocalAddress()); - return new ProtocolEngine_0_10( conn, _network, _port, _transport); - } - }; - - private DelegateCreator creator_1_0_0 = new DelegateCreator() - { - - public AmqpProtocolVersion getVersion() - { - return AmqpProtocolVersion.v1_0_0; - } - - - public byte[] getHeaderIdentifier() - { - return AMQP_1_0_0_HEADER; - } - - public ServerProtocolEngine getProtocolEngine() - { - return new ProtocolEngine_1_0_0(_network, _broker, _id, _port, _transport); - } - }; - - private DelegateCreator creator_1_0_0_SASL = new DelegateCreator() - { - - public AmqpProtocolVersion getVersion() - { - return AmqpProtocolVersion.v1_0_0; - } - - - public byte[] getHeaderIdentifier() - { - return AMQP_SASL_1_0_0_HEADER; - } - - public ServerProtocolEngine getProtocolEngine() - { - return new ProtocolEngine_1_0_0_SASL(_network, _broker, _id, _port, _transport); - } - }; - - private final DelegateCreator[] _creators = - new DelegateCreator[] { creator_0_8, creator_0_9, creator_0_9_1, creator_0_10, creator_1_0_0_SASL, creator_1_0_0 }; - private class ClosedDelegateProtocolEngine implements ServerProtocolEngine { @@ -521,7 +317,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine } if(equal) { - newDelegate = _creators[i].getProtocolEngine(); + newDelegate = _creators[i].newProtocolEngine(_broker, _network, _port, _transport, _id); } } @@ -662,7 +458,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine { _decryptEngine = new MultiVersionProtocolEngine(_broker, null, false, false, _supported, - _defaultSupportedReply, _port, Transport.SSL, _id); + _defaultSupportedReply, _port, Transport.SSL, _id, _creators); _engine = _sslContext.createSSLEngine(); _engine.setUseClientMode(false); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java index 4b76546da1..3ce9383ee0 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java @@ -20,6 +20,8 @@ */ package org.apache.qpid.server.protocol; +import java.util.ArrayList; +import java.util.List; import javax.net.ssl.SSLContext; import org.apache.qpid.protocol.ProtocolEngineFactory; import org.apache.qpid.protocol.ServerProtocolEngine; @@ -29,6 +31,8 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.plugin.ProtocolEngineCreator; +import org.apache.qpid.server.plugin.QpidServiceLoader; public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory { @@ -42,6 +46,7 @@ public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory private final boolean _needClientAuth; private final Port _port; private final Transport _transport; + private final ProtocolEngineCreator[] _creators; public MultiVersionProtocolEngineFactory(Broker broker, SSLContext sslContext, @@ -62,6 +67,12 @@ public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory _sslContext = sslContext; _supported = supportedVersions; _defaultSupportedReply = defaultSupportedReply; + List<ProtocolEngineCreator> creators = new ArrayList<ProtocolEngineCreator>(); + for(ProtocolEngineCreator c : new QpidServiceLoader<ProtocolEngineCreator>().instancesOf(ProtocolEngineCreator.class)) + { + creators.add(c); + } + _creators = creators.toArray(new ProtocolEngineCreator[creators.size()]); _wantClientAuth = wantClientAuth; _needClientAuth = needClientAuth; _port = port; @@ -72,7 +83,7 @@ public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory { return new MultiVersionProtocolEngine(_broker, _sslContext, _wantClientAuth, _needClientAuth, _supported, _defaultSupportedReply, _port, _transport, - ID_GENERATOR.getAndIncrement() - ); + ID_GENERATOR.getAndIncrement(), + _creators); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index 4f610cc925..ceebe4f965 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java @@ -76,7 +76,7 @@ public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, Transa boolean isAutoDelete(); - AMQShortString getOwner(); + String getOwner(); AuthorizationHolder getAuthorizationHolder(); void setAuthorizationHolder(AuthorizationHolder principalHolder); @@ -225,7 +225,8 @@ public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, Transa void setAlternateExchange(Exchange exchange); - Map<String, Object> getArguments(); + Collection<String> getAvailableAttributes(); + Object getAttribute(String attrName); void checkCapacity(AMQSessionModel channel); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index 1eeb6dccf3..029c7e4f86 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java @@ -28,57 +28,46 @@ import java.util.UUID; import org.apache.qpid.AMQException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeFactory; -import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.store.DurableConfigurationStoreHelper; import org.apache.qpid.server.virtualhost.ExchangeExistsException; import org.apache.qpid.server.virtualhost.VirtualHost; -public class AMQQueueFactory +public class AMQQueueFactory implements QueueFactory { - public static final String X_QPID_FLOW_RESUME_CAPACITY = "x-qpid-flow-resume-capacity"; - public static final String X_QPID_CAPACITY = "x-qpid-capacity"; - public static final String X_QPID_MINIMUM_ALERT_REPEAT_GAP = "x-qpid-minimum-alert-repeat-gap"; - public static final String X_QPID_MAXIMUM_MESSAGE_COUNT = "x-qpid-maximum-message-count"; - public static final String X_QPID_MAXIMUM_MESSAGE_SIZE = "x-qpid-maximum-message-size"; - public static final String X_QPID_MAXIMUM_MESSAGE_AGE = "x-qpid-maximum-message-age"; - public static final String X_QPID_MAXIMUM_QUEUE_DEPTH = "x-qpid-maximum-queue-depth"; - - public static final String X_QPID_PRIORITIES = "x-qpid-priorities"; - public static final String X_QPID_DESCRIPTION = "x-qpid-description"; - public static final String QPID_LVQ_KEY = "qpid.LVQ_key"; - public static final String QPID_LAST_VALUE_QUEUE = "qpid.last_value_queue"; - public static final String QPID_LAST_VALUE_QUEUE_KEY = "qpid.last_value_queue_key"; - public static final String QPID_QUEUE_SORT_KEY = "qpid.queue_sort_key"; + public static final String QPID_DEFAULT_LVQ_KEY = "qpid.LVQ_key"; + - public static final String DLQ_ROUTING_KEY = "dlq"; - public static final String X_QPID_DLQ_ENABLED = "x-qpid-dlq-enabled"; - public static final String X_QPID_MAXIMUM_DELIVERY_COUNT = "x-qpid-maximum-delivery-count"; public static final String DEFAULT_DLQ_NAME_SUFFIX = "_DLQ"; + public static final String DLQ_ROUTING_KEY = "dlq"; + private static final int MAX_LENGTH = 255; - private AMQQueueFactory() + private final VirtualHost _virtualHost; + private final QueueRegistry _queueRegistry; + + public AMQQueueFactory(VirtualHost virtualHost, QueueRegistry queueRegistry) { + _virtualHost = virtualHost; + _queueRegistry = queueRegistry; } private abstract static class QueueProperty { - private final AMQShortString _argumentName; + private final String _argumentName; public QueueProperty(String argumentName) { - _argumentName = new AMQShortString(argumentName); + _argumentName = argumentName; } - public AMQShortString getArgumentName() + public String getArgumentName() { return _argumentName; } @@ -129,56 +118,56 @@ public class AMQQueueFactory } private static final QueueProperty[] DECLAREABLE_PROPERTIES = { - new QueueLongProperty(X_QPID_MAXIMUM_MESSAGE_AGE) + new QueueLongProperty(Queue.ALERT_THRESHOLD_MESSAGE_AGE) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMaximumMessageAge(value); } }, - new QueueLongProperty(X_QPID_MAXIMUM_MESSAGE_SIZE) + new QueueLongProperty(Queue.ALERT_THRESHOLD_MESSAGE_SIZE) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMaximumMessageSize(value); } }, - new QueueLongProperty(X_QPID_MAXIMUM_MESSAGE_COUNT) + new QueueLongProperty(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMaximumMessageCount(value); } }, - new QueueLongProperty(X_QPID_MAXIMUM_QUEUE_DEPTH) + new QueueLongProperty(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMaximumQueueDepth(value); } }, - new QueueLongProperty(X_QPID_MINIMUM_ALERT_REPEAT_GAP) + new QueueLongProperty(Queue.ALERT_REPEAT_GAP) { public void setPropertyValue(AMQQueue queue, long value) { queue.setMinimumAlertRepeatGap(value); } }, - new QueueLongProperty(X_QPID_CAPACITY) + new QueueLongProperty(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES) { public void setPropertyValue(AMQQueue queue, long value) { queue.setCapacity(value); } }, - new QueueLongProperty(X_QPID_FLOW_RESUME_CAPACITY) + new QueueLongProperty(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES) { public void setPropertyValue(AMQQueue queue, long value) { queue.setFlowResumeCapacity(value); } }, - new QueueIntegerProperty(X_QPID_MAXIMUM_DELIVERY_COUNT) + new QueueIntegerProperty(Queue.MAXIMUM_DELIVERY_ATTEMPTS) { public void setPropertyValue(AMQQueue queue, int value) { @@ -187,15 +176,45 @@ public class AMQQueueFactory } }; + @Override + public AMQQueue restoreQueue(UUID id, + String queueName, + String owner, + boolean autoDelete, + boolean exclusive, + boolean deleteOnNoConsumer, + Map<String, Object> arguments) throws AMQSecurityException, AMQException + { + return createOrRestoreQueue(id, queueName, true, owner, autoDelete, exclusive, deleteOnNoConsumer, arguments, false); + + } + /** * @param id the id to use. + * @param deleteOnNoConsumer */ - public static AMQQueue createAMQQueueImpl(UUID id, - String queueName, - boolean durable, - String owner, - boolean autoDelete, - boolean exclusive, VirtualHost virtualHost, Map<String, Object> arguments) throws AMQSecurityException, AMQException + @Override + public AMQQueue createQueue(UUID id, + String queueName, + boolean durable, + String owner, + boolean autoDelete, + boolean exclusive, + boolean deleteOnNoConsumer, + Map<String, Object> arguments) throws AMQSecurityException, AMQException + { + return createOrRestoreQueue(id, queueName, durable, owner, autoDelete, exclusive, deleteOnNoConsumer, arguments, true); + } + + private AMQQueue createOrRestoreQueue(UUID id, + String queueName, + boolean durable, + String owner, + boolean autoDelete, + boolean exclusive, + boolean deleteOnNoConsumer, + Map<String, Object> arguments, + boolean createInStore) throws AMQSecurityException, AMQException { if (id == null) { @@ -206,16 +225,11 @@ public class AMQQueueFactory throw new IllegalArgumentException("Queue name must not be null"); } - // Access check - if (!virtualHost.getSecurityManager().authoriseCreateQueue(autoDelete, durable, exclusive, null, null, new AMQShortString(queueName), owner)) - { - String description = "Permission denied: queue-name '" + queueName + "'"; - throw new AMQSecurityException(description); - } - QueueConfiguration queueConfiguration = virtualHost.getConfiguration().getQueueConfiguration(queueName); - boolean isDLQEnabled = isDLQEnabled(autoDelete, arguments, queueConfiguration); - if (isDLQEnabled) + QueueConfiguration queueConfiguration = _virtualHost.getConfiguration().getQueueConfiguration(queueName); + + boolean createDLQ = createDLQ(autoDelete, arguments, queueConfiguration); + if (createDLQ) { validateDLNames(queueName); } @@ -226,17 +240,17 @@ public class AMQQueueFactory if(arguments != null) { - if(arguments.containsKey(QPID_LAST_VALUE_QUEUE) || arguments.containsKey(QPID_LAST_VALUE_QUEUE_KEY)) + if(arguments.containsKey(Queue.LVQ_KEY)) { - conflationKey = (String) arguments.get(QPID_LAST_VALUE_QUEUE_KEY); + conflationKey = (String) arguments.get(Queue.LVQ_KEY); if(conflationKey == null) { - conflationKey = QPID_LVQ_KEY; + conflationKey = QPID_DEFAULT_LVQ_KEY; } } - else if(arguments.containsKey(X_QPID_PRIORITIES)) + else if(arguments.containsKey(Queue.PRIORITIES)) { - Object prioritiesObj = arguments.get(X_QPID_PRIORITIES); + Object prioritiesObj = arguments.get(Queue.PRIORITIES); if(prioritiesObj instanceof Number) { priorities = ((Number)prioritiesObj).intValue(); @@ -257,60 +271,67 @@ public class AMQQueueFactory // TODO - should warn here of invalid format } } - else if(arguments.containsKey(QPID_QUEUE_SORT_KEY)) + else if(arguments.containsKey(Queue.SORT_KEY)) { - sortingKey = (String)arguments.get(QPID_QUEUE_SORT_KEY); + sortingKey = (String)arguments.get(Queue.SORT_KEY); } } AMQQueue q; if(sortingKey != null) { - q = new SortedQueue(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, sortingKey); + q = new SortedQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments, sortingKey); } else if(conflationKey != null) { - q = new ConflationQueue(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, conflationKey); + q = new ConflationQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments, conflationKey); } else if(priorities > 1) { - q = new AMQPriorityQueue(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments, priorities); + q = new AMQPriorityQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments, priorities); } else { - q = new SimpleAMQQueue(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, arguments); + q = new SimpleAMQQueue(id, queueName, durable, owner, autoDelete, exclusive, _virtualHost, arguments); } + q.setDeleteOnNoConsumers(deleteOnNoConsumer); + //Register the new queue - virtualHost.getQueueRegistry().registerQueue(q); - q.configure(virtualHost.getConfiguration().getQueueConfiguration(queueName)); + _queueRegistry.registerQueue(q); + + q.configure(_virtualHost.getConfiguration().getQueueConfiguration(queueName)); if(arguments != null) { for(QueueProperty p : DECLAREABLE_PROPERTIES) { - if(arguments.containsKey(p.getArgumentName().toString())) + if(arguments.containsKey(p.getArgumentName())) { - p.setPropertyValue(q, arguments.get(p.getArgumentName().toString())); + p.setPropertyValue(q, arguments.get(p.getArgumentName())); } } + + if(arguments.get(Queue.NO_LOCAL) instanceof Boolean) + { + q.setNoLocal((Boolean)arguments.get(Queue.NO_LOCAL)); + } + } - if(isDLQEnabled) + if(createDLQ) { final String dlExchangeName = getDeadLetterExchangeName(queueName); final String dlQueueName = getDeadLetterQueueName(queueName); - final QueueRegistry queueRegistry = virtualHost.getQueueRegistry(); - Exchange dlExchange = null; - final UUID dlExchangeId = UUIDGenerator.generateExchangeUUID(dlExchangeName, virtualHost.getName()); + final UUID dlExchangeId = UUIDGenerator.generateExchangeUUID(dlExchangeName, _virtualHost.getName()); try { - dlExchange = virtualHost.createExchange(dlExchangeId, + dlExchange = _virtualHost.createExchange(dlExchangeId, dlExchangeName, - ExchangeDefaults.FANOUT_EXCHANGE_CLASS.toString(), + ExchangeDefaults.FANOUT_EXCHANGE_CLASS, true, false, null); } catch(ExchangeExistsException e) @@ -321,23 +342,19 @@ public class AMQQueueFactory AMQQueue dlQueue = null; - synchronized(queueRegistry) + synchronized(_queueRegistry) { - dlQueue = queueRegistry.getQueue(dlQueueName); + dlQueue = _queueRegistry.getQueue(dlQueueName); if(dlQueue == null) { //set args to disable DLQ'ing/MDC from the DLQ itself, preventing loops etc final Map<String, Object> args = new HashMap<String, Object>(); - args.put(X_QPID_DLQ_ENABLED, false); - args.put(X_QPID_MAXIMUM_DELIVERY_COUNT, 0); + args.put(Queue.CREATE_DLQ_ON_CREATION, false); + args.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 0); - dlQueue = createAMQQueueImpl(UUIDGenerator.generateQueueUUID(dlQueueName, virtualHost.getName()), dlQueueName, true, owner, false, exclusive, virtualHost, args); - - //enter the dlq in the persistent store - DurableConfigurationStoreHelper.createQueue(virtualHost.getDurableConfigurationStore(), - dlQueue, - FieldTable.convertToFieldTable(args)); + dlQueue = _virtualHost.createQueue(UUIDGenerator.generateQueueUUID(dlQueueName, _virtualHost.getName()), dlQueueName, true, owner, false, exclusive, + false, args); } } @@ -350,11 +367,31 @@ public class AMQQueueFactory } q.setAlternateExchange(dlExchange); } + else if(arguments != null && arguments.get(Queue.ALTERNATE_EXCHANGE) instanceof String) + { + + final String altExchangeAttr = (String) arguments.get(Queue.ALTERNATE_EXCHANGE); + Exchange altExchange; + try + { + altExchange = _virtualHost.getExchange(UUID.fromString(altExchangeAttr)); + } + catch(IllegalArgumentException e) + { + altExchange = _virtualHost.getExchange(altExchangeAttr); + } + q.setAlternateExchange(altExchange); + } + + if (createInStore && q.isDurable() && !q.isAutoDelete()) + { + DurableConfigurationStoreHelper.createQueue(_virtualHost.getDurableConfigurationStore(), q); + } return q; } - public static AMQQueue createAMQQueueImpl(QueueConfiguration config, VirtualHost host) throws AMQException + public AMQQueue createAMQQueueImpl(QueueConfiguration config) throws AMQException { String queueName = config.getName(); @@ -365,9 +402,9 @@ public class AMQQueueFactory Map<String, Object> arguments = createQueueArgumentsFromConfig(config); // we need queues that are defined in config to have deterministic ids. - UUID id = UUIDGenerator.generateQueueUUID(queueName, host.getName()); + UUID id = UUIDGenerator.generateQueueUUID(queueName, _virtualHost.getName()); - AMQQueue q = createAMQQueueImpl(id, queueName, durable, owner, autodelete, exclusive, host, arguments); + AMQQueue q = createQueue(id, queueName, durable, owner, autodelete, exclusive, false, arguments); q.configure(config); return q; } @@ -390,16 +427,16 @@ public class AMQQueueFactory { // check if DLQ name and DLQ exchange name do not exceed 255 String exchangeName = getDeadLetterExchangeName(name); - if (exchangeName.length() > AMQShortString.MAX_LENGTH) + if (exchangeName.length() > MAX_LENGTH) { throw new IllegalArgumentException("DL exchange name '" + exchangeName - + "' length exceeds limit of " + AMQShortString.MAX_LENGTH + " characters for queue " + name); + + "' length exceeds limit of " + MAX_LENGTH + " characters for queue " + name); } String queueName = getDeadLetterQueueName(name); - if (queueName.length() > AMQShortString.MAX_LENGTH) + if (queueName.length() > MAX_LENGTH) { throw new IllegalArgumentException("DLQ queue name '" + queueName + "' length exceeds limit of " - + AMQShortString.MAX_LENGTH + " characters for queue " + name); + + MAX_LENGTH + " characters for queue " + name); } } @@ -414,21 +451,23 @@ public class AMQQueueFactory * queue configuration * @return true if DLQ enabled */ - protected static boolean isDLQEnabled(boolean autoDelete, Map<String, Object> arguments, QueueConfiguration qConfig) + protected static boolean createDLQ(boolean autoDelete, Map<String, Object> arguments, QueueConfiguration qConfig) { //feature is not to be enabled for temporary queues or when explicitly disabled by argument - if (!autoDelete) + if (!(autoDelete || (arguments != null && arguments.containsKey(Queue.ALTERNATE_EXCHANGE)))) { - boolean dlqArgumentPresent = arguments != null && arguments.containsKey(X_QPID_DLQ_ENABLED); + boolean dlqArgumentPresent = arguments != null + && arguments.containsKey(Queue.CREATE_DLQ_ON_CREATION); if (dlqArgumentPresent || qConfig.isDeadLetterQueueEnabled()) { boolean dlqEnabled = true; if (dlqArgumentPresent) { - Object argument = arguments.get(X_QPID_DLQ_ENABLED); - dlqEnabled = argument instanceof Boolean && ((Boolean)argument).booleanValue(); + Object argument = arguments.get(Queue.CREATE_DLQ_ON_CREATION); + dlqEnabled = (argument instanceof Boolean && ((Boolean)argument).booleanValue()) + || (argument instanceof String && Boolean.parseBoolean(argument.toString())); } - return dlqEnabled; + return dlqEnabled ; } } return false; @@ -464,31 +503,30 @@ public class AMQQueueFactory if(config.getArguments() != null && !config.getArguments().isEmpty()) { - arguments.putAll(config.getArguments()); + arguments.putAll(QueueArgumentsConverter.convertWireArgsToModel(new HashMap<String, Object>(config.getArguments()))); } if(config.isLVQ() || config.getLVQKey() != null) { - arguments.put(QPID_LAST_VALUE_QUEUE, 1); - arguments.put(QPID_LAST_VALUE_QUEUE_KEY, config.getLVQKey() == null ? QPID_LVQ_KEY : config.getLVQKey()); + arguments.put(Queue.LVQ_KEY, config.getLVQKey() == null ? QPID_DEFAULT_LVQ_KEY : config.getLVQKey()); } else if (config.getPriority() || config.getPriorities() > 0) { - arguments.put(X_QPID_PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities()); + arguments.put(Queue.PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities()); } else if (config.getQueueSortKey() != null && !"".equals(config.getQueueSortKey())) { - arguments.put(QPID_QUEUE_SORT_KEY, config.getQueueSortKey()); + arguments.put(Queue.SORT_KEY, config.getQueueSortKey()); } if (!config.getAutoDelete() && config.isDeadLetterQueueEnabled()) { - arguments.put(X_QPID_DLQ_ENABLED, true); + arguments.put(Queue.CREATE_DLQ_ON_CREATION, true); } if (config.getDescription() != null && !"".equals(config.getDescription())) { - arguments.put(X_QPID_DESCRIPTION, config.getDescription()); + arguments.put(Queue.DESCRIPTION, config.getDescription()); } if (arguments.isEmpty()) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java index cef7e2d0c8..6145570b0c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/BaseQueue.java @@ -40,5 +40,5 @@ public interface BaseQueue extends TransactionLogResource boolean isDurable(); boolean isDeleted(); - AMQShortString getNameShortString(); + String getName(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java index 27a9e13617..7d091dbf73 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.ArrayList; @@ -31,7 +30,7 @@ import java.util.concurrent.ConcurrentMap; public class DefaultQueueRegistry implements QueueRegistry { - private ConcurrentMap<AMQShortString, AMQQueue> _queueMap = new ConcurrentHashMap<AMQShortString, AMQQueue>(); + private ConcurrentMap<String, AMQQueue> _queueMap = new ConcurrentHashMap<String, AMQQueue>(); private final VirtualHost _virtualHost; private final Collection<RegistryChangeListener> _listeners = @@ -49,7 +48,7 @@ public class DefaultQueueRegistry implements QueueRegistry public void registerQueue(AMQQueue queue) { - _queueMap.put(queue.getNameShortString(), queue); + _queueMap.put(queue.getName(), queue); synchronized (_listeners) { for(RegistryChangeListener listener : _listeners) @@ -59,7 +58,7 @@ public class DefaultQueueRegistry implements QueueRegistry } } - public void unregisterQueue(AMQShortString name) + public void unregisterQueue(String name) { AMQQueue q = _queueMap.remove(name); if(q != null) @@ -74,15 +73,6 @@ public class DefaultQueueRegistry implements QueueRegistry } } - public AMQQueue getQueue(AMQShortString name) - { - return _queueMap.get(name); - } - - public Collection<AMQShortString> getQueueNames() - { - return _queueMap.keySet(); - } public Collection<AMQQueue> getQueues() { @@ -91,7 +81,7 @@ public class DefaultQueueRegistry implements QueueRegistry public AMQQueue getQueue(String queue) { - return getQueue(new AMQShortString(queue)); + return queue == null ? null : _queueMap.get(queue); } public void addRegistryChangeListener(RegistryChangeListener listener) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java index d7dbd58537..2a78ee430c 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java @@ -44,12 +44,6 @@ public class InboundMessageAdapter implements InboundMessage _entry = entry; } - - public AMQShortString getRoutingKeyShortString() - { - return AMQShortString.valueOf(_entry.getMessage().getRoutingKey()); - } - public String getRoutingKey() { return _entry.getMessage().getRoutingKey(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java index 3efef9ab98..566cdd0ea5 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java @@ -28,7 +28,7 @@ public enum NotificationCheck MESSAGE_COUNT_ALERT
{
- public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener) + public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
int msgCount;
final long maximumMessageCount = queue.getMaximumMessageCount();
@@ -45,7 +45,7 @@ public enum NotificationCheck },
MESSAGE_SIZE_ALERT(true)
{
- public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener) + public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
final long maximumMessageSize = queue.getMaximumMessageSize();
if(maximumMessageSize != 0)
@@ -57,7 +57,7 @@ public enum NotificationCheck if (messageSize >= maximumMessageSize)
{
String notificationMsg = messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageNumber() + "]";
-
+
logNotification(this, queue, notificationMsg);
listener.notifyClients(this, queue, notificationMsg);
return true;
@@ -69,7 +69,7 @@ public enum NotificationCheck },
QUEUE_DEPTH_ALERT
{
- public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener) + public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
// Check for threshold queue depth in bytes
final long maximumQueueDepth = queue.getMaximumQueueDepth();
@@ -81,7 +81,7 @@ public enum NotificationCheck if (queueDepth >= maximumQueueDepth)
{
String notificationMsg = (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.";
-
+
logNotification(this, queue, notificationMsg);
listener.notifyClients(this, queue, notificationMsg);
return true;
@@ -93,7 +93,7 @@ public enum NotificationCheck },
MESSAGE_AGE_ALERT
{
- public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener) + public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener)
{
final long maxMessageAge = queue.getMaximumMessageAge();
@@ -107,7 +107,7 @@ public enum NotificationCheck {
long oldestAge = currentTime - firstArrivalTime;
String notificationMsg = (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.";
-
+
logNotification(this, queue, notificationMsg);
listener.notifyClients(this, queue, notificationMsg);
@@ -115,7 +115,7 @@ public enum NotificationCheck }
}
return false;
-
+
}
}
@@ -140,11 +140,11 @@ public enum NotificationCheck return _messageSpecific;
}
- public abstract boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener); + public abstract boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener);
//A bit of a hack, only for use until we do the logging listener
private static void logNotification(NotificationCheck notification, AMQQueue queue, String notificationMsg)
{
- LOGGER.info(notification.name() + " On Queue " + queue.getNameShortString() + " - " + notificationMsg);
+ LOGGER.info(notification.name() + " On Queue " + queue.getName() + " - " + notificationMsg);
}
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueArgumentsConverter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueArgumentsConverter.java new file mode 100644 index 0000000000..589f385d22 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueArgumentsConverter.java @@ -0,0 +1,152 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.queue; + +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import org.apache.qpid.server.model.Queue; + +public class QueueArgumentsConverter +{ + public static final String X_QPID_FLOW_RESUME_CAPACITY = "x-qpid-flow-resume-capacity"; + public static final String X_QPID_CAPACITY = "x-qpid-capacity"; + public static final String X_QPID_MINIMUM_ALERT_REPEAT_GAP = "x-qpid-minimum-alert-repeat-gap"; + public static final String X_QPID_MAXIMUM_MESSAGE_COUNT = "x-qpid-maximum-message-count"; + public static final String X_QPID_MAXIMUM_MESSAGE_SIZE = "x-qpid-maximum-message-size"; + public static final String X_QPID_MAXIMUM_MESSAGE_AGE = "x-qpid-maximum-message-age"; + public static final String X_QPID_MAXIMUM_QUEUE_DEPTH = "x-qpid-maximum-queue-depth"; + + public static final String QPID_ALERT_COUNT = "qpid.alert_count"; + public static final String QPID_ALERT_SIZE = "qpid.alert_size"; + public static final String QPID_ALERT_REPEAT_GAP = "qpid.alert_repeat_gap"; + + public static final String X_QPID_PRIORITIES = "x-qpid-priorities"; + + public static final String X_QPID_DESCRIPTION = "x-qpid-description"; + + public static final String QPID_LAST_VALUE_QUEUE_KEY = "qpid.last_value_queue_key"; + + public static final String QPID_QUEUE_SORT_KEY = "qpid.queue_sort_key"; + public static final String X_QPID_DLQ_ENABLED = "x-qpid-dlq-enabled"; + public static final String X_QPID_MAXIMUM_DELIVERY_COUNT = "x-qpid-maximum-delivery-count"; + public static final String QPID_GROUP_HEADER_KEY = "qpid.group_header_key"; + public static final String QPID_SHARED_MSG_GROUP = "qpid.shared_msg_group"; + public static final String QPID_DEFAULT_MESSAGE_GROUP_ARG = "qpid.default-message-group"; + public static final String QPID_TRACE_EXCLUDE = "qpid.trace.exclude"; + public static final String QPID_TRACE_ID = "qpid.trace.id"; + + public static final String QPID_LAST_VALUE_QUEUE = "qpid.last_value_queue"; + + /** + * No-local queue argument is used to support the no-local feature of Durable Subscribers. + */ + public static final String QPID_NO_LOCAL = "no-local"; + static final Map<String, String> ATTRIBUTE_MAPPINGS = new LinkedHashMap<String, String>(); + static + { + ATTRIBUTE_MAPPINGS.put(X_QPID_MINIMUM_ALERT_REPEAT_GAP, Queue.ALERT_REPEAT_GAP); + ATTRIBUTE_MAPPINGS.put(X_QPID_MAXIMUM_MESSAGE_AGE, Queue.ALERT_THRESHOLD_MESSAGE_AGE); + ATTRIBUTE_MAPPINGS.put(X_QPID_MAXIMUM_MESSAGE_SIZE, Queue.ALERT_THRESHOLD_MESSAGE_SIZE); + + ATTRIBUTE_MAPPINGS.put(X_QPID_MAXIMUM_MESSAGE_COUNT, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES); + ATTRIBUTE_MAPPINGS.put(X_QPID_MAXIMUM_QUEUE_DEPTH, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES); + ATTRIBUTE_MAPPINGS.put(QPID_ALERT_COUNT, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES); + ATTRIBUTE_MAPPINGS.put(QPID_ALERT_SIZE, Queue.ALERT_THRESHOLD_QUEUE_DEPTH_BYTES); + ATTRIBUTE_MAPPINGS.put(QPID_ALERT_REPEAT_GAP, Queue.ALERT_REPEAT_GAP); + + ATTRIBUTE_MAPPINGS.put(X_QPID_MAXIMUM_DELIVERY_COUNT, Queue.MAXIMUM_DELIVERY_ATTEMPTS); + + ATTRIBUTE_MAPPINGS.put(X_QPID_CAPACITY, Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES); + ATTRIBUTE_MAPPINGS.put(X_QPID_FLOW_RESUME_CAPACITY, Queue.QUEUE_FLOW_RESUME_SIZE_BYTES); + + ATTRIBUTE_MAPPINGS.put(QPID_QUEUE_SORT_KEY, Queue.SORT_KEY); + ATTRIBUTE_MAPPINGS.put(QPID_LAST_VALUE_QUEUE_KEY, Queue.LVQ_KEY); + ATTRIBUTE_MAPPINGS.put(X_QPID_PRIORITIES, Queue.PRIORITIES); + + ATTRIBUTE_MAPPINGS.put(X_QPID_DESCRIPTION, Queue.DESCRIPTION); + + ATTRIBUTE_MAPPINGS.put(X_QPID_DLQ_ENABLED, Queue.CREATE_DLQ_ON_CREATION); + ATTRIBUTE_MAPPINGS.put(QPID_GROUP_HEADER_KEY, Queue.MESSAGE_GROUP_KEY); + //ATTRIBUTE_MAPPINGS.put(QPID_SHARED_MSG_GROUP, Queue.MESSAGE_GROUP_SHARED_GROUPS); + ATTRIBUTE_MAPPINGS.put(QPID_DEFAULT_MESSAGE_GROUP_ARG, Queue.MESSAGE_GROUP_DEFAULT_GROUP); + ATTRIBUTE_MAPPINGS.put(QPID_TRACE_EXCLUDE, Queue.FEDERATION_EXCLUDES); + ATTRIBUTE_MAPPINGS.put(QPID_TRACE_ID, Queue.FEDERATION_ID); + ATTRIBUTE_MAPPINGS.put(QPID_NO_LOCAL, Queue.NO_LOCAL); + + } + + + public static Map<String,Object> convertWireArgsToModel(Map<String,Object> wireArguments) + { + Map<String,Object> modelArguments = new HashMap<String, Object>(); + if(wireArguments != null) + { + for(Map.Entry<String,String> entry : ATTRIBUTE_MAPPINGS.entrySet()) + { + if(wireArguments.containsKey(entry.getKey())) + { + modelArguments.put(entry.getValue(), wireArguments.get(entry.getKey())); + } + } + if(wireArguments.containsKey(QPID_LAST_VALUE_QUEUE) && !wireArguments.containsKey(QPID_LAST_VALUE_QUEUE_KEY)) + { + modelArguments.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_DEFAULT_LVQ_KEY); + } + if(wireArguments.containsKey(QPID_SHARED_MSG_GROUP)) + { + modelArguments.put(Queue.MESSAGE_GROUP_SHARED_GROUPS, + SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE.equals(String.valueOf(wireArguments.get(QPID_SHARED_MSG_GROUP)))); + } + if(wireArguments.get(X_QPID_DLQ_ENABLED) != null) + { + modelArguments.put(Queue.CREATE_DLQ_ON_CREATION, Boolean.parseBoolean(wireArguments.get(X_QPID_DLQ_ENABLED).toString())); + } + + if(wireArguments.get(QPID_NO_LOCAL) != null) + { + modelArguments.put(Queue.NO_LOCAL, Boolean.parseBoolean(wireArguments.get(QPID_NO_LOCAL).toString())); + } + + } + return modelArguments; + } + + + public static Map<String,Object> convertModelArgsToWire(Map<String,Object> modelArguments) + { + Map<String,Object> wireArguments = new HashMap<String, Object>(); + for(Map.Entry<String,String> entry : ATTRIBUTE_MAPPINGS.entrySet()) + { + if(modelArguments.containsKey(entry.getValue())) + { + wireArguments.put(entry.getKey(), modelArguments.get(entry.getValue())); + } + } + + if(Boolean.TRUE.equals(modelArguments.get(Queue.MESSAGE_GROUP_SHARED_GROUPS))) + { + wireArguments.put(QPID_SHARED_MSG_GROUP, SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE); + } + + return wireArguments; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueFactory.java new file mode 100644 index 0000000000..3e4e1df5a2 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueFactory.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.queue; + +import java.util.Map; +import java.util.UUID; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQSecurityException; + +public interface QueueFactory +{ + AMQQueue createQueue(UUID id, + String queueName, + boolean durable, + String owner, + boolean autoDelete, + boolean exclusive, + boolean deleteOnNoConsumer, + Map<String, Object> arguments) throws AMQSecurityException, AMQException; + + AMQQueue restoreQueue(UUID id, + String queueName, + String owner, + boolean autoDelete, + boolean exclusive, + boolean deleteOnNoConsumer, + Map<String, Object> arguments) throws AMQSecurityException, AMQException; + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java index e8c34128e9..bc1d5942bd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Collection; @@ -32,11 +31,7 @@ public interface QueueRegistry void registerQueue(AMQQueue queue); - void unregisterQueue(AMQShortString name); - - AMQQueue getQueue(AMQShortString name); - - Collection<AMQShortString> getQueueNames(); + void unregisterQueue(String name); Collection<AMQQueue> getQueues(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index b0ab93162a..fb36433799 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.EnumSet; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -51,6 +51,7 @@ import org.apache.qpid.server.logging.actors.QueueActor; import org.apache.qpid.server.logging.messages.QueueMessages; import org.apache.qpid.server.logging.subjects.QueueLogSubject; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.security.AuthorizationHolder; import org.apache.qpid.server.subscription.AssignedSubscriptionMessageGroupManager; @@ -68,21 +69,19 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class); - public static final String QPID_GROUP_HEADER_KEY = "qpid.group_header_key"; - public static final String QPID_SHARED_MSG_GROUP = "qpid.shared_msg_group"; public static final String SHARED_MSG_GROUP_ARG_VALUE = "1"; - private static final String QPID_DEFAULT_MESSAGE_GROUP_ARG = "qpid.default-message-group"; private static final String QPID_NO_GROUP = "qpid.no-group"; private static final String DEFAULT_SHARED_MESSAGE_GROUP = System.getProperty(BrokerProperties.PROPERTY_DEFAULT_SHARED_MESSAGE_GROUP, QPID_NO_GROUP); + // TODO - should make this configurable at the vhost / broker level private static final int DEFAULT_MAX_GROUPS = 255; private final VirtualHost _virtualHost; - private final AMQShortString _name; + private final String _name; /** null means shared */ - private final AMQShortString _owner; + private final String _owner; private AuthorizationHolder _authorizationHolder; @@ -195,25 +194,16 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private AMQQueue.NotificationListener _notificationListener; private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length]; - protected SimpleAMQQueue(UUID id, AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String,Object> arguments) - { - this(id, name, durable, owner, autoDelete, exclusive,virtualHost, new SimpleQueueEntryList.Factory(), arguments); - } public SimpleAMQQueue(UUID id, String queueName, boolean durable, String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String, Object> arguments) { this(id, queueName, durable, owner, autoDelete, exclusive, virtualHost, new SimpleQueueEntryList.Factory(), arguments); } - public SimpleAMQQueue(UUID id, String queueName, boolean durable, String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, QueueEntryListFactory entryListFactory, Map<String, Object> arguments) - { - this(id, queueName == null ? null : new AMQShortString(queueName), durable, owner == null ? null : new AMQShortString(owner), autoDelete, exclusive, virtualHost, entryListFactory, arguments); - } - protected SimpleAMQQueue(UUID id, - AMQShortString name, + String name, boolean durable, - AMQShortString owner, + String owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, @@ -237,7 +227,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes _exclusive = exclusive; _virtualHost = virtualHost; _entries = entryListFactory.createQueueEntryList(this); - _arguments = arguments == null ? new HashMap<String, Object>() : new HashMap<String, Object>(arguments); + _arguments = Collections.synchronizedMap(arguments == null ? new LinkedHashMap<String, Object>() : new LinkedHashMap<String, Object>(arguments)); _id = id; _asyncDelivery = ReferenceCountingExecutorService.getInstance().acquireExecutorService(); @@ -255,19 +245,21 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes durable, !durable, _entries.getPriorities() > 0)); - if(arguments != null && arguments.containsKey(QPID_GROUP_HEADER_KEY)) + if(arguments != null && arguments.containsKey(Queue.MESSAGE_GROUP_KEY)) { - if(arguments.containsKey(QPID_SHARED_MSG_GROUP) && String.valueOf(arguments.get(QPID_SHARED_MSG_GROUP)).equals(SHARED_MSG_GROUP_ARG_VALUE)) + if(arguments.get(Queue.MESSAGE_GROUP_SHARED_GROUPS) != null + && (Boolean)(arguments.get(Queue.MESSAGE_GROUP_SHARED_GROUPS))) { - Object defaultGroup = arguments.get(QPID_DEFAULT_MESSAGE_GROUP_ARG); + Object defaultGroup = arguments.get(Queue.MESSAGE_GROUP_DEFAULT_GROUP); _messageGroupManager = - new DefinedGroupMessageGroupManager(String.valueOf(arguments.get(QPID_GROUP_HEADER_KEY)), + new DefinedGroupMessageGroupManager(String.valueOf(arguments.get(Queue.MESSAGE_GROUP_KEY)), defaultGroup == null ? DEFAULT_SHARED_MESSAGE_GROUP : defaultGroup.toString(), this); } else { - _messageGroupManager = new AssignedSubscriptionMessageGroupManager(String.valueOf(arguments.get(QPID_GROUP_HEADER_KEY)), DEFAULT_MAX_GROUPS); + _messageGroupManager = new AssignedSubscriptionMessageGroupManager(String.valueOf(arguments.get( + Queue.MESSAGE_GROUP_KEY)), DEFAULT_MAX_GROUPS); } } else @@ -310,11 +302,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } } - public AMQShortString getNameShortString() - { - return _name; - } - public void setNoLocal(boolean nolocal) { _nolocal = nolocal; @@ -358,13 +345,17 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes _alternateExchange = exchange; } - /** - * Arguments used to create this queue. The caller is assured - * that null will never be returned. - */ - public Map<String, Object> getArguments() + + @Override + public Collection<String> getAvailableAttributes() { - return _arguments; + return new ArrayList<String>(_arguments.keySet()); + } + + @Override + public Object getAttribute(String attrName) + { + return _arguments.get(attrName); } public boolean isAutoDelete() @@ -372,7 +363,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes return _autoDelete; } - public AMQShortString getOwner() + public String getOwner() { return _owner; } @@ -395,7 +386,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes public String getName() { - return getNameShortString().toString(); + return _name; } // ------ Manage Subscriptions @@ -511,7 +502,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes _logger.info("Auto-deleteing queue:" + this); } - delete(); + getVirtualHost().removeQueue(this); // we need to manually fire the event to the removed subscription (which was the last one left for this // queue. This is because the delete method uses the subscription set which has just been cleared @@ -1061,7 +1052,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes public int compareTo(final AMQQueue o) { - return _name.compareTo(o.getNameShortString()); + return _name.compareTo(o.getName()); } public AtomicInteger getAtomicQueueCount() @@ -1340,7 +1331,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } } - _virtualHost.getQueueRegistry().unregisterQueue(_name); List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() { @@ -2192,7 +2182,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes @Override public String toString() { - return String.valueOf(getNameShortString()); + return getName(); } public long getUnackedMessageCountHigh() @@ -2282,18 +2272,18 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { if (description == null) { - _arguments.remove(AMQQueueFactory.X_QPID_DESCRIPTION); + _arguments.remove(Queue.DESCRIPTION); } else { - _arguments.put(AMQQueueFactory.X_QPID_DESCRIPTION, description); + _arguments.put(Queue.DESCRIPTION, description); } } @Override public String getDescription() { - return (String) _arguments.get(AMQQueueFactory.X_QPID_DESCRIPTION); + return (String) _arguments.get(Queue.DESCRIPTION); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index fa5024c1fe..9d16f4b927 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -33,6 +33,7 @@ import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.configuration.startup.DefaultRecovererProvider; +import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.logging.CompositeStartupMessageLogger; import org.apache.qpid.server.logging.Log4jMessageLogger; import org.apache.qpid.server.logging.LogActor; @@ -113,7 +114,8 @@ public class ApplicationRegistry implements IApplicationRegistry _taskExecutor = new TaskExecutor(); _taskExecutor.start(); - RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, brokerOptions); + StoreConfigurationChangeListener storeChangeListener = new StoreConfigurationChangeListener(_store); + RecovererProvider provider = new DefaultRecovererProvider((StatisticsGatherer)this, _virtualHostRegistry, _logRecorder, _rootMessageLogger, _taskExecutor, brokerOptions, storeChangeListener); ConfiguredObjectRecoverer<? extends ConfiguredObject> brokerRecoverer = provider.getRecoverer(Broker.class.getSimpleName()); _broker = (Broker) brokerRecoverer.create(provider, _store.getRootEntry()); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java index 09e79d3ae9..ff45add206 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java @@ -20,7 +20,6 @@ package org.apache.qpid.server.security; import org.apache.log4j.Logger; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.model.AccessControlProvider; @@ -44,6 +43,7 @@ import static org.apache.qpid.server.security.access.ObjectType.METHOD; import static org.apache.qpid.server.security.access.ObjectType.QUEUE; import static org.apache.qpid.server.security.access.ObjectType.USER; import static org.apache.qpid.server.security.access.ObjectType.VIRTUALHOST; +import static org.apache.qpid.server.security.access.Operation.ACCESS_LOGS; import static org.apache.qpid.server.security.access.Operation.BIND; import static org.apache.qpid.server.security.access.Operation.CONFIGURE; import static org.apache.qpid.server.security.access.Operation.CONSUME; @@ -166,12 +166,12 @@ public class SecurityManager implements ConfigurationChangeListener { String pluginTypeName = getPluginTypeName(accessControl); _hostPlugins.put(pluginTypeName, accessControl); - + if(_logger.isDebugEnabled()) { _logger.debug("Added access control to host plugins with name: " + vhostName); } - + break; } } @@ -289,7 +289,7 @@ public class SecurityManager implements ConfigurationChangeListener return true; } - public boolean authoriseBind(final Exchange exch, final AMQQueue queue, final AMQShortString routingKey) + public boolean authoriseBind(final Exchange exch, final AMQQueue queue, final String routingKey) { return checkAllPlugins(new AccessCheck() { @@ -351,8 +351,8 @@ public class SecurityManager implements ConfigurationChangeListener }); } - public boolean authoriseCreateExchange(final Boolean autoDelete, final Boolean durable, final AMQShortString exchangeName, - final Boolean internal, final Boolean nowait, final Boolean passive, final AMQShortString exchangeType) + public boolean authoriseCreateExchange(final Boolean autoDelete, final Boolean durable, final String exchangeName, + final Boolean internal, final Boolean nowait, final Boolean passive, final String exchangeType) { return checkAllPlugins(new AccessCheck() { @@ -365,7 +365,7 @@ public class SecurityManager implements ConfigurationChangeListener } public boolean authoriseCreateQueue(final Boolean autoDelete, final Boolean durable, final Boolean exclusive, - final Boolean nowait, final Boolean passive, final AMQShortString queueName, final String owner) + final Boolean nowait, final Boolean passive, final String queueName, final String owner) { return checkAllPlugins(new AccessCheck() { @@ -491,7 +491,7 @@ public class SecurityManager implements ConfigurationChangeListener }); } - public boolean authoriseUnbind(final Exchange exch, final AMQShortString routingKey, final AMQQueue queue) + public boolean authoriseUnbind(final Exchange exch, final String routingKey, final AMQQueue queue) { return checkAllPlugins(new AccessCheck() { @@ -629,4 +629,15 @@ public class SecurityManager implements ConfigurationChangeListener }); } + public boolean authoriseLogsAccess() + { + return checkAllPlugins(new AccessCheck() + { + Result allowed(AccessControl plugin) + { + return plugin.authorise(ACCESS_LOGS, BROKER, ObjectProperties.EMPTY); + } + }); + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java index 6c631fc360..a379f85bbb 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java @@ -26,7 +26,6 @@ import java.util.Map; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.AMQQueue; @@ -136,12 +135,6 @@ public class ObjectProperties setName(name); } - - public ObjectProperties(AMQShortString name) - { - setName(name); - } - public ObjectProperties(AMQQueue queue) { setName(queue.getName()); @@ -164,7 +157,7 @@ public class ObjectProperties } } - public ObjectProperties(Exchange exch, AMQQueue queue, AMQShortString routingKey) + public ObjectProperties(Exchange exch, AMQQueue queue, String routingKey) { this(queue); @@ -174,11 +167,6 @@ public class ObjectProperties put(Property.ROUTING_KEY, routingKey); } - public ObjectProperties(Exchange exch, AMQShortString routingKey) - { - this(exch.getName(), routingKey.asString()); - } - public ObjectProperties(String exchangeName, String routingKey, Boolean immediate) { this(exchangeName, routingKey); @@ -195,8 +183,8 @@ public class ObjectProperties put(Property.ROUTING_KEY, routingKey); } - public ObjectProperties(Boolean autoDelete, Boolean durable, AMQShortString exchangeName, - Boolean internal, Boolean nowait, Boolean passive, AMQShortString exchangeType) + public ObjectProperties(Boolean autoDelete, Boolean durable, String exchangeName, + Boolean internal, Boolean nowait, Boolean passive, String exchangeType) { super(); @@ -212,7 +200,7 @@ public class ObjectProperties } public ObjectProperties(Boolean autoDelete, Boolean durable, Boolean exclusive, Boolean nowait, Boolean passive, - AMQShortString queueName, String owner) + String queueName, String owner) { super(); @@ -257,16 +245,6 @@ public class ObjectProperties _properties.put(Property.NAME, name); } - public void setName(AMQShortString name) - { - put(Property.NAME, name); - } - - public String put(Property key, AMQShortString value) - { - return put(key, value == null ? "" : value.asString()); - } - public String put(Property key, String value) { return _properties.put(key, value == null ? "" : value.trim()); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java index 048d9a8fc9..9016205d1c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectType.java @@ -19,6 +19,7 @@ package org.apache.qpid.server.security.access; import static org.apache.qpid.server.security.access.Operation.ACCESS; +import static org.apache.qpid.server.security.access.Operation.ACCESS_LOGS; import static org.apache.qpid.server.security.access.Operation.BIND; import static org.apache.qpid.server.security.access.Operation.CONFIGURE; import static org.apache.qpid.server.security.access.Operation.CONSUME; @@ -50,7 +51,7 @@ public enum ObjectType METHOD(Operation.ALL, ACCESS, UPDATE), USER(Operation.ALL, CREATE, DELETE, UPDATE), GROUP(Operation.ALL, CREATE, DELETE, UPDATE), - BROKER(Operation.ALL, CONFIGURE); + BROKER(Operation.ALL, CONFIGURE, ACCESS_LOGS); private EnumSet<Operation> _actions; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java index df5289b7bf..db5b8fba11 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/Operation.java @@ -33,7 +33,8 @@ public enum Operation DELETE, PURGE, UPDATE, - CONFIGURE; + CONFIGURE, + ACCESS_LOGS; public static Operation parse(String text) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java index eecc704011..a4c4fff42f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java @@ -7,9 +7,9 @@ * 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 @@ -61,13 +61,13 @@ public class AmqPlainSaslServer implements SaslServer try { final FieldTable ft = FieldTableFactory.newFieldTable(new DataInputStream(new ByteArrayInputStream(response)), response.length); - String username = (String) ft.getString("LOGIN"); + String username = ft.getString("LOGIN"); // we do not care about the prompt but it throws if null NameCallback nameCb = new NameCallback("prompt", username); // we do not care about the prompt but it throws if null PasswordCallback passwordCb = new PasswordCallback("prompt", false); // TODO: should not get pwd as a String but as a char array... - String pwd = (String) ft.getString("PASSWORD"); + String pwd = ft.getString("PASSWORD"); AuthorizeCallback authzCb = new AuthorizeCallback(username, username); Callback[] callbacks = new Callback[]{nameCb, passwordCb, authzCb}; _cbh.handle(callbacks); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java index 475f74180e..e1007d91e0 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java @@ -26,6 +26,7 @@ import javax.security.sasl.SaslServer; import org.apache.log4j.Logger; import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class ExternalSaslServer implements SaslServer { @@ -88,7 +89,6 @@ public class ExternalSaslServer implements SaslServer if (_externalPrincipal instanceof X500Principal && !_useFullDN) { // Construct username as <CN>@<DC1>.<DC2>.<DC3>....<DCN> - String username; String dn = ((X500Principal) _externalPrincipal).getName(X500Principal.RFC2253); @@ -97,62 +97,21 @@ public class ExternalSaslServer implements SaslServer LOGGER.debug("Parsing username from Principal DN: " + dn); } - if (dn.contains("CN=")) + username = SSLUtil.getIdFromSubjectDN(dn); + if (username.isEmpty()) { - username = dn.substring(dn.indexOf("CN=") + 3, (dn.indexOf(",", dn.indexOf("CN=")) != -1) ? dn.indexOf(",", dn.indexOf("CN=")) : dn.length()); - - if (username.isEmpty()) - { - // CN is empty => Cannot construct username => Authentication failed => return null - if(LOGGER.isDebugEnabled()) - { - LOGGER.debug("CN value was empty in Principal name, unable to construct username"); - } - return null; - } - else - { - if (dn.contains("DC=")) - { - int start = 0; - String dc = ""; - - while (dn.indexOf("DC=", start) != -1) - { - int dcStart = dn.indexOf("DC=", start) + 3; - int dcEnd = (dn.indexOf(",", dn.indexOf("DC=", start)) != -1) ? dn.indexOf(",", dn.indexOf("DC=", start)) : dn.length(); - - if (dc.isEmpty()) - { - dc = dn.substring(dcStart, dcEnd); - } - else - { - dc = dc.concat(".").concat(dn.substring(dcStart, dcEnd)); - } - - start = dn.indexOf("DC=", start) + 1; - } - - username = username.concat("@").concat(dc); - } - } - + // CN is empty => Cannot construct username => Authentication failed => return null if(LOGGER.isDebugEnabled()) { - LOGGER.debug("Constructing Principal with username: " + username); + LOGGER.debug("CN value was empty in Principal name, unable to construct username"); } - return new UsernamePrincipal(username); + return null; } - else + if(LOGGER.isDebugEnabled()) { - // No CN => Cannot construct username => Authentication failed => return null - if(LOGGER.isDebugEnabled()) - { - LOGGER.debug("No CN= present in DN, unable to construct username"); - } - return null; + LOGGER.debug("Constructing Principal with username: " + username); } + return new UsernamePrincipal(username); } else { @@ -160,8 +119,7 @@ public class ExternalSaslServer implements SaslServer { LOGGER.debug("Using external Principal: " + _externalPrincipal); } - return _externalPrincipal; } } -}
\ No newline at end of file +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java new file mode 100644 index 0000000000..dbe8bf22a0 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractDurableConfiguredObjectRecoverer.java @@ -0,0 +1,77 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +import java.util.Map; +import java.util.UUID; + +public abstract class AbstractDurableConfiguredObjectRecoverer<T> implements DurableConfiguredObjectRecoverer +{ + @Override + public void load(final DurableConfigurationRecoverer durableConfigurationRecoverer, + final UUID id, + final Map<String, Object> attributes) + { + final UnresolvedObject obj = createUnresolvedObject(id, getType(), attributes); + UnresolvedDependency[] dependencies = obj.getUnresolvedDependencies(); + for(final UnresolvedDependency dependency : dependencies) + { + Object dep; + if((dep = durableConfigurationRecoverer.getResolvedObject(dependency.getType(), dependency.getId())) != null) + { + dependency.resolve(dep); + } + else + { + durableConfigurationRecoverer.addResolutionListener(dependency.getType(), dependency.getId(), + new DependencyListener() + { + + @Override + public void dependencyResolved(final String depType, + final UUID depId, + final Object o) + { + dependency.resolve(o); + if(obj.getUnresolvedDependencies().length == 0) + { + durableConfigurationRecoverer.resolve(getType(), id, obj.resolve()); + } + } + }); + } + } + if(obj.getUnresolvedDependencies().length == 0) + { + durableConfigurationRecoverer.resolve(getType(), id, obj.resolve()); + } + else + { + durableConfigurationRecoverer.addUnresolvedObject(getType(), id, obj); + } + + } + + public abstract UnresolvedObject<T> createUnresolvedObject(final UUID id, + final String type, + final Map<String, Object> attributes); + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java index fdb36c9013..4a1452d86c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java @@ -35,6 +35,8 @@ import java.sql.SQLException; import java.sql.Statement; import java.sql.Types; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.UUID; @@ -45,6 +47,7 @@ import org.apache.qpid.AMQException; import org.apache.qpid.AMQStoreException; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.plugin.MessageMetaDataType; import org.apache.qpid.server.queue.AMQQueue; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonParseException; @@ -54,6 +57,7 @@ import org.codehaus.jackson.map.ObjectMapper; abstract public class AbstractJDBCMessageStore implements MessageStore, DurableConfigurationStore { private static final String DB_VERSION_TABLE_NAME = "QPID_DB_VERSION"; + private static final String CONFIGURATION_VERSION_TABLE_NAME = "QPID_CONFIG_VERSION"; private static final String QUEUE_ENTRY_TABLE_NAME = "QPID_QUEUE_ENTRIES"; @@ -67,17 +71,27 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC private static final String XID_ACTIONS_TABLE_NAME = "QPID_XID_ACTIONS"; private static final String CONFIGURED_OBJECTS_TABLE_NAME = "QPID_CONFIGURED_OBJECTS"; + private static final int DEFAULT_CONFIG_VERSION = 0; public static String[] ALL_TABLES = new String[] { DB_VERSION_TABLE_NAME, LINKS_TABLE_NAME, BRIDGES_TABLE_NAME, XID_ACTIONS_TABLE_NAME, - XID_TABLE_NAME, QUEUE_ENTRY_TABLE_NAME, MESSAGE_CONTENT_TABLE_NAME, META_DATA_TABLE_NAME, CONFIGURED_OBJECTS_TABLE_NAME }; + XID_TABLE_NAME, QUEUE_ENTRY_TABLE_NAME, MESSAGE_CONTENT_TABLE_NAME, META_DATA_TABLE_NAME, CONFIGURED_OBJECTS_TABLE_NAME, CONFIGURATION_VERSION_TABLE_NAME }; - private static final int DB_VERSION = 6; + private static final int DB_VERSION = 7; private final AtomicLong _messageId = new AtomicLong(0); private AtomicBoolean _closed = new AtomicBoolean(false); private static final String CREATE_DB_VERSION_TABLE = "CREATE TABLE "+ DB_VERSION_TABLE_NAME + " ( version int not null )"; private static final String INSERT_INTO_DB_VERSION = "INSERT INTO "+ DB_VERSION_TABLE_NAME + " ( version ) VALUES ( ? )"; + private static final String SELECT_FROM_DB_VERSION = "SELECT version FROM " + DB_VERSION_TABLE_NAME; + private static final String UPDATE_DB_VERSION = "UPDATE " + DB_VERSION_TABLE_NAME + " SET version = ?"; + + + private static final String CREATE_CONFIG_VERSION_TABLE = "CREATE TABLE "+ CONFIGURATION_VERSION_TABLE_NAME + " ( version int not null )"; + private static final String INSERT_INTO_CONFIG_VERSION = "INSERT INTO "+ CONFIGURATION_VERSION_TABLE_NAME + " ( version ) VALUES ( ? )"; + private static final String SELECT_FROM_CONFIG_VERSION = "SELECT version FROM " + CONFIGURATION_VERSION_TABLE_NAME; + private static final String UPDATE_CONFIG_VERSION = "UPDATE " + CONFIGURATION_VERSION_TABLE_NAME + " SET version = ?"; + private static final String INSERT_INTO_QUEUE_ENTRY = "INSERT INTO " + QUEUE_ENTRY_TABLE_NAME + " (queue_id, message_id) values (?,?)"; private static final String DELETE_FROM_QUEUE_ENTRY = "DELETE FROM " + QUEUE_ENTRY_TABLE_NAME + " WHERE queue_id = ? AND message_id =?"; @@ -155,6 +169,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC private MessageStoreRecoveryHandler _messageRecoveryHandler; private TransactionLogRecoveryHandler _tlogRecoveryHandler; private ConfigurationRecoveryHandler _configRecoveryHandler; + private VirtualHost _virtualHost; public AbstractJDBCMessageStore() { @@ -162,48 +177,143 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC } @Override - public void configureConfigStore(String name, - ConfigurationRecoveryHandler configRecoveryHandler, - VirtualHost virtualHost) throws Exception + public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler configRecoveryHandler) throws Exception { _stateManager.attainState(State.INITIALISING); _configRecoveryHandler = configRecoveryHandler; - - commonConfiguration(name, virtualHost); + _virtualHost = virtualHost; } @Override - public void configureMessageStore(String name, - MessageStoreRecoveryHandler recoveryHandler, + public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler recoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) throws Exception { + if(_stateManager.isInState(State.INITIAL)) + { + _stateManager.attainState(State.INITIALISING); + } + + _virtualHost = virtualHost; _tlogRecoveryHandler = tlogRecoveryHandler; _messageRecoveryHandler = recoveryHandler; + completeInitialisation(); + } + + private void completeInitialisation() throws ClassNotFoundException, SQLException, AMQStoreException + { + commonConfiguration(); + _stateManager.attainState(State.INITIALISED); } @Override public void activate() throws Exception { + if(_stateManager.isInState(State.INITIALISING)) + { + completeInitialisation(); + } _stateManager.attainState(State.ACTIVATING); // this recovers durable exchanges, queues, and bindings - recoverConfiguration(_configRecoveryHandler); - recoverMessages(_messageRecoveryHandler); - TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = recoverQueueEntries(_tlogRecoveryHandler); - recoverXids(dtxrh); + if(_configRecoveryHandler != null) + { + recoverConfiguration(_configRecoveryHandler); + } + if(_messageRecoveryHandler != null) + { + recoverMessages(_messageRecoveryHandler); + } + if(_tlogRecoveryHandler != null) + { + TransactionLogRecoveryHandler.DtxRecordRecoveryHandler dtxrh = recoverQueueEntries(_tlogRecoveryHandler); + recoverXids(dtxrh); + + } _stateManager.attainState(State.ACTIVE); } - private void commonConfiguration(String name, VirtualHost virtualHost) - throws ClassNotFoundException, SQLException + private void commonConfiguration() + throws ClassNotFoundException, SQLException, AMQStoreException { - implementationSpecificConfiguration(name, virtualHost); + implementationSpecificConfiguration(_virtualHost.getName(), _virtualHost); createOrOpenDatabase(); + upgradeIfNecessary(); + } + protected void upgradeIfNecessary() throws SQLException, AMQStoreException + { + Connection conn = newAutoCommitConnection(); + try + { + + PreparedStatement statement = conn.prepareStatement(SELECT_FROM_DB_VERSION); + try + { + ResultSet rs = statement.executeQuery(); + try + { + if(!rs.next()) + { + throw new AMQStoreException(DB_VERSION_TABLE_NAME + " does not contain the database version"); + } + int version = rs.getInt(1); + switch (version) + { + case 6: + upgradeFromV6(); + case DB_VERSION: + return; + default: + throw new AMQStoreException("Unknown database version: " + version); + } + } + finally + { + rs.close(); + } + } + finally + { + statement.close(); + } + } + finally + { + conn.close(); + } + + } + + private void upgradeFromV6() throws SQLException + { + updateDbVersion(7); + } + + private void updateDbVersion(int newVersion) throws SQLException + { + Connection conn = newAutoCommitConnection(); + try + { + + PreparedStatement statement = conn.prepareStatement(UPDATE_DB_VERSION); + try + { + statement.setInt(1,newVersion); + statement.execute(); + } + finally + { + statement.close(); + } + } + finally + { + conn.close(); + } } protected abstract void implementationSpecificConfiguration(String name, @@ -222,6 +332,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC Connection conn = newAutoCommitConnection(); createVersionTable(conn); + createConfigVersionTable(conn); createConfiguredObjectsTable(conn); createQueueEntryTable(conn); createMetaDataTable(conn); @@ -258,7 +369,33 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC pstmt.close(); } } + } + private void createConfigVersionTable(final Connection conn) throws SQLException + { + if(!tableExists(CONFIGURATION_VERSION_TABLE_NAME, conn)) + { + Statement stmt = conn.createStatement(); + try + { + stmt.execute(CREATE_CONFIG_VERSION_TABLE); + } + finally + { + stmt.close(); + } + + PreparedStatement pstmt = conn.prepareStatement(INSERT_INTO_CONFIG_VERSION); + try + { + pstmt.setInt(1, DEFAULT_CONFIG_VERSION); + pstmt.execute(); + } + finally + { + pstmt.close(); + } + } } private void createConfiguredObjectsTable(final Connection conn) throws SQLException @@ -278,6 +415,8 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC } } + + private void createQueueEntryTable(final Connection conn) throws SQLException { if(!tableExists(QUEUE_ENTRY_TABLE_NAME, conn)) @@ -456,10 +595,10 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC { try { - recoveryHandler.beginConfigurationRecovery(this); + recoveryHandler.beginConfigurationRecovery(this, getConfigVersion()); loadConfiguredObjects(recoveryHandler); - recoveryHandler.completeConfigurationRecovery(); + setConfigVersion(recoveryHandler.completeConfigurationRecovery()); } catch (SQLException e) { @@ -467,6 +606,67 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC } } + private void setConfigVersion(int version) throws SQLException + { + Connection conn = newAutoCommitConnection(); + try + { + + PreparedStatement stmt = conn.prepareStatement(UPDATE_CONFIG_VERSION); + try + { + stmt.setInt(1, version); + stmt.execute(); + + } + finally + { + stmt.close(); + } + } + finally + { + conn.close(); + } + } + + private int getConfigVersion() throws SQLException + { + Connection conn = newAutoCommitConnection(); + try + { + + Statement stmt = conn.createStatement(); + try + { + ResultSet rs = stmt.executeQuery(SELECT_FROM_CONFIG_VERSION); + try + { + + if(rs.next()) + { + return rs.getInt(1); + } + return DEFAULT_CONFIG_VERSION; + } + finally + { + rs.close(); + } + + } + finally + { + stmt.close(); + } + } + finally + { + conn.close(); + } + + } + @Override public void close() throws Exception { @@ -895,6 +1095,11 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC } + protected boolean isConfigStoreOnly() + { + return _messageRecoveryHandler == null; + } + private static final class ConnectionWrapper { private final Connection _connection; @@ -1055,8 +1260,8 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC ByteBuffer buf = ByteBuffer.wrap(dataAsBytes); buf.position(1); buf = buf.slice(); - MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]]; - StorableMessageMetaData metaData = type.getFactory().createMetaData(buf); + MessageMetaDataType type = MessageMetaDataTypeRegistry.fromOrdinal(dataAsBytes[0]); + StorableMessageMetaData metaData = type.createMetaData(buf); StoredJDBCMessage message = new StoredJDBCMessage(messageId, metaData, true); messageHandler.message(message); } @@ -1307,8 +1512,8 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC ByteBuffer buf = ByteBuffer.wrap(dataAsBytes); buf.position(1); buf = buf.slice(); - MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]]; - StorableMessageMetaData metaData = type.getFactory().createMetaData(buf); + MessageMetaDataType type = MessageMetaDataTypeRegistry.fromOrdinal(dataAsBytes[0]); + StorableMessageMetaData metaData = type.createMetaData(buf); return metaData; } @@ -1804,15 +2009,35 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC Connection conn = newAutoCommitConnection(); try { - PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_CONFIGURED_OBJECTS); - try - { - stmt.setString(1, id.toString()); - results = stmt.executeUpdate(); - } - finally + results = removeConfiguredObject(id, conn); + } + finally + { + conn.close(); + } + } + catch (SQLException e) + { + throw new AMQStoreException("Error deleting of configured object with id " + id + " from database: " + e.getMessage(), e); + } + return results; + } + + public UUID[] removeConfiguredObjects(UUID... objects) throws AMQStoreException + { + Collection<UUID> removed = new ArrayList<UUID>(objects.length); + try + { + + Connection conn = newAutoCommitConnection(); + try + { + for(UUID id : objects) { - stmt.close(); + if(removeConfiguredObject(id, conn) != 0) + { + removed.add(id); + } } } finally @@ -1822,7 +2047,22 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC } catch (SQLException e) { - throw new AMQStoreException("Error deleting of configured object with id " + id + " from database: " + e.getMessage(), e); + throw new AMQStoreException("Error deleting of configured objects " + Arrays.asList(objects) + " from database: " + e.getMessage(), e); + } + return removed.toArray(new UUID[removed.size()]); + } + + private int removeConfiguredObject(final UUID id, final Connection conn) throws SQLException + { + final int results;PreparedStatement stmt = conn.prepareStatement(DELETE_FROM_CONFIGURED_OBJECTS); + try + { + stmt.setString(1, id.toString()); + results = stmt.executeUpdate(); + } + finally + { + stmt.close(); } return results; } @@ -1836,52 +2076,121 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC Connection conn = newAutoCommitConnection(); try { - PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT); - try + updateConfiguredObject(configuredObject, false, conn); + } + finally + { + conn.close(); + } + } + catch (SQLException e) + { + throw new AMQStoreException("Error updating configured object " + configuredObject + " in database: " + e.getMessage(), e); + } + } + } + + @Override + public void update(ConfiguredObjectRecord... records) throws AMQStoreException + { + update(false, records); + } + + public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws AMQStoreException + { + if (_stateManager.isInState(State.ACTIVE) || _stateManager.isInState(State.ACTIVATING)) + { + try + { + Connection conn = newConnection(); + try + { + for(ConfiguredObjectRecord record : records) { - stmt.setString(1, configuredObject.getId().toString()); - ResultSet rs = stmt.executeQuery(); + updateConfiguredObject(record, createIfNecessary, conn); + } + conn.commit(); + } + finally + { + conn.close(); + } + } + catch (SQLException e) + { + throw new AMQStoreException("Error updating configured objects in database: " + e.getMessage(), e); + } + + } + + } + + private void updateConfiguredObject(ConfiguredObjectRecord configuredObject, + boolean createIfNecessary, + Connection conn) + throws SQLException, AMQStoreException + { + PreparedStatement stmt = conn.prepareStatement(FIND_CONFIGURED_OBJECT); + try + { + stmt.setString(1, configuredObject.getId().toString()); + ResultSet rs = stmt.executeQuery(); + try + { + if (rs.next()) + { + PreparedStatement stmt2 = conn.prepareStatement(UPDATE_CONFIGURED_OBJECTS); try { - if (rs.next()) + stmt2.setString(1, configuredObject.getType()); + if (configuredObject.getAttributes() != null) { - PreparedStatement stmt2 = conn.prepareStatement(UPDATE_CONFIGURED_OBJECTS); - try - { - stmt2.setString(1, configuredObject.getType()); - if (configuredObject.getAttributes() != null) - { - byte[] attributesAsBytes = (new ObjectMapper()).writeValueAsBytes( - configuredObject.getAttributes()); - ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes); - stmt2.setBinaryStream(2, bis, attributesAsBytes.length); - } - else - { - stmt2.setNull(2, Types.BLOB); - } - stmt2.setString(3, configuredObject.getId().toString()); - stmt2.execute(); - } - finally - { - stmt2.close(); - } + byte[] attributesAsBytes = (new ObjectMapper()).writeValueAsBytes( + configuredObject.getAttributes()); + ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes); + stmt2.setBinaryStream(2, bis, attributesAsBytes.length); + } + else + { + stmt2.setNull(2, Types.BLOB); } + stmt2.setString(3, configuredObject.getId().toString()); + stmt2.execute(); } finally { - rs.close(); + stmt2.close(); } } - finally + else if(createIfNecessary) { - stmt.close(); + PreparedStatement insertStmt = conn.prepareStatement(INSERT_INTO_CONFIGURED_OBJECTS); + try + { + insertStmt.setString(1, configuredObject.getId().toString()); + insertStmt.setString(2, configuredObject.getType()); + if(configuredObject.getAttributes() == null) + { + insertStmt.setNull(3, Types.BLOB); + } + else + { + final Map<String, Object> attributes = configuredObject.getAttributes(); + byte[] attributesAsBytes = new ObjectMapper().writeValueAsBytes(attributes); + ByteArrayInputStream bis = new ByteArrayInputStream(attributesAsBytes); + insertStmt.setBinaryStream(3, bis, attributesAsBytes.length); + } + insertStmt.execute(); + } + finally + { + insertStmt.close(); + } } } finally { - conn.close(); + rs.close(); } } catch (JsonMappingException e) @@ -1896,11 +2205,11 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC { throw new AMQStoreException("Error updating configured object " + configuredObject + " in database: " + e.getMessage(), e); } - catch (SQLException e) + finally { - throw new AMQStoreException("Error updating configured object " + configuredObject + " in database: " + e.getMessage(), e); + stmt.close(); } - } + } private ConfiguredObjectRecord loadConfiguredObject(final UUID id) throws AMQStoreException diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java index b7372828e1..3abf083026 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/AbstractMemoryMessageStore.java @@ -20,19 +20,15 @@ */ package org.apache.qpid.server.store; -import java.util.Map; -import java.util.UUID; -import org.apache.qpid.AMQStoreException; -import org.apache.qpid.server.message.EnqueableMessage; - import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.model.VirtualHost; /** A simple message store that stores the messages in a thread-safe structure in memory. */ -public class MemoryMessageStore extends NullMessageStore +abstract public class AbstractMemoryMessageStore extends NullMessageStore { - public static final String TYPE = "Memory"; private final AtomicLong _messageId = new AtomicLong(1); private final AtomicBoolean _closed = new AtomicBoolean(false); @@ -78,30 +74,36 @@ public class MemoryMessageStore extends NullMessageStore private final StateManager _stateManager; private final EventManager _eventManager = new EventManager(); - public MemoryMessageStore() + public AbstractMemoryMessageStore() { _stateManager = new StateManager(_eventManager); } @Override - public void configureConfigStore(String name, - ConfigurationRecoveryHandler recoveryHandler, - VirtualHost virtualHost) throws Exception + public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) throws Exception { _stateManager.attainState(State.INITIALISING); } @Override - public void configureMessageStore(String name, - MessageStoreRecoveryHandler recoveryHandler, + public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler recoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) throws Exception { + if(_stateManager.isInState(State.INITIAL)) + { + _stateManager.attainState(State.INITIALISING); + } _stateManager.attainState(State.INITIALISED); } @Override public void activate() throws Exception { + + if(_stateManager.isInState(State.INITIALISING)) + { + _stateManager.attainState(State.INITIALISED); + } _stateManager.attainState(State.ACTIVATING); _stateManager.attainState(State.ACTIVE); @@ -142,9 +144,4 @@ public class MemoryMessageStore extends NullMessageStore _eventManager.addEventListener(eventListener, events); } - @Override - public String getStoreType() - { - return TYPE; - } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java index 2a4aed5373..a3534d3fa5 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java @@ -28,10 +28,14 @@ import java.util.UUID; public interface ConfigurationRecoveryHandler { - void beginConfigurationRecovery(DurableConfigurationStore store); + void beginConfigurationRecovery(DurableConfigurationStore store, int configVersion); void configuredObject(UUID id, String type, Map<String, Object> attributes); - void completeConfigurationRecovery(); + /** + * + * @return the model version of the configuration + */ + int completeConfigurationRecovery(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java index 5c8f452dc7..44490385d9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecord.java @@ -60,4 +60,29 @@ public class ConfiguredObjectRecord return "ConfiguredObjectRecord [id=" + _id + ", type=" + _type + ", attributes=" + _attributes + "]"; } + @Override + public boolean equals(Object o) + { + if(this == o) + { + return true; + } + if(o == null || getClass() != o.getClass()) + { + return false; + } + + ConfiguredObjectRecord that = (ConfiguredObjectRecord) o; + + return _type.equals(that._type) && _id.equals(that._id) && _attributes.equals(that._attributes); + } + + @Override + public int hashCode() + { + int result = _id.hashCode(); + result = 31 * result + _type.hashCode(); + result = 31 * result + _attributes.hashCode(); + return result; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DependencyListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DependencyListener.java new file mode 100644 index 0000000000..120c904cf7 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DependencyListener.java @@ -0,0 +1,28 @@ +/* + * + * 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; + +interface DependencyListener +{ + void dependencyResolved(String type, UUID id, Object o); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java new file mode 100644 index 0000000000..7fb80bde96 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationRecoverer.java @@ -0,0 +1,242 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +import java.util.ArrayList; +import java.util.Collection; +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.AMQStoreException; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.ConfigStoreMessages; +import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; + +import static org.apache.qpid.server.model.VirtualHost.CURRENT_CONFIG_VERSION; + +public class DurableConfigurationRecoverer implements ConfigurationRecoveryHandler +{ + private static final Logger _logger = Logger.getLogger(DurableConfigurationRecoverer.class); + + private final Map<String, Map<UUID, Object>> _resolvedObjects = new HashMap<String, Map<UUID, Object>>(); + + private final Map<String, Map<UUID, UnresolvedObject>> _unresolvedObjects = + new HashMap<String, Map<UUID, UnresolvedObject>>(); + + private final Map<String, Map<UUID, List<DependencyListener>>> _dependencyListeners = + new HashMap<String, Map<UUID, List<DependencyListener>>>(); + private final Map<String, DurableConfiguredObjectRecoverer> _recoverers; + private final UpgraderProvider _upgraderProvider; + + private DurableConfigurationStoreUpgrader _upgrader; + + private DurableConfigurationStore _store; + private final String _name; + + private MessageStoreLogSubject _logSubject; + + public DurableConfigurationRecoverer(final String name, + Map<String, DurableConfiguredObjectRecoverer> recoverers, + UpgraderProvider upgraderProvider) + { + _recoverers = recoverers; + _name = name; + _upgraderProvider = upgraderProvider; + } + + @Override + public void beginConfigurationRecovery(final DurableConfigurationStore store, final int configVersion) + { + _logSubject = new MessageStoreLogSubject(_name, store.getClass().getSimpleName()); + + _store = store; + _upgrader = _upgraderProvider.getUpgrader(configVersion, this); + } + + @Override + public void configuredObject(final UUID id, final String type, final Map<String, Object> attributes) + { + _upgrader.configuredObject(id, type, attributes); + } + + void onConfiguredObject(final UUID id, final String type, final Map<String, Object> attributes) + { + DurableConfiguredObjectRecoverer recoverer = getRecoverer(type); + if(recoverer == null) + { + throw new IllegalConfigurationException("Unkown type for configured object: " + type); + } + recoverer.load(this, id, attributes); + } + + private DurableConfiguredObjectRecoverer getRecoverer(final String type) + { + DurableConfiguredObjectRecoverer recoverer = _recoverers.get(type); + return recoverer; + } + + @Override + public int completeConfigurationRecovery() + { + _upgrader.complete(); + checkUnresolvedDependencies(); + applyUpgrade(); + + CurrentActor.get().message(_logSubject, ConfigStoreMessages.RECOVERY_COMPLETE()); + return CURRENT_CONFIG_VERSION; + } + + private void applyUpgrade() + { + + final Collection<ConfiguredObjectRecord> updates = new ArrayList<ConfiguredObjectRecord>(); + final Collection<UUID> deletes = new ArrayList<UUID>(); + for(Map.Entry<UUID,ConfiguredObjectRecord> entry : _upgrader.getUpdatedRecords().entrySet()) + { + if(entry.getValue() != null) + { + updates.add(entry.getValue()); + } + else + { + deletes.add(entry.getKey()); + } + } + + try + { + if(!updates.isEmpty()) + { + _store.update(true,updates.toArray(new ConfiguredObjectRecord[updates.size()])); + } + if(!deletes.isEmpty()) + { + _store.removeConfiguredObjects(deletes.toArray(new UUID[deletes.size()])); + } + } + catch (AMQStoreException e) + { + // TODO better exception + throw new RuntimeException("Unable to update config store when upgrading"); + } + + } + + 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 DependencyListener dependencyListener) + { + 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); + + } + + Object getResolvedObject(final String type, final UUID id) + { + Map<UUID, Object> objects = _resolvedObjects.get(type); + return objects == null ? null : objects.get(id); + } + + void resolve(final String type, final UUID id, final Object object) + { + Map<UUID, Object> typeObjects = _resolvedObjects.get(type); + if(typeObjects == null) + { + typeObjects = new HashMap<UUID, Object>(); + _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); + } + } + } + } + + 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/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java index fdde21ba89..6b0748b0c3 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStore.java @@ -45,15 +45,13 @@ public interface DurableConfigurationStore * * * - * @param name The name to be used by this store - * @param recoveryHandler Handler to be called as the store recovers on start up + * + * * @param virtualHost + * @param recoveryHandler Handler to be called as the store recovers on start up * @throws Exception If any error occurs that means the store is unable to configure itself. */ - void configureConfigStore(String name, - ConfigurationRecoveryHandler recoveryHandler, - VirtualHost virtualHost) throws Exception; - + void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) throws Exception; /** @@ -77,6 +75,8 @@ public interface DurableConfigurationStore */ void remove(UUID id, String type) throws AMQStoreException; + public UUID[] removeConfiguredObjects(UUID... objects) throws AMQStoreException; + /** * Updates the specified object in the persistent store, IF it is already present. If the object @@ -91,4 +91,9 @@ public interface DurableConfigurationStore void update(UUID id, String type, Map<String, Object> attributes) throws AMQStoreException; + public void update(ConfiguredObjectRecord... records) throws AMQStoreException; + public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws AMQStoreException; + + + void close() throws Exception; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreCreator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreCreator.java new file mode 100644 index 0000000000..3a69f802f0 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreCreator.java @@ -0,0 +1,78 @@ +/* + * + * 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.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class DurableConfigurationStoreCreator +{ + private Map<String, DurableConfigurationStoreFactory> _factories = new HashMap<String, DurableConfigurationStoreFactory>(); + + public DurableConfigurationStoreCreator() + { + QpidServiceLoader<DurableConfigurationStoreFactory> qpidServiceLoader = new QpidServiceLoader<DurableConfigurationStoreFactory>(); + Iterable<DurableConfigurationStoreFactory> factories = qpidServiceLoader.atLeastOneInstanceOf(DurableConfigurationStoreFactory.class); + for (DurableConfigurationStoreFactory durableConfigurationStoreFactory : factories) + { + String type = durableConfigurationStoreFactory.getType(); + DurableConfigurationStoreFactory factory = _factories.put(type.toLowerCase(), durableConfigurationStoreFactory); + if (factory != null) + { + throw new IllegalStateException("DurableConfigurationStoreFactory with type name '" + type + + "' is already registered using class '" + factory.getClass().getName() + "', can not register class '" + + durableConfigurationStoreFactory.getClass().getName() + "'"); + } + } + } + + public boolean isValidType(String storeType) + { + return _factories.containsKey(storeType.toLowerCase()); + } + + + public DurableConfigurationStore createMessageStore(String storeType) + { + DurableConfigurationStoreFactory factory = _factories.get(storeType.toLowerCase()); + if (factory == null) + { + throw new IllegalConfigurationException("Unknown store type: " + storeType + + ". Supported types: " + _factories.keySet()); + } + return factory.createDurableConfigurationStore(); + } + + public Collection<DurableConfigurationStoreFactory> getFactories() + { + return Collections.unmodifiableCollection(_factories.values()); + } + + public Collection<String> getStoreTypes() + { + return Collections.unmodifiableCollection(_factories.keySet()); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java index 9fab29fea6..d311685375 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java @@ -20,10 +20,14 @@ */ package org.apache.qpid.server.store; +import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; import org.apache.qpid.AMQStoreException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; @@ -32,60 +36,69 @@ import org.apache.qpid.server.model.Exchange; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueArgumentsConverter; public class DurableConfigurationStoreHelper { + private static final String BINDING = Binding.class.getSimpleName(); + private static final String EXCHANGE = Exchange.class.getSimpleName(); + private static final String QUEUE = Queue.class.getSimpleName(); + private static final Set<String> QUEUE_ARGUMENTS_EXCLUDES = new HashSet<String>(Arrays.asList(Queue.NAME, + Queue.OWNER, + Queue.EXCLUSIVE, + Queue.ALTERNATE_EXCHANGE)); + public static void updateQueue(DurableConfigurationStore store, AMQQueue queue) throws AMQStoreException { Map<String, Object> attributesMap = new LinkedHashMap<String, Object>(); attributesMap.put(Queue.NAME, queue.getName()); - attributesMap.put(Queue.OWNER, AMQShortString.toString(queue.getOwner())); + attributesMap.put(Queue.OWNER, queue.getOwner()); attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive()); + if (queue.getAlternateExchange() != null) { attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId()); } - else - { - attributesMap.remove(Queue.ALTERNATE_EXCHANGE); - } - if (attributesMap.containsKey(Queue.ARGUMENTS)) - { - // We wouldn't need this if createQueueConfiguredObject took only AMQQueue - Map<String, Object> currentArgs = (Map<String, Object>) attributesMap.get(Queue.ARGUMENTS); - currentArgs.putAll(queue.getArguments()); - } - else + + Collection<String> availableAttrs = queue.getAvailableAttributes(); + + for(String attrName : availableAttrs) { - attributesMap.put(Queue.ARGUMENTS, queue.getArguments()); + if(!QUEUE_ARGUMENTS_EXCLUDES.contains(attrName)) + { + attributesMap.put(attrName, queue.getAttribute(attrName)); + } } - store.update(queue.getId(), Queue.class.getName(), attributesMap); + + store.update(queue.getId(), QUEUE, attributesMap); } - public static void createQueue(DurableConfigurationStore store, AMQQueue queue, FieldTable arguments) + public static void createQueue(DurableConfigurationStore store, AMQQueue queue) throws AMQStoreException { Map<String, Object> attributesMap = new HashMap<String, Object>(); attributesMap.put(Queue.NAME, queue.getName()); - attributesMap.put(Queue.OWNER, AMQShortString.toString(queue.getOwner())); + attributesMap.put(Queue.OWNER, queue.getOwner()); attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive()); if (queue.getAlternateExchange() != null) { attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId()); } - // TODO KW i think the arguments could come from the queue itself removing the need for the parameter arguments. - // It would also do away with the need for the if/then/else within updateQueueConfiguredObject - if (arguments != null) + + for(String attrName : queue.getAvailableAttributes()) { - attributesMap.put(Queue.ARGUMENTS, FieldTable.convertToMap(arguments)); + if(!QUEUE_ARGUMENTS_EXCLUDES.contains(attrName)) + { + attributesMap.put(attrName, queue.getAttribute(attrName)); + } } - store.create(queue.getId(),Queue.class.getName(),attributesMap); + store.create(queue.getId(), QUEUE,attributesMap); } public static void removeQueue(DurableConfigurationStore store, AMQQueue queue) throws AMQStoreException { - store.remove(queue.getId(), Queue.class.getName()); + store.remove(queue.getId(), QUEUE); } public static void createExchange(DurableConfigurationStore store, org.apache.qpid.server.exchange.Exchange exchange) @@ -93,10 +106,10 @@ public class DurableConfigurationStoreHelper { Map<String, Object> attributesMap = new HashMap<String, Object>(); attributesMap.put(Exchange.NAME, exchange.getName()); - attributesMap.put(Exchange.TYPE, AMQShortString.toString(exchange.getTypeShortString())); + attributesMap.put(Exchange.TYPE, exchange.getTypeName()); attributesMap.put(Exchange.LIFETIME_POLICY, exchange.isAutoDelete() ? LifetimePolicy.AUTO_DELETE.name() : LifetimePolicy.PERMANENT.name()); - store.create(exchange.getId(), Exchange.class.getName(), attributesMap); + store.create(exchange.getId(), EXCHANGE, attributesMap); } @@ -104,7 +117,7 @@ public class DurableConfigurationStoreHelper public static void removeExchange(DurableConfigurationStore store, org.apache.qpid.server.exchange.Exchange exchange) throws AMQStoreException { - store.remove(exchange.getId(),Exchange.class.getName()); + store.remove(exchange.getId(), EXCHANGE); } public static void createBinding(DurableConfigurationStore store, org.apache.qpid.server.binding.Binding binding) @@ -119,14 +132,14 @@ public class DurableConfigurationStoreHelper { attributesMap.put(Binding.ARGUMENTS, arguments); } - store.create(binding.getId(), Binding.class.getName(), attributesMap); + store.create(binding.getId(), BINDING, attributesMap); } public static void removeBinding(DurableConfigurationStore store, org.apache.qpid.server.binding.Binding binding) throws AMQStoreException { - store.remove(binding.getId(), Binding.class.getName()); + store.remove(binding.getId(), BINDING); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreUpgrader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreUpgrader.java new file mode 100644 index 0000000000..1d3e4cc672 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreUpgrader.java @@ -0,0 +1,35 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +import java.util.Map; +import java.util.UUID; + +public interface DurableConfigurationStoreUpgrader +{ + void configuredObject(UUID id, String type, Map<String, Object> attributes); + + void complete(); + + void setNextUpgrader(DurableConfigurationStoreUpgrader upgrader); + + Map<UUID, ConfiguredObjectRecord> getUpdatedRecords(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java new file mode 100644 index 0000000000..e065728bd3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/DurableConfiguredObjectRecoverer.java @@ -0,0 +1,33 @@ +/* + * + * 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 java.util.UUID; + +public interface DurableConfiguredObjectRecoverer +{ + public void load(final DurableConfigurationRecoverer durableConfigurationRecoverer, + final UUID id, + final Map<String, Object> attributes); + + public String getType(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java new file mode 100644 index 0000000000..8eed1fa5a4 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java @@ -0,0 +1,513 @@ +/* + * + * 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.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.channels.FileLock; +import java.nio.channels.OverlappingFileLockException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Model; +import org.apache.qpid.server.model.VirtualHost; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; + +public class JsonFileConfigStore implements DurableConfigurationStore +{ + private static final Model MODEL = Model.getInstance(); + + private static final Map<String,Class<? extends ConfiguredObject>> CLASS_NAME_MAPPING = generateClassNameMap(VirtualHost.class); + 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 String _directoryName; + private String _name; + private FileLock _fileLock; + private String _configFileName; + private String _backupFileName; + private int _configVersion; + + public JsonFileConfigStore() + { + _objectMapper.enable(SerializationConfig.Feature.INDENT_OUTPUT); + } + + @Override + public void configureConfigStore(final VirtualHost virtualHost, final ConfigurationRecoveryHandler recoveryHandler) + throws Exception + { + _name = virtualHost.getName(); + + Object storePathAttr = virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH); + if(!(storePathAttr instanceof String)) + { + throw new AMQStoreException("Cannot determine path for configuration storage"); + } + _directoryName = (String) storePathAttr; + _configFileName = _name + ".json"; + _backupFileName = _name + ".bak"; + checkDirectoryIsWritable(_directoryName); + getFileLock(); + + if(!fileExists(_configFileName)) + { + if(!fileExists(_backupFileName)) + { + File newFile = new File(_directoryName, _configFileName); + _objectMapper.writeValue(newFile, Collections.emptyMap()); + } + else + { + renameFile(_backupFileName, _configFileName); + } + } + + + load(); + recoveryHandler.beginConfigurationRecovery(this,_configVersion); + List<ConfiguredObjectRecord> records = new ArrayList<ConfiguredObjectRecord>(_objectsById.values()); + for(ConfiguredObjectRecord record : records) + { + recoveryHandler.configuredObject(record.getId(), record.getType(), record.getAttributes()); + } + int oldConfigVersion = _configVersion; + _configVersion = recoveryHandler.completeConfigurationRecovery(); + if(oldConfigVersion != _configVersion) + { + save(); + } + } + + private void renameFile(String fromFileName, String toFileName) throws AMQStoreException + { + File toFile = new File(_directoryName, toFileName); + if(toFile.exists()) + { + if(!toFile.delete()) + { + throw new AMQStoreException("Cannot delete file " + toFile.getAbsolutePath()); + } + } + File fromFile = new File(_directoryName, fromFileName); + + if(!fromFile.renameTo(toFile)) + { + throw new AMQStoreException("Cannot rename file " + fromFile.getAbsolutePath() + " to " + toFile.getAbsolutePath()); + } + } + + private boolean fileExists(String fileName) + { + File file = new File(_directoryName, fileName); + return file.exists(); + } + + private void getFileLock() throws IOException, AMQStoreException + { + File lockFile = new File(_directoryName, _name + ".lck"); + lockFile.createNewFile(); + + FileOutputStream out = new FileOutputStream(lockFile); + FileChannel channel = out.getChannel(); + try + { + _fileLock = channel.tryLock(); + } + catch(OverlappingFileLockException e) + { + _fileLock = null; + } + if(_fileLock == null) + { + throw new AMQStoreException("Cannot get lock on file " + lockFile.getAbsolutePath() + " is another instance running?"); + } + lockFile.deleteOnExit(); + } + + private void checkDirectoryIsWritable(String directoryName) throws AMQStoreException + { + File dir = new File(directoryName); + if(dir.exists()) + { + if(dir.isDirectory()) + { + if(!dir.canWrite()) + { + throw new AMQStoreException("Configuration path " + directoryName + " exists, but is not writable"); + } + + } + else + { + throw new AMQStoreException("Configuration path " + directoryName + " exists, but is not a directory"); + } + } + else if(!dir.mkdirs()) + { + throw new AMQStoreException("Cannot create directory " + directoryName); + } + } + + private void load() throws IOException + { + Map data = _objectMapper.readValue(new File(_directoryName,_configFileName),Map.class); + Collection<Class<? extends ConfiguredObject>> childClasses = + MODEL.getChildTypes(VirtualHost.class); + String modelVersion = (String) data.remove("modelVersion"); + Object configVersion; + if((configVersion = data.remove("configVersion")) instanceof Integer) + { + _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); + } + } + } + } + } + } + + 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 = + MODEL.getChildTypes(clazz); + String idStr = (String) data.remove("id"); + final UUID id = UUID.fromString(idStr); + final String type = clazz.getSimpleName(); + + for(Class<? extends ConfiguredObject> childClass : childClasses) + { + final String childType = childClass.getSimpleName(); + String attrName = childType.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, clazz, id); + } + } + } + } + + } + if(parentId != null) + { + data.put(parentClass.getSimpleName().toLowerCase(),parentId); + for(Class<? extends ConfiguredObject> otherParent : MODEL.getParentTypes(clazz)) + { + if(otherParent != parentClass) + { + final String otherParentAttr = otherParent.getSimpleName().toLowerCase(); + Object otherParentId = data.get(otherParentAttr); + if(otherParentId instanceof String) + { + try + { + data.put(otherParentAttr, UUID.fromString((String) otherParentId)); + } + catch(IllegalArgumentException e) + { + // + } + } + } + + } + } + + _objectsById.put(id, new ConfiguredObjectRecord(id, type, data)); + List<UUID> idsForType = _idsByType.get(type); + if(idsForType == null) + { + idsForType = new ArrayList<UUID>(); + _idsByType.put(type, idsForType); + } + idsForType.add(id); + + } + + @Override + public synchronized void create(final UUID id, final String type, final Map<String, Object> attributes) throws AMQStoreException + { + if(_objectsById.containsKey(id)) + { + throw new AMQStoreException("Object with id " + id + " already exists"); + } + else if(!CLASS_NAME_MAPPING.containsKey(type)) + { + throw new AMQStoreException("Cannot create object of unknown type " + type); + } + else + { + ConfiguredObjectRecord record = new ConfiguredObjectRecord(id, type, attributes); + _objectsById.put(id, record); + List<UUID> idsForType = _idsByType.get(type); + if(idsForType == null) + { + idsForType = new ArrayList<UUID>(); + _idsByType.put(type, idsForType); + } + idsForType.add(id); + save(); + } + } + + private void save() throws AMQStoreException + { + Collection<Class<? extends ConfiguredObject>> childClasses = + MODEL.getChildTypes(VirtualHost.class); + + Map<String, Object> virtualHostMap = new LinkedHashMap<String, Object>(); + virtualHostMap.put("modelVersion", Model.MODEL_VERSION); + virtualHostMap.put("configVersion", _configVersion); + + for(Class<? extends ConfiguredObject> childClass : childClasses) + { + 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); + } + } + + try + { + + File tmpFile = File.createTempFile("cfg","tmp", new File(_directoryName)); + tmpFile.deleteOnExit(); + _objectMapper.writeValue(tmpFile,virtualHostMap); + renameFile(_configFileName,_backupFileName); + renameFile(tmpFile.getName(),_configFileName); + tmpFile.delete(); + File backupFile = new File(_directoryName, _backupFileName); + backupFile.delete(); + + } + catch (IOException e) + { + throw new AMQStoreException("Cannot save to store", e); + } + } + + private Map<String, Object> build(final Class<? extends ConfiguredObject> type, final UUID id) + { + ConfiguredObjectRecord record = _objectsById.get(id); + Map<String,Object> map = new LinkedHashMap<String, Object>(); + map.put("id", id); + map.putAll(record.getAttributes()); + map.remove(MODEL.getParentTypes(type).iterator().next().getSimpleName().toLowerCase()); + + Collection<Class<? extends ConfiguredObject>> childClasses = + new ArrayList<Class<? extends ConfiguredObject>>(MODEL.getChildTypes(type)); + + for(Class<? extends ConfiguredObject> childClass : childClasses) + { + // only add if this is the "first" parent + if(MODEL.getParentTypes(childClass).iterator().next() == type) + { + String attrName = childClass.getSimpleName().toLowerCase() + "s"; + List<UUID> childIds = _idsByType.get(childClass.getSimpleName()); + if(childIds != null) + { + List<Map<String,Object>> entities = new ArrayList<Map<String, Object>>(); + for(UUID childId : childIds) + { + ConfiguredObjectRecord childRecord = _objectsById.get(childId); + final String parentArg = type.getSimpleName().toLowerCase(); + if(id.toString().equals(String.valueOf(childRecord.getAttributes().get(parentArg)))) + { + entities.add(build(childClass,childId)); + } + } + if(!entities.isEmpty()) + { + map.put(attrName,entities); + } + } + } + } + + return map; + } + + @Override + public void remove(final UUID id, final String type) throws AMQStoreException + { + removeConfiguredObjects(id); + } + + @Override + public synchronized UUID[] removeConfiguredObjects(final UUID... objects) throws AMQStoreException + { + List<UUID> removedIds = new ArrayList<UUID>(); + for(UUID id : objects) + { + ConfiguredObjectRecord record = _objectsById.remove(id); + if(record != null) + { + removedIds.add(id); + _idsByType.get(record.getType()).remove(id); + } + } + save(); + return removedIds.toArray(new UUID[removedIds.size()]); + } + + @Override + public void update(final UUID id, final String type, final Map<String, Object> attributes) throws AMQStoreException + { + update(false, new ConfiguredObjectRecord(id, type, attributes)); + } + + @Override + public void update(final ConfiguredObjectRecord... records) throws AMQStoreException + { + update(false, records); + } + + @Override + public void update(final boolean createIfNecessary, final ConfiguredObjectRecord... records) + throws AMQStoreException + { + for(ConfiguredObjectRecord record : records) + { + final UUID id = record.getId(); + final String type = record.getType(); + + if(_objectsById.containsKey(id)) + { + final ConfiguredObjectRecord existingRecord = _objectsById.get(id); + if(!type.equals(existingRecord.getType())) + { + throw new AMQStoreException("Cannot change the type of record " + id + " from type " + + existingRecord.getType() + " to type " + type); + } + } + else if(!createIfNecessary) + { + throw new AMQStoreException("Cannot update record with id " + id + + " of type " + type + " as it does not exist"); + } + else if(!CLASS_NAME_MAPPING.containsKey(type)) + { + throw new AMQStoreException("Cannot update record of unknown type " + type); + } + } + for(ConfiguredObjectRecord record : records) + { + final UUID id = record.getId(); + final String type = record.getType(); + if(_objectsById.put(id, record) == null) + { + List<UUID> idsForType = _idsByType.get(type); + if(idsForType == null) + { + idsForType = new ArrayList<UUID>(); + _idsByType.put(type, idsForType); + } + idsForType.add(id); + } + } + + save(); + } + + public void close() throws Exception + { + try + { + releaseFileLock(); + } + finally + { + _fileLock = null; + _idsByType.clear(); + _objectsById.clear(); + } + + } + + private void releaseFileLock() throws IOException + { + _fileLock.release(); + _fileLock.channel().close(); + } + + + private static Map<String,Class<? extends ConfiguredObject>> generateClassNameMap(final Class<? extends ConfiguredObject> clazz) + { + Map<String,Class<? extends ConfiguredObject>>map = new HashMap<String, Class<? extends ConfiguredObject>>(); + map.put(clazz.getSimpleName().toString(), clazz); + Collection<Class<? extends ConfiguredObject>> childClasses = MODEL.getChildTypes(clazz); + if(childClasses != null) + { + for(Class<? extends ConfiguredObject> childClass : childClasses) + { + map.putAll(generateClassNameMap(childClass)); + } + } + return map; + } + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java new file mode 100644 index 0000000000..374a35d10d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/JsonFileConfigStoreFactory.java @@ -0,0 +1,52 @@ +/* + * + * 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.model.VirtualHost; +import org.apache.qpid.server.plugin.DurableConfigurationStoreFactory; + +public class JsonFileConfigStoreFactory implements DurableConfigurationStoreFactory +{ + @Override + public String getType() + { + return JsonFileConfigStore.TYPE; + } + + @Override + public DurableConfigurationStore createDurableConfigurationStore() + { + return new JsonFileConfigStore(); + } + + @Override + public void validateAttributes(Map<String, Object> attributes) + { + Object storePath = attributes.get(VirtualHost.CONFIG_STORE_PATH); + if(!(storePath instanceof String)) + { + throw new IllegalArgumentException("Attribute '"+ VirtualHost.CONFIG_STORE_PATH + +"' is required and must be of type String."); + + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataTypeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataTypeRegistry.java new file mode 100644 index 0000000000..64f3ab15ee --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageMetaDataTypeRegistry.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.store; + +import org.apache.qpid.server.plugin.MessageMetaDataType; +import org.apache.qpid.server.plugin.QpidServiceLoader; + +public class MessageMetaDataTypeRegistry +{ + private static MessageMetaDataType[] values; + + static + { + int maxOrdinal = -1; + + Iterable<MessageMetaDataType> messageMetaDataTypes = + new QpidServiceLoader<MessageMetaDataType>().atLeastOneInstanceOf(MessageMetaDataType.class); + + for(MessageMetaDataType type : messageMetaDataTypes) + { + if(type.ordinal()>maxOrdinal) + { + maxOrdinal = type.ordinal(); + } + } + values = new MessageMetaDataType[maxOrdinal+1]; + for(MessageMetaDataType type : new QpidServiceLoader<MessageMetaDataType>().instancesOf(MessageMetaDataType.class)) + { + if(values[type.ordinal()] != null) + { + throw new IllegalStateException("Multiple MessageDataType (" + +values[type.ordinal()].getClass().getName() + +", " + + type.getClass().getName() + + ") defined for the same ordinal value: " + type.ordinal()); + } + values[type.ordinal()] = type; + } + } + + + public static MessageMetaDataType fromOrdinal(int ordinal) + { + return values[ordinal]; + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java index 5fc6bad368..996d71d51d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.store; -import org.apache.commons.configuration.Configuration; +import org.apache.qpid.server.model.VirtualHost; /** * MessageStore defines the interface to a storage area, which can be used to preserve the state of messages. @@ -33,13 +33,14 @@ public interface MessageStore * whatever parameters it wants. * * - * @param name The name to be used by this store + * + * + * @param virtualHost * @param messageRecoveryHandler Handler to be called as the store recovers on start up * @param tlogRecoveryHandler * @throws Exception If any error occurs that means the store is unable to configure itself. */ - void configureMessageStore(String name, - MessageStoreRecoveryHandler messageRecoveryHandler, + void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) throws Exception; void activate() throws Exception; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java index fe7dd81e0c..a8013b8e9b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreCreator.java @@ -61,7 +61,8 @@ public class MessageStoreCreator MessageStoreFactory factory = _factories.get(storeType.toLowerCase()); if (factory == null) { - throw new IllegalConfigurationException("Unknown store type: " + storeType); + throw new IllegalConfigurationException("Unknown store type: " + storeType + + ". Supported types: " + _factories.keySet()); } return factory.createMessageStore(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NonNullUpgrader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NonNullUpgrader.java new file mode 100644 index 0000000000..a671e93b26 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NonNullUpgrader.java @@ -0,0 +1,62 @@ +/* + * + * 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.HashMap; +import java.util.Map; +import java.util.UUID; + +public abstract class NonNullUpgrader implements DurableConfigurationStoreUpgrader +{ + private DurableConfigurationStoreUpgrader _nextUpgrader; + private final Map<UUID, ConfiguredObjectRecord> _updates = new HashMap<UUID, ConfiguredObjectRecord>(); + + public final void setNextUpgrader(final DurableConfigurationStoreUpgrader upgrader) + { + if(_nextUpgrader == null) + { + _nextUpgrader = upgrader; + } + else + { + _nextUpgrader.setNextUpgrader(upgrader); + } + } + + protected DurableConfigurationStoreUpgrader getNextUpgrader() + { + return _nextUpgrader; + } + + protected Map<UUID, ConfiguredObjectRecord> getUpdateMap() + { + return _updates; + } + + @Override + public final Map<UUID, ConfiguredObjectRecord> getUpdatedRecords() + { + final Map<UUID, ConfiguredObjectRecord> updates = new HashMap<UUID, ConfiguredObjectRecord>(_updates); + updates.putAll(_nextUpgrader.getUpdatedRecords()); + return updates; + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java index 77cde80af9..57dbfabaa4 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java @@ -21,14 +21,13 @@ package org.apache.qpid.server.store; import java.util.Map; import java.util.UUID; +import org.apache.qpid.AMQStoreException; import org.apache.qpid.server.model.VirtualHost; public abstract class NullMessageStore implements MessageStore, DurableConfigurationStore { @Override - public void configureConfigStore(String name, - ConfigurationRecoveryHandler recoveryHandler, - VirtualHost virtualHost) throws Exception + public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) throws Exception { } @@ -38,18 +37,34 @@ public abstract class NullMessageStore implements MessageStore, DurableConfigura } @Override + public void update(ConfiguredObjectRecord... records) throws AMQStoreException + { + } + + @Override + public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws AMQStoreException + { + } + + + @Override public void remove(UUID id, String type) { } @Override + public UUID[] removeConfiguredObjects(final UUID... objects) throws AMQStoreException + { + return objects; + } + + @Override public void create(UUID id, String type, Map<String, Object> attributes) { } @Override - public void configureMessageStore(String name, - MessageStoreRecoveryHandler recoveryHandler, + public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler recoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) throws Exception { } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullUpgrader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullUpgrader.java new file mode 100644 index 0000000000..c8a812fa89 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullUpgrader.java @@ -0,0 +1,58 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +import java.util.Collections; +import java.util.Map; +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 UUID id, final String type, final Map<String, Object> attributes) + { + _durableConfigurationRecoverer.onConfiguredObject(id, type, attributes); + } + + @Override + public void complete() + { + } + + @Override + public void setNextUpgrader(final DurableConfigurationStoreUpgrader upgrader) + { + throw new UnsupportedOperationException("NullUpgrader must always be the last upgrader"); + } + + @Override + public Map<UUID, ConfiguredObjectRecord> getUpdatedRecords() + { + return Collections.emptyMap(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java index 12d2a6a6c7..9ae6cca8e6 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/StorableMessageMetaData.java @@ -21,6 +21,7 @@ package org.apache.qpid.server.store; import java.nio.ByteBuffer; +import org.apache.qpid.server.plugin.MessageMetaDataType; public interface StorableMessageMetaData { @@ -34,3 +35,4 @@ public interface StorableMessageMetaData boolean isPersistent(); } + diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UnresolvedDependency.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UnresolvedDependency.java new file mode 100644 index 0000000000..98348efbd2 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UnresolvedDependency.java @@ -0,0 +1,31 @@ +/* + * + * 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; + +public interface UnresolvedDependency<T> +{ + public UUID getId(); + public String getType(); + + public void resolve(final T dependency); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UnresolvedObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UnresolvedObject.java new file mode 100644 index 0000000000..7ebebadae7 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UnresolvedObject.java @@ -0,0 +1,28 @@ +/* + * + * 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; + +public interface UnresolvedObject<T> +{ + public UnresolvedDependency[] getUnresolvedDependencies(); + + T resolve(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UpgraderProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UpgraderProvider.java new file mode 100644 index 0000000000..c2ea0745ff --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/UpgraderProvider.java @@ -0,0 +1,26 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.store; + +public interface UpgraderProvider +{ + DurableConfigurationStoreUpgrader getUpgrader(int configVersion, DurableConfigurationRecoverer recoverer); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java index 7a924abb3d..36d49d8279 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.subscription; +import java.util.concurrent.atomic.AtomicLong; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.logging.LogActor; @@ -29,6 +30,8 @@ import org.apache.qpid.server.queue.QueueEntry; public interface Subscription { + AtomicLong SUB_ID_GENERATOR = new AtomicLong(0); + LogActor getLogActor(); boolean isTransient(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java deleted file mode 100644 index 3659243cea..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java +++ /dev/null @@ -1,85 +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.subscription; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.filter.FilterManager; -import org.apache.qpid.server.flow.FlowCreditManager; -import org.apache.qpid.server.flow.FlowCreditManager_0_10; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.transport.ServerSession; -import org.apache.qpid.transport.MessageAcceptMode; -import org.apache.qpid.transport.MessageAcquireMode; -import org.apache.qpid.transport.MessageFlowMode; - -import java.util.Map; - -/** - * Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory - * primarily assists testing although in future more sophisticated subscribers may need a different subscription - * implementation. - * - * @see org.apache.qpid.server.queue.AMQQueue - */ -public interface SubscriptionFactory -{ - Subscription createSubscription(int channel, - AMQProtocolSession protocolSession, - AMQShortString consumerTag, - boolean acks, - FieldTable filters, - boolean noLocal, FlowCreditManager creditManager) throws AMQException; - - - Subscription createSubscription(AMQChannel channel, - AMQProtocolSession protocolSession, - AMQShortString consumerTag, - boolean acks, - FieldTable filters, - boolean noLocal, - FlowCreditManager creditManager, - ClientDeliveryMethod clientMethod, - RecordDeliveryMethod recordMethod - ) - throws AMQException; - - - SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(AMQChannel channel, - AMQProtocolSession session, - AMQShortString consumerTag, - FieldTable filters, - boolean noLocal, - FlowCreditManager creditManager, - ClientDeliveryMethod deliveryMethod, - RecordDeliveryMethod recordMethod) throws AMQException; - - Subscription_0_10 createSubscription(final ServerSession session, - final String destination, - final MessageAcceptMode acceptMode, - final MessageAcquireMode acquireMode, - final MessageFlowMode flowMode, - final FlowCreditManager_0_10 creditManager, - final FilterManager filterManager, - final Map<String,Object> arguments); -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java index 43e60c8e13..31e4dc6def 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java @@ -38,7 +38,7 @@ import java.util.List; /** * An implementation of ServerTransaction where each enqueue/dequeue * operation takes place within it own transaction. - * + * * Since there is no long-lived transaction, the commit and rollback methods of * this implementation are empty. */ @@ -98,13 +98,13 @@ public class AsyncAutoCommitTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getName()); } txn = _messageStore.newTransaction(); txn.dequeueMessage(queue, message); future = txn.commitTranAsync(); - + txn = null; } else @@ -172,7 +172,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getName()); } if(txn == null) @@ -220,7 +220,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getName()); } txn = _messageStore.newTransaction(); @@ -262,19 +262,19 @@ public class AsyncAutoCommitTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getName()); } if (txn == null) { txn = _messageStore.newTransaction(); } - + txn.enqueueMessage(queue, message); } } - + } StoreFuture future; if (txn != null) @@ -320,8 +320,8 @@ public class AsyncAutoCommitTransaction implements ServerTransaction } }); } - } - + } + public void commit() { } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java index 8a9479a2d4..b081641f47 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java @@ -37,7 +37,7 @@ import java.util.List; /** * An implementation of ServerTransaction where each enqueue/dequeue * operation takes place within it own transaction. - * + * * Since there is no long-lived transaction, the commit and rollback methods of * this implementation are empty. */ @@ -82,7 +82,7 @@ public class AutoCommitTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getName()); } txn = _messageStore.newTransaction(); @@ -119,7 +119,7 @@ public class AutoCommitTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getName()); } if(txn == null) @@ -161,7 +161,7 @@ public class AutoCommitTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getName()); } txn = _messageStore.newTransaction(); @@ -199,19 +199,19 @@ public class AutoCommitTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getName()); } if (txn == null) { txn = _messageStore.newTransaction(); } - + txn.enqueueMessage(queue, message); } } - + } if (txn != null) { @@ -240,8 +240,8 @@ public class AutoCommitTransaction implements ServerTransaction public void commit(final Runnable immediatePostTransactionAction) { immediatePostTransactionAction.run(); - } - + } + public void commit() { } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java index afa7cb0fb4..23265199c7 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java @@ -1,5 +1,5 @@ /* - * + * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -7,16 +7,16 @@ * 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.txn; @@ -39,7 +39,7 @@ import java.util.List; /** * A concrete implementation of ServerTransaction where enqueue/dequeue * operations share a single long-lived transaction. - * + * * The caller is responsible for invoking commit() (or rollback()) as necessary. */ public class LocalTransaction implements ServerTransaction @@ -103,7 +103,7 @@ public class LocalTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getName()); } beginTranIfNecessary(); @@ -135,7 +135,7 @@ public class LocalTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Dequeue of message number " + message.getMessageNumber() + " from transaction log. Queue : " + queue.getName()); } beginTranIfNecessary(); @@ -207,7 +207,7 @@ public class LocalTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString()); + _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getName()); } beginTranIfNecessary(); @@ -238,7 +238,7 @@ public class LocalTransaction implements ServerTransaction { if (_logger.isDebugEnabled()) { - _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getNameShortString() ); + _logger.debug("Enqueue of message number " + message.getMessageNumber() + " to transaction log. Queue : " + queue.getName() ); } beginTranIfNecessary(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java index 15f5becec2..0cd4f0b6b2 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java @@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit; import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; +import org.apache.qpid.AMQSecurityException; import org.apache.qpid.server.configuration.ExchangeConfiguration; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.configuration.VirtualHostConfiguration; @@ -43,7 +44,6 @@ import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.exchange.DefaultExchangeRegistry; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeFactory; -import org.apache.qpid.server.exchange.ExchangeInUseException; import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.VirtualHostMessages; @@ -51,7 +51,7 @@ import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; -import org.apache.qpid.server.protocol.v1_0.LinkRegistry; +import org.apache.qpid.server.protocol.LinkRegistry; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.DefaultQueueRegistry; @@ -61,9 +61,11 @@ import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.DurableConfigurationStoreHelper; +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.txn.DtxRegistry; +import org.apache.qpid.server.virtualhost.plugins.QueueExistsException; public abstract class AbstractVirtualHost implements VirtualHost, IConnectionRegistry.RegistryChangeListener, EventListener { @@ -96,6 +98,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg private final ConnectionRegistry _connectionRegistry; private final DtxRegistry _dtxRegistry; + private final AMQQueueFactory _queueFactory; private volatile State _state = State.INITIALISING; @@ -137,11 +140,14 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg _houseKeepingTasks = new ScheduledThreadPoolExecutor(_vhostConfig.getHouseKeepingThreadCount()); + _queueRegistry = new DefaultQueueRegistry(this); + _queueFactory = new AMQQueueFactory(this, _queueRegistry); + _exchangeFactory = new DefaultExchangeFactory(this); - _exchangeRegistry = new DefaultExchangeRegistry(this); + _exchangeRegistry = new DefaultExchangeRegistry(this, _queueRegistry); initialiseStatistics(); @@ -299,12 +305,12 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg private void configureQueue(QueueConfiguration queueConfiguration) throws AMQException, ConfigurationException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this); + AMQQueue queue = _queueFactory.createAMQQueueImpl(queueConfiguration); String queueName = queue.getName(); if (queue.isDurable()) { - DurableConfigurationStoreHelper.createQueue(getDurableConfigurationStore(), queue, null); + DurableConfigurationStoreHelper.createQueue(getDurableConfigurationStore(), queue); } //get the exchange name (returns default exchange name if none was specified) @@ -429,12 +435,108 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg } @Override + public AMQQueue getQueue(String name) + { + return _queueRegistry.getQueue(name); + } + + @Override + public AMQQueue getQueue(UUID id) + { + return _queueRegistry.getQueue(id); + } + + @Override + public Collection<AMQQueue> getQueues() + { + return _queueRegistry.getQueues(); + } + + @Override + public int removeQueue(AMQQueue queue) throws AMQException + { + synchronized (getQueueRegistry()) + { + int purged = queue.delete(); + + getQueueRegistry().unregisterQueue(queue.getName()); + if (queue.isDurable() && !queue.isAutoDelete()) + { + DurableConfigurationStore store = getDurableConfigurationStore(); + DurableConfigurationStoreHelper.removeQueue(store, queue); + } + return purged; + } + } + + @Override + public AMQQueue createQueue(UUID id, + String queueName, + boolean durable, + String owner, + boolean autoDelete, + boolean exclusive, + boolean deleteOnNoConsumer, + Map<String, Object> arguments) throws AMQException + { + + if (queueName == null) + { + throw new IllegalArgumentException("Queue name must not be null"); + } + + // Access check + if (!getSecurityManager().authoriseCreateQueue(autoDelete, + durable, + exclusive, + null, + null, + queueName, + owner)) + { + String description = "Permission denied: queue-name '" + queueName + "'"; + throw new AMQSecurityException(description); + } + + synchronized (_queueRegistry) + { + if(_queueRegistry.getQueue(queueName) != null) + { + throw new QueueExistsException("Queue with name " + queueName + " already exists", _queueRegistry.getQueue(queueName)); + } + if(id == null) + { + + id = UUIDGenerator.generateExchangeUUID(queueName, getName()); + while(_queueRegistry.getQueue(id) != null) + { + id = UUID.randomUUID(); + } + + } + else if(_queueRegistry.getQueue(id) != null) + { + throw new QueueExistsException("Queue with id " + id + " already exists", _queueRegistry.getQueue(queueName)); + } + return _queueFactory.createQueue(id, queueName, durable, owner, autoDelete, exclusive, deleteOnNoConsumer, + arguments); + } + + } + + @Override public Exchange getExchange(String name) { return _exchangeRegistry.getExchange(name); } @Override + public Exchange getExchange(UUID id) + { + return _exchangeRegistry.getExchange(id); + } + + @Override public Exchange getDefaultExchange() { return _exchangeRegistry.getDefaultExchange(); @@ -514,7 +616,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg for(ExchangeType type : getExchangeTypes()) { - if(type.getDefaultExchangeName().toString().equals( exchange.getName() )) + if(type.getDefaultExchangeName().equals( exchange.getName() )) { throw new RequiredExchangeException(exchange.getName()); } @@ -564,6 +666,18 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg _logger.error("Failed to close message store", e); } } + if (getDurableConfigurationStore() != null) + { + //Remove MessageStore Interface should not throw Exception + try + { + getDurableConfigurationStore().close(); + } + catch (Exception e) + { + _logger.error("Failed to close message store", e); + } + } } @@ -745,6 +859,22 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg } } + protected Map<String, DurableConfiguredObjectRecoverer> getDurableConfigurationRecoverers() + { + DurableConfiguredObjectRecoverer[] recoverers = { + new QueueRecoverer(this, getExchangeRegistry(), _queueFactory), + new ExchangeRecoverer(getExchangeRegistry(), getExchangeFactory()), + new BindingRecoverer(this, getExchangeRegistry()) + }; + + final Map<String, DurableConfiguredObjectRecoverer> recovererMap= new HashMap<String, DurableConfiguredObjectRecoverer>(); + for(DurableConfiguredObjectRecoverer recoverer : recoverers) + { + recovererMap.put(recoverer.getType(), recoverer); + } + return recovererMap; + } + private class VirtualHostHouseKeepingTask extends HouseKeepingTask { public VirtualHostHouseKeepingTask() @@ -766,8 +896,7 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg q.checkMessageStatus(); } catch (Exception e) { - _logger.error("Exception in housekeeping for queue: " - + q.getNameShortString().toString(), e); + _logger.error("Exception in housekeeping for queue: " + q.getName(), e); //Don't throw exceptions as this will stop the // house keeping task from running. } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java new file mode 100644 index 0000000000..a321c285b7 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java @@ -0,0 +1,177 @@ +/* + * + * 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.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.apache.log4j.Logger; +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeRegistry; +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.UnresolvedDependency; +import org.apache.qpid.server.store.UnresolvedObject; + +public class BindingRecoverer extends AbstractDurableConfiguredObjectRecoverer<Binding> +{ + private static final Logger _logger = Logger.getLogger(BindingRecoverer.class); + + private final ExchangeRegistry _exchangeRegistry; + private final VirtualHost _virtualHost; + + public BindingRecoverer(final VirtualHost virtualHost, + final ExchangeRegistry exchangeRegistry) + { + _exchangeRegistry = exchangeRegistry; + _virtualHost = virtualHost; + } + + @Override + public UnresolvedObject<Binding> createUnresolvedObject(final UUID id, + final String type, + final Map<String, Object> attributes) + { + return new UnresolvedBinding(id, attributes); + } + + @Override + public String getType() + { + return org.apache.qpid.server.model.Binding.class.getSimpleName(); + } + + private class UnresolvedBinding implements UnresolvedObject<Binding> + { + private final Map<String, Object> _bindingArgumentsMap; + private final String _bindingName; + private final UUID _queueId; + private final UUID _exchangeId; + private final UUID _bindingId; + + private List<UnresolvedDependency> _unresolvedDependencies = + new ArrayList<UnresolvedDependency>(); + + private Exchange _exchange; + private AMQQueue _queue; + + public UnresolvedBinding(final UUID id, + final Map<String, Object> attributeMap) + { + _bindingId = id; + _exchangeId = UUID.fromString(String.valueOf(attributeMap.get(org.apache.qpid.server.model.Binding.EXCHANGE))); + _queueId = UUID.fromString(String.valueOf(attributeMap.get(org.apache.qpid.server.model.Binding.QUEUE))); + _exchange = _exchangeRegistry.getExchange(_exchangeId); + if(_exchange == null) + { + _unresolvedDependencies.add(new ExchangeDependency()); + } + _queue = _virtualHost.getQueue(_queueId); + if(_queue == null) + { + _unresolvedDependencies.add(new QueueDependency()); + } + + _bindingName = (String) attributeMap.get(org.apache.qpid.server.model.Binding.NAME); + _bindingArgumentsMap = (Map<String, Object>) attributeMap.get(org.apache.qpid.server.model.Binding.ARGUMENTS); + } + + @Override + public UnresolvedDependency[] getUnresolvedDependencies() + { + return _unresolvedDependencies.toArray(new UnresolvedDependency[_unresolvedDependencies.size()]); + } + + @Override + public Binding resolve() + { + try + { + if(_exchange.getBinding(_bindingName, _queue, _bindingArgumentsMap) == null) + { + _logger.info("Restoring binding: (Exchange: " + _exchange.getName() + ", Queue: " + _queue.getName() + + ", Routing Key: " + _bindingName + ", Arguments: " + _bindingArgumentsMap + ")"); + + _exchange.restoreBinding(_bindingId, _bindingName, _queue, _bindingArgumentsMap); + } + return _exchange.getBinding(_bindingName, _queue, _bindingArgumentsMap); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } + + private class QueueDependency implements UnresolvedDependency<AMQQueue> + { + + @Override + public UUID getId() + { + return _queueId; + } + + @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<Exchange> + { + + @Override + public UUID getId() + { + return _exchangeId; + } + + @Override + public String getType() + { + return org.apache.qpid.server.model.Exchange.class.getSimpleName(); + } + + @Override + public void resolve(final Exchange dependency) + { + _exchange = dependency; + _unresolvedDependencies.remove(this); + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java new file mode 100644 index 0000000000..8d05e719ee --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/DefaultUpgraderProvider.java @@ -0,0 +1,266 @@ +/* + * + * 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.LinkedHashMap; +import java.util.Map; +import java.util.UUID; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.exchange.FilterSupport; +import org.apache.qpid.server.exchange.TopicExchange; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.queue.QueueArgumentsConverter; +import org.apache.qpid.server.store.ConfiguredObjectRecord; +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; + +import static org.apache.qpid.server.model.VirtualHost.CURRENT_CONFIG_VERSION; + +public class DefaultUpgraderProvider implements UpgraderProvider +{ + private final ExchangeRegistry _exchangeRegistry; + private final VirtualHost _virtualHost; + + public DefaultUpgraderProvider(final VirtualHost virtualHost, + final ExchangeRegistry exchangeRegistry) + { + _virtualHost = virtualHost; + _exchangeRegistry = exchangeRegistry; + } + + public DurableConfigurationStoreUpgrader getUpgrader(final int configVersion, DurableConfigurationRecoverer recoverer) + { + DurableConfigurationStoreUpgrader currentUpgrader = null; + switch(configVersion) + { + case 0: + currentUpgrader = addUpgrader(currentUpgrader, new Version0Upgrader()); + case 1: + currentUpgrader = addUpgrader(currentUpgrader, new Version1Upgrader()); + case 2: + currentUpgrader = addUpgrader(currentUpgrader, new Version2Upgrader()); + + case CURRENT_CONFIG_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 UUID id, final String type, Map<String, Object> attributes) + { + _records.put(id, new ConfiguredObjectRecord(id, type, attributes)); + } + + 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(Map<String, Object> binding) + { + UUID exchangeId = UUID.fromString((String)binding.get(Binding.EXCHANGE)); + + if(_records.containsKey(exchangeId)) + { + return "topic".equals(_records.get(exchangeId) + .getAttributes() + .get(org.apache.qpid.server.model.Exchange.TYPE)); + } + else + { + return _exchangeRegistry.getExchange(exchangeId) != null + && _exchangeRegistry.getExchange(exchangeId).getType() == 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(attributes)) + { + attributes = new LinkedHashMap<String, Object>(attributes); + removeSelectorArguments(attributes); + + record = new ConfiguredObjectRecord(id, type, attributes); + getUpdateMap().put(id, record); + entry.setValue(record); + + } + getNextUpgrader().configuredObject(id, type, attributes); + } + + 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 non-existant queues or exchanges. + */ + private class Version1Upgrader extends NonNullUpgrader + { + @Override + public void configuredObject(final UUID id, String type, final Map<String, Object> attributes) + { + type = type.substring(1+type.lastIndexOf('.')); + getUpdateMap().put(id, new ConfiguredObjectRecord(id, type, attributes)); + + } + + @Override + public void complete() + { + for(Map.Entry<UUID, ConfiguredObjectRecord> entry : getUpdateMap().entrySet()) + { + final ConfiguredObjectRecord record = entry.getValue(); + if(isBinding(record.getType()) && (unknownExchange((String) record.getAttributes().get(Binding.EXCHANGE)) + || unknownQueue((String) record.getAttributes().get(Binding.QUEUE)))) + { + entry.setValue(null); + } + else + { + getNextUpgrader().configuredObject(record.getId(), record.getType(), record.getAttributes()); + } + } + getNextUpgrader().complete(); + } + + private boolean unknownExchange(final String exchangeIdString) + { + UUID exchangeId = UUID.fromString(exchangeIdString); + ConfiguredObjectRecord localRecord = getUpdateMap().get(exchangeId); + return !((localRecord != null && localRecord.getType().equals(Exchange.class.getSimpleName())) + || _exchangeRegistry.getExchange(exchangeId) != null); + } + + private boolean unknownQueue(final String queueIdString) + { + UUID queueId = UUID.fromString(queueIdString); + 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(UUID id, String type, Map<String, Object> attributes) + { + if(Queue.class.getSimpleName().equals(type)) + { + Map<String, Object> newAttributes = new LinkedHashMap<String, Object>(); + if(attributes.get(ARGUMENTS) instanceof Map) + { + newAttributes.putAll(QueueArgumentsConverter.convertWireArgsToModel((Map<String, Object>) attributes + .get(ARGUMENTS))); + } + newAttributes.putAll(attributes); + attributes = newAttributes; + getUpdateMap().put(id, new ConfiguredObjectRecord(id,type,attributes)); + } + + getNextUpgrader().configuredObject(id,type,attributes); + } + + @Override + public void complete() + { + getNextUpgrader().complete(); + } + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java new file mode 100644 index 0000000000..6ad7014c47 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/ExchangeRecoverer.java @@ -0,0 +1,102 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.virtualhost; + +import java.util.Map; +import java.util.UUID; +import org.apache.qpid.AMQException; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeFactory; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.store.AbstractDurableConfiguredObjectRecoverer; +import org.apache.qpid.server.store.UnresolvedDependency; +import org.apache.qpid.server.store.UnresolvedObject; + +public class ExchangeRecoverer extends AbstractDurableConfiguredObjectRecoverer<Exchange> +{ + private final ExchangeRegistry _exchangeRegistry; + private final ExchangeFactory _exchangeFactory; + + public ExchangeRecoverer(final ExchangeRegistry exchangeRegistry, final ExchangeFactory exchangeFactory) + { + _exchangeRegistry = exchangeRegistry; + _exchangeFactory = exchangeFactory; + } + + @Override + public String getType() + { + return org.apache.qpid.server.model.Exchange.class.getSimpleName(); + } + + @Override + public UnresolvedObject<Exchange> createUnresolvedObject(final UUID id, + final String type, + final Map<String, Object> attributes) + { + return new UnresolvedExchange(id, attributes); + } + + private class UnresolvedExchange implements UnresolvedObject<Exchange> + { + private Exchange _exchange; + + public UnresolvedExchange(final UUID id, + final Map<String, Object> attributeMap) + { + String exchangeName = (String) attributeMap.get(org.apache.qpid.server.model.Exchange.NAME); + String exchangeType = (String) attributeMap.get(org.apache.qpid.server.model.Exchange.TYPE); + String lifeTimePolicy = (String) attributeMap.get(org.apache.qpid.server.model.Exchange.LIFETIME_POLICY); + boolean autoDelete = lifeTimePolicy == null + || LifetimePolicy.valueOf(lifeTimePolicy) == LifetimePolicy.AUTO_DELETE; + try + { + _exchange = _exchangeRegistry.getExchange(id); + if(_exchange == null) + { + _exchange = _exchangeRegistry.getExchange(exchangeName); + } + if (_exchange == null) + { + _exchange = _exchangeFactory.restoreExchange(id, exchangeName, exchangeType, autoDelete); + _exchangeRegistry.registerExchange(_exchange); + } + } + catch (AMQException e) + { + throw new RuntimeException("Error recovering exchange uuid " + id + " name " + exchangeName, e); + } + } + + @Override + public UnresolvedDependency[] getUnresolvedDependencies() + { + return new UnresolvedDependency[0]; + } + + @Override + public Exchange resolve() + { + return _exchange; + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java new file mode 100644 index 0000000000..02d628da68 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/QueueRecoverer.java @@ -0,0 +1,157 @@ +/* + * + * 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.LinkedHashMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.apache.log4j.Logger; +import org.apache.qpid.AMQException; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueFactory; +import org.apache.qpid.server.store.AbstractDurableConfiguredObjectRecoverer; +import org.apache.qpid.server.store.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 VirtualHost _virtualHost; + private final ExchangeRegistry _exchangeRegistry; + private final QueueFactory _queueFactory; + + public QueueRecoverer(final VirtualHost virtualHost, + final ExchangeRegistry exchangeRegistry, + final QueueFactory queueFactory) + { + _virtualHost = virtualHost; + _exchangeRegistry = exchangeRegistry; + _queueFactory = queueFactory; + } + + @Override + public String getType() + { + return Queue.class.getSimpleName(); + } + + @Override + public UnresolvedObject<AMQQueue> createUnresolvedObject(final UUID id, + final String type, + final Map<String, Object> attributes) + { + return new UnresolvedQueue(id, type, attributes); + } + + private class UnresolvedQueue implements UnresolvedObject<AMQQueue> + { + private final Map<String, Object> _attributes; + private final UUID _alternateExchangeId; + private final UUID _id; + private AMQQueue _queue; + private List<UnresolvedDependency> _dependencies = new ArrayList<UnresolvedDependency>(); + private Exchange _alternateExchange; + + public UnresolvedQueue(final UUID id, + final String type, + final Map<String, Object> attributes) + { + _attributes = attributes; + _alternateExchangeId = _attributes.get(Queue.ALTERNATE_EXCHANGE) == null ? null : UUID.fromString((String) _attributes + .get(Queue.ALTERNATE_EXCHANGE)); + _id = id; + if (_alternateExchangeId != null) + { + _alternateExchange = _exchangeRegistry.getExchange(_alternateExchangeId); + if(_alternateExchange == null) + { + _dependencies.add(new AlternateExchangeDependency()); + } + } + } + + @Override + public UnresolvedDependency[] getUnresolvedDependencies() + { + return _dependencies.toArray(new UnresolvedDependency[_dependencies.size()]); + } + + @Override + public AMQQueue resolve() + { + String queueName = (String) _attributes.get(Queue.NAME); + String owner = (String) _attributes.get(Queue.OWNER); + boolean exclusive = (Boolean) _attributes.get(Queue.EXCLUSIVE); + + Map<String, Object> queueArgumentsMap = new LinkedHashMap<String, Object>(_attributes); + queueArgumentsMap.remove(Queue.NAME); + queueArgumentsMap.remove(Queue.OWNER); + queueArgumentsMap.remove(Queue.EXCLUSIVE); + + try + { + _queue = _virtualHost.getQueue(_id); + if(_queue == null) + { + _queue = _virtualHost.getQueue(queueName); + } + + if (_queue == null) + { + _queue = _queueFactory.restoreQueue(_id, queueName, owner, false, exclusive, + false, queueArgumentsMap); + } + } + catch (AMQException e) + { + throw new RuntimeException("Error recovering queue uuid " + _id + " name " + queueName, e); + } + return _queue; + } + + private class AlternateExchangeDependency implements UnresolvedDependency + { + @Override + public UUID getId() + { + return _alternateExchangeId; + } + + @Override + public String getType() + { + return "Exchange"; + } + + @Override + public void resolve(final Object dependency) + { + _alternateExchange = (Exchange) dependency; + _dependencies.remove(this); + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java index b34444cb4c..b7e51d88d3 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHost.java @@ -23,7 +23,9 @@ import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.stats.StatisticsGatherer; +import org.apache.qpid.server.store.DurableConfigurationRecoverer; 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.MessageStoreCreator; import org.apache.qpid.server.store.OperationalLoggingListener; @@ -68,7 +70,7 @@ public class StandardVirtualHost extends AbstractVirtualHost final MessageStoreLogSubject - storeLogSubject = new MessageStoreLogSubject(this, messageStore.getClass().getSimpleName()); + storeLogSubject = new MessageStoreLogSubject(getName(), messageStore.getClass().getSimpleName()); OperationalLoggingListener.listen(messageStore, storeLogSubject); return messageStore; @@ -77,7 +79,14 @@ public class StandardVirtualHost extends AbstractVirtualHost private DurableConfigurationStore initialiseConfigurationStore(VirtualHost virtualHost) throws Exception { DurableConfigurationStore configurationStore; - if(getMessageStore() instanceof DurableConfigurationStore) + final Object storeTypeAttr = virtualHost.getAttribute(VirtualHost.CONFIG_STORE_TYPE); + String storeType = storeTypeAttr == null ? null : String.valueOf(storeTypeAttr); + + if(storeType != null) + { + configurationStore = new DurableConfigurationStoreCreator().createMessageStore(storeType); + } + else if(getMessageStore() instanceof DurableConfigurationStore) { configurationStore = (DurableConfigurationStore) getMessageStore(); } @@ -96,11 +105,13 @@ public class StandardVirtualHost extends AbstractVirtualHost _durableConfigurationStore = initialiseConfigurationStore(virtualHost); - VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this, getExchangeRegistry(), getExchangeFactory()); + DurableConfigurationRecoverer configRecoverer = + new DurableConfigurationRecoverer(getName(), getDurableConfigurationRecoverers(), + new DefaultUpgraderProvider(this, getExchangeRegistry())); + _durableConfigurationStore.configureConfigStore(virtualHost, configRecoverer); - _durableConfigurationStore.configureConfigStore(getName(), recoveryHandler, virtualHost); - - _messageStore.configureMessageStore(getName(), recoveryHandler, recoveryHandler); + VirtualHostConfigRecoveryHandler recoveryHandler = new VirtualHostConfigRecoveryHandler(this, getExchangeRegistry(), getExchangeFactory()); + _messageStore.configureMessageStore(virtualHost, recoveryHandler, recoveryHandler); initialiseModel(hostConfig); @@ -109,25 +120,6 @@ public class StandardVirtualHost extends AbstractVirtualHost attainActivation(); } - - protected void closeStorage() - { - //Close MessageStore - if (_messageStore != null) - { - //Remove MessageStore Interface should not throw Exception - try - { - getMessageStore().close(); - } - catch (Exception e) - { - getLogger().error("Failed to close message store", e); - } - } - } - - @Override public MessageStore getMessageStore() { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHostFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHostFactory.java index 2b4cc37814..08f35c08f9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHostFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/StandardVirtualHostFactory.java @@ -19,20 +19,14 @@ package org.apache.qpid.server.virtualhost;/* * */ -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedHashMap; -import java.util.List; import java.util.Map; import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.model.adapter.VirtualHostAdapter; import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.server.plugin.VirtualHostFactory; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.MessageStoreConstants; import org.apache.qpid.server.store.MessageStoreCreator; @@ -89,17 +83,6 @@ public class StandardVirtualHostFactory implements VirtualHostFactory factory.validateAttributes(attributes); } } - // TODO - each store type should validate its own attributes - if(!((String) storeType).equalsIgnoreCase(MemoryMessageStore.TYPE)) - { - /* Object storePath = attributes.get(STORE_PATH_ATTRIBUTE); - if(!(storePath instanceof String)) - { - throw new IllegalArgumentException("Attribute '"+ STORE_PATH_ATTRIBUTE - +"' is required and must be of type String."); - - }*/ - } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index 2435854912..2ebbedccd4 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -21,18 +21,18 @@ package org.apache.qpid.server.virtualhost; import java.util.Collection; +import java.util.Map; import java.util.UUID; import java.util.concurrent.ScheduledFuture; import org.apache.qpid.AMQException; +import org.apache.qpid.AMQSecurityException; import org.apache.qpid.common.Closeable; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeFactory; -import org.apache.qpid.server.exchange.ExchangeInUseException; -import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.plugin.ExchangeType; -import org.apache.qpid.server.protocol.v1_0.LinkRegistry; +import org.apache.qpid.server.protocol.LinkRegistry; +import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.stats.StatisticsGatherer; @@ -48,7 +48,23 @@ public interface VirtualHost extends DurableConfigurationStore.Source, Closeable String getName(); - QueueRegistry getQueueRegistry(); + AMQQueue getQueue(String name); + + AMQQueue getQueue(UUID id); + + Collection<AMQQueue> getQueues(); + + int removeQueue(AMQQueue queue) throws AMQException; + + AMQQueue createQueue(UUID id, + String queueName, + boolean durable, + String owner, + boolean autoDelete, + boolean exclusive, + boolean deleteOnNoConsumer, + Map<String, Object> arguments) throws AMQException; + Exchange createExchange(UUID id, String exchange, @@ -61,6 +77,8 @@ public interface VirtualHost extends DurableConfigurationStore.Source, Closeable void removeExchange(Exchange exchange, boolean force) throws AMQException; Exchange getExchange(String name); + Exchange getExchange(UUID id); + Exchange getDefaultExchange(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java index 34c42cc9cc..39ca3197b4 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java @@ -20,9 +20,6 @@ */ package org.apache.qpid.server.virtualhost; -import java.io.DataInputStream; -import java.io.IOException; -import java.nio.ByteBuffer; import java.util.HashMap; import java.util.Map; import java.util.TreeMap; @@ -31,28 +28,16 @@ import java.util.UUID; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.AMQStoreException; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.messages.ConfigStoreMessages; import org.apache.qpid.server.logging.messages.TransactionLogMessages; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; -import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.message.MessageReference; -import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.model.Binding; -import org.apache.qpid.server.model.LifetimePolicy; -import org.apache.qpid.server.model.Queue; -import org.apache.qpid.server.protocol.v1_0.Message_1_0; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.QueueEntry; -import org.apache.qpid.server.store.ConfigurationRecoveryHandler; -import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.MessageStoreRecoveryHandler; import org.apache.qpid.server.store.StoredMessage; @@ -64,9 +49,8 @@ import org.apache.qpid.server.txn.DtxRegistry; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.transport.Xid; import org.apache.qpid.transport.util.Functions; -import org.apache.qpid.util.ByteBufferInputStream; -public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHandler, +public class VirtualHostConfigRecoveryHandler implements MessageStoreRecoveryHandler, MessageStoreRecoveryHandler.StoredMessageRecoveryHandler, TransactionLogRecoveryHandler, @@ -81,8 +65,6 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa private final Map<Long, ServerMessage> _recoveredMessages = new HashMap<Long, ServerMessage>(); private final Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>(); - private final Map<String, Map<UUID, Map<String, Object>>> _configuredObjects = new HashMap<String, Map<UUID, Map<String, Object>>>(); - private final ExchangeRegistry _exchangeRegistry; private final ExchangeFactory _exchangeFactory; @@ -98,75 +80,14 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa _exchangeFactory = exchangeFactory; } - @Override - public void beginConfigurationRecovery(DurableConfigurationStore store) - { - _logSubject = new MessageStoreLogSubject(_virtualHost,store.getClass().getSimpleName()); - - CurrentActor.get().message(_logSubject, ConfigStoreMessages.RECOVERY_START()); - } - public VirtualHostConfigRecoveryHandler begin(MessageStore store) { - _logSubject = new MessageStoreLogSubject(_virtualHost,store.getClass().getSimpleName()); + _logSubject = new MessageStoreLogSubject(_virtualHost.getName(), store.getClass().getSimpleName()); _store = store; CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_START(null, false)); return this; } - public void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments, UUID alternateExchangeId) - { - try - { - AMQQueue q = _virtualHost.getQueueRegistry().getQueue(queueName); - - if (q == null) - { - q = AMQQueueFactory.createAMQQueueImpl(id, queueName, true, owner, false, exclusive, _virtualHost, - FieldTable.convertToMap(arguments)); - _virtualHost.getQueueRegistry().registerQueue(q); - - if (alternateExchangeId != null) - { - Exchange altExchange = _exchangeRegistry.getExchange(alternateExchangeId); - if (altExchange == null) - { - _logger.error("Unknown exchange id " + alternateExchangeId + ", cannot set alternate exchange on queue with id " + id); - return; - } - q.setAlternateExchange(altExchange); - } - } - - CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_START(queueName, true)); - - //Record that we have a queue for recovery - _queueRecoveries.put(queueName, 0); - } - catch (AMQException e) - { - throw new RuntimeException("Error recovering queue uuid " + id + " name " + queueName, e); - } - } - - public void exchange(UUID id, String exchangeName, String type, boolean autoDelete) - { - try - { - Exchange exchange; - exchange = _exchangeRegistry.getExchange(exchangeName); - if (exchange == null) - { - exchange = _exchangeFactory.createExchange(id, exchangeName, type, true, autoDelete); - _exchangeRegistry.registerExchange(exchange); - } - } - catch (AMQException e) - { - throw new RuntimeException("Error recovering exchange uuid " + id + " name " + exchangeName, e); - } - } - public StoredMessageRecoveryHandler begin() { return this; @@ -174,21 +95,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa public void message(StoredMessage message) { - ServerMessage serverMessage; - switch(message.getMetaData().getType()) - { - case META_DATA_0_8: - serverMessage = new AMQMessage(message); - break; - case META_DATA_0_10: - serverMessage = new MessageTransferMessage(message, null); - break; - case META_DATA_1_0: - serverMessage = new Message_1_0(message); - break; - default: - throw new RuntimeException("Unknown message type retrieved from store " + message.getMetaData().getClass()); - } + ServerMessage serverMessage = message.getMetaData().getType().createMessage(message); _recoveredMessages.put(message.getMessageNumber(), serverMessage); _unusedMessages.put(message.getMessageNumber(), message); @@ -212,7 +119,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa } for(Transaction.Record record : enqueues) { - final AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(record.getQueue().getId()); + final AMQQueue queue = _virtualHost.getQueue(record.getQueue().getId()); if(queue != null) { final long messageId = record.getMessage().getMessageNumber(); @@ -272,7 +179,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa } for(Transaction.Record record : dequeues) { - final AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(record.getQueue().getId()); + final AMQQueue queue = _virtualHost.getQueue(record.getQueue().getId()); if(queue != null) { final long messageId = record.getMessage().getMessageNumber(); @@ -355,63 +262,13 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_COMPLETE(null, false)); } - private void binding(UUID bindingId, UUID exchangeId, UUID queueId, String bindingKey, ByteBuffer buf) - { - try - { - Exchange exchange = _exchangeRegistry.getExchange(exchangeId); - if (exchange == null) - { - _logger.error("Unknown exchange id " + exchangeId + ", cannot bind queue with id " + queueId); - return; - } - - AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(queueId); - if (queue == null) - { - _logger.error("Unknown queue id " + queueId + ", cannot be bound to exchange: " + exchange.getName()); - } - else - { - FieldTable argumentsFT = null; - if(buf != null) - { - try - { - argumentsFT = new FieldTable(new DataInputStream(new ByteBufferInputStream(buf)),buf.limit()); - } - catch (IOException e) - { - throw new RuntimeException("IOException should not be thrown here", e); - } - } - - Map<String, Object> argumentMap = FieldTable.convertToMap(argumentsFT); - - if(exchange.getBinding(bindingKey, queue, argumentMap) == null) - { - - _logger.info("Restoring binding: (Exchange: " + exchange.getNameShortString() + ", Queue: " + queue.getName() - + ", Routing Key: " + bindingKey + ", Arguments: " + argumentsFT + ")"); - - exchange.restoreBinding(bindingId, bindingKey, queue, argumentMap); - } - } - } - catch (AMQException e) - { - throw new RuntimeException(e); - } - - } - public void complete() { } public void queueEntry(final UUID queueId, long messageId) { - AMQQueue queue = _virtualHost.getQueueRegistry().getQueue(queueId); + AMQQueue queue = _virtualHost.getQueue(queueId); try { if(queue != null) @@ -486,107 +343,6 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa return this; } - @Override - public void configuredObject(UUID id, String type, Map<String, Object> attributes) - { - Map<UUID, Map<String, Object>> typeMap = _configuredObjects.get(type); - if(typeMap == null) - { - typeMap = new HashMap<UUID, Map<String, Object>>(); - _configuredObjects.put(type,typeMap); - } - typeMap.put(id, attributes); - } - - @Override - public void completeConfigurationRecovery() - { - Map<UUID, Map<String, Object>> exchangeObjects = - _configuredObjects.remove(org.apache.qpid.server.model.Exchange.class.getName()); - - if(exchangeObjects != null) - { - recoverExchanges(exchangeObjects); - } - - Map<UUID, Map<String, Object>> queueObjects = - _configuredObjects.remove(org.apache.qpid.server.model.Queue.class.getName()); - - if(queueObjects != null) - { - recoverQueues(queueObjects); - } - - - Map<UUID, Map<String, Object>> bindingObjects = - _configuredObjects.remove(Binding.class.getName()); - - if(bindingObjects != null) - { - recoverBindings(bindingObjects); - } - - - CurrentActor.get().message(_logSubject, ConfigStoreMessages.RECOVERY_COMPLETE()); - } - - private void recoverExchanges(Map<UUID, Map<String, Object>> exchangeObjects) - { - for(Map.Entry<UUID, Map<String,Object>> entry : exchangeObjects.entrySet()) - { - Map<String,Object> attributeMap = entry.getValue(); - String exchangeName = (String) attributeMap.get(org.apache.qpid.server.model.Exchange.NAME); - String exchangeType = (String) attributeMap.get(org.apache.qpid.server.model.Exchange.TYPE); - String lifeTimePolicy = (String) attributeMap.get(org.apache.qpid.server.model.Exchange.LIFETIME_POLICY); - boolean autoDelete = lifeTimePolicy == null - || LifetimePolicy.valueOf(lifeTimePolicy) == LifetimePolicy.AUTO_DELETE; - exchange(entry.getKey(), exchangeName, exchangeType, autoDelete); - } - } - - private void recoverQueues(Map<UUID, Map<String, Object>> queueObjects) - { - for(Map.Entry<UUID, Map<String,Object>> entry : queueObjects.entrySet()) - { - Map<String,Object> attributeMap = entry.getValue(); - - String queueName = (String) attributeMap.get(Queue.NAME); - String owner = (String) attributeMap.get(Queue.OWNER); - boolean exclusive = (Boolean) attributeMap.get(Queue.EXCLUSIVE); - UUID alternateExchangeId = attributeMap.get(Queue.ALTERNATE_EXCHANGE) == null ? null : UUID.fromString((String)attributeMap.get(Queue.ALTERNATE_EXCHANGE)); - @SuppressWarnings("unchecked") - Map<String, Object> queueArgumentsMap = (Map<String, Object>) attributeMap.get(Queue.ARGUMENTS); - FieldTable arguments = null; - if (queueArgumentsMap != null) - { - arguments = FieldTable.convertToFieldTable(queueArgumentsMap); - } - queue(entry.getKey(), queueName, owner, exclusive, arguments, alternateExchangeId); - } - } - - private void recoverBindings(Map<UUID, Map<String, Object>> bindingObjects) - { - for(Map.Entry<UUID, Map<String,Object>> entry : bindingObjects.entrySet()) - { - Map<String,Object> attributeMap = entry.getValue(); - UUID exchangeId = UUID.fromString((String)attributeMap.get(Binding.EXCHANGE)); - UUID queueId = UUID.fromString((String) attributeMap.get(Binding.QUEUE)); - String bindingName = (String) attributeMap.get(Binding.NAME); - - @SuppressWarnings("unchecked") - Map<String, Object> bindingArgumentsMap = (Map<String, Object>) attributeMap.get(Binding.ARGUMENTS); - FieldTable arguments = null; - if (bindingArgumentsMap != null) - { - arguments = FieldTable.convertToFieldTable(bindingArgumentsMap); - } - ByteBuffer argumentsBB = (arguments == null ? null : ByteBuffer.wrap(arguments.getDataAsBytes())); - - binding(entry.getKey(), exchangeId, queueId, bindingName, argumentsBB); - } - } - private static class DummyMessage implements EnqueableMessage { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/QueueExistsException.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/QueueExistsException.java new file mode 100644 index 0000000000..54f7d0d172 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/QueueExistsException.java @@ -0,0 +1,40 @@ +/* + * + * 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.plugins; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.queue.AMQQueue; + +public class QueueExistsException extends AMQException +{ + private final AMQQueue _existing; + + public QueueExistsException(String name, AMQQueue existing) + { + super(name); + _existing = existing; + } + + public AMQQueue getExistingQueue() + { + return _existing; + } +} diff --git a/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory b/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.DurableConfigurationStoreFactory new file mode 100644 index 0000000000..d183d91f18 --- /dev/null +++ b/qpid/java/broker/src/main/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.JsonFileConfigStoreFactory diff --git a/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PreferencesProviderFactory b/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PreferencesProviderFactory new file mode 100644 index 0000000000..9fe8379120 --- /dev/null +++ b/qpid/java/broker/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.PreferencesProviderFactory @@ -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.model.adapter.FileSystemPreferencesProviderFactory
\ No newline at end of file diff --git a/qpid/java/broker/src/main/resources/initial-config.json b/qpid/java/broker/src/main/resources/initial-config.json index 9bf7d71e8a..a203190c4b 100644 --- a/qpid/java/broker/src/main/resources/initial-config.json +++ b/qpid/java/broker/src/main/resources/initial-config.json @@ -26,7 +26,12 @@ "authenticationproviders" : [ { "name" : "passwordFile", "type" : "PlainPasswordFile", - "path" : "${qpid.home_dir}/etc/passwd" + "path" : "${qpid.home_dir}/etc/passwd", + "preferencesproviders" : [{ + "name": "fileSystemPreferences", + "type": "FileSystemPreferences", + "path" : "${qpid.work_dir}/preferences/passwordFile" + }] } ], "ports" : [ { "name" : "AMQP", diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java index 40b253a049..c22fcf4a14 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java @@ -240,11 +240,10 @@ public class BrokerOptionsTest extends QpidTestCase public void testDefaultWorkDirWithQpidWork() { - String qpidWork = "/test/value"; + String qpidWork = new File(File.separator + "test" + File.separator + "value").getAbsolutePath(); setTestSystemProperty("QPID_WORK", qpidWork); - String expectedPath = new File(qpidWork).getAbsolutePath(); - assertEquals (expectedPath, _options.getConfigProperties().get(BrokerOptions.QPID_WORK_DIR)); + assertEquals (qpidWork, _options.getConfigProperties().get(BrokerOptions.QPID_WORK_DIR)); } public void testDefaultWorkDirWithoutQpidWork() @@ -265,11 +264,10 @@ public class BrokerOptionsTest extends QpidTestCase public void testDefaultHomeDirWithQpidHome() { - String qpidHome = "/test/value"; + String qpidHome = new File(File.separator + "test" + File.separator + "value").getAbsolutePath(); setTestSystemProperty("QPID_HOME", qpidHome); - String expectedPath = new File(qpidHome).getAbsolutePath(); - assertEquals (expectedPath, _options.getConfigProperties().get(BrokerOptions.QPID_HOME_DIR)); + assertEquals (qpidHome, _options.getConfigProperties().get(BrokerOptions.QPID_HOME_DIR)); assertEquals("unexpected number of entries", 6, _options.getConfigProperties().keySet().size()); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java index de6d036f29..dc9ddf7b32 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java @@ -113,17 +113,17 @@ public class VirtualHostConfigurationTest extends QpidTestCase VirtualHost vhost = createVirtualHost(getName()); // Check that atest was a priority queue with 5 priorities - AMQQueue atest = vhost.getQueueRegistry().getQueue(new AMQShortString("atest")); + AMQQueue atest = vhost.getQueue("atest"); assertTrue(atest instanceof AMQPriorityQueue); assertEquals(5, ((AMQPriorityQueue) atest).getPriorities()); // Check that ptest was a priority queue with 10 priorities - AMQQueue ptest = vhost.getQueueRegistry().getQueue(new AMQShortString("ptest")); + AMQQueue ptest = vhost.getQueue("ptest"); assertTrue(ptest instanceof AMQPriorityQueue); assertEquals(10, ((AMQPriorityQueue) ptest).getPriorities()); // Check that ntest wasn't a priority queue - AMQQueue ntest = vhost.getQueueRegistry().getQueue(new AMQShortString("ntest")); + AMQQueue ntest = vhost.getQueue("ntest"); assertFalse(ntest instanceof AMQPriorityQueue); } @@ -146,13 +146,13 @@ public class VirtualHostConfigurationTest extends QpidTestCase VirtualHost vhost = createVirtualHost(getName()); // Check specifically configured values - AMQQueue aTest = vhost.getQueueRegistry().getQueue(new AMQShortString("atest")); + AMQQueue aTest = vhost.getQueue("atest"); assertEquals(4, aTest.getMaximumQueueDepth()); assertEquals(5, aTest.getMaximumMessageSize()); assertEquals(6, aTest.getMaximumMessageAge()); // Check default values - AMQQueue bTest = vhost.getQueueRegistry().getQueue(new AMQShortString("btest")); + AMQQueue bTest = vhost.getQueue("btest"); assertEquals(1, bTest.getMaximumQueueDepth()); assertEquals(2, bTest.getMaximumMessageSize()); assertEquals(3, bTest.getMaximumMessageAge()); @@ -214,10 +214,10 @@ public class VirtualHostConfigurationTest extends QpidTestCase assertFalse("c3p0 queue DLQ was configured as disabled", extra.getConfiguration().getQueueConfiguration("c3p0").isDeadLetterQueueEnabled()); // Get queues - AMQQueue biggles = test.getQueueRegistry().getQueue(new AMQShortString("biggles")); - AMQQueue beetle = test.getQueueRegistry().getQueue(new AMQShortString("beetle")); - AMQQueue r2d2 = extra.getQueueRegistry().getQueue(new AMQShortString("r2d2")); - AMQQueue c3p0 = extra.getQueueRegistry().getQueue(new AMQShortString("c3p0")); + AMQQueue biggles = test.getQueue("biggles"); + AMQQueue beetle = test.getQueue("beetle"); + AMQQueue r2d2 = extra.getQueue("r2d2"); + AMQQueue c3p0 = extra.getQueue("c3p0"); // Disabled specifically for this queue, overriding virtualhost setting assertNull("Biggles queue should not have alt exchange as DLQ should be configured as disabled: " + biggles.getAlternateExchange(), biggles.getAlternateExchange()); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecovererTest.java new file mode 100644 index 0000000000..eed54ef5bf --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/AuthenticationProviderRecovererTest.java @@ -0,0 +1,143 @@ +/* + * + * 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 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 org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.server.model.adapter.PreferencesProviderCreator; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +public class AuthenticationProviderRecovererTest extends QpidTestCase +{ + private Broker _broker; + private AuthenticationProviderRecoverer _recoverer; + private ConfigurationEntryStore _configurationStore; + private PreferencesProviderCreator _preferencesProviderCreator; + + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _broker = BrokerTestHelper.createBrokerMock(); + _preferencesProviderCreator = new PreferencesProviderCreator(); + QpidServiceLoader<AuthenticationManagerFactory> serviceLoader = new QpidServiceLoader<AuthenticationManagerFactory>(); + AuthenticationProviderFactory authenticationProviderFactory = new AuthenticationProviderFactory(serviceLoader, _preferencesProviderCreator); + StoreConfigurationChangeListener storeChangeListener = mock(StoreConfigurationChangeListener.class); + _recoverer = new AuthenticationProviderRecoverer(authenticationProviderFactory, storeChangeListener); + _configurationStore = mock(ConfigurationEntryStore.class); + } + + public void tearDown() throws Exception + { + try + { + BrokerTestHelper.tearDown(); + } + finally + { + super.tearDown(); + } + } + + public void testRecoverAuthenticationProviderWithPreferencesProvider() + { + File authenticationProviderFile = TestFileUtils.createTempFile(this, "test-authenticator.txt", "test_user:test_user"); + try + { + Map<String, Object> authenticationAttributes = new HashMap<String, Object>(); + authenticationAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, + PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + authenticationAttributes.put(AuthenticationProvider.NAME, "test-authenticator"); + authenticationAttributes.put(PlainPasswordFileAuthenticationManagerFactory.ATTRIBUTE_PATH, + authenticationProviderFile.getAbsolutePath()); + UUID authenticationId = UUID.randomUUID(); + + final PreferencesProviderRecoverer preferencesRecoverer = new PreferencesProviderRecoverer(_preferencesProviderCreator); + RecovererProvider recovererProvider = new RecovererProvider() + { + @Override + public ConfiguredObjectRecoverer<? extends ConfiguredObject> getRecoverer(String type) + { + return preferencesRecoverer; + } + }; + + Map<String, Object> preferencesAttributes = new HashMap<String, Object>(); + UUID preferencesId = UUID.randomUUID(); + preferencesAttributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.class); + preferencesAttributes.put(PreferencesProvider.NAME, "test-provider"); + File file = TestFileUtils.createTempFile(this, ".prefs.json", + "{\"test_user\":{\"pref1\": \"pref1Value\", \"pref2\": 1.0} }"); + preferencesAttributes.put(FileSystemPreferencesProvider.PATH, file.getAbsolutePath()); + ConfigurationEntry preferencesEntry = new ConfigurationEntry(preferencesId, PreferencesProvider.class.getSimpleName(), + preferencesAttributes, Collections.<UUID> emptySet(), _configurationStore); + when(_configurationStore.getEntry(preferencesId)).thenReturn(preferencesEntry); + + ConfigurationEntry authenticationProviderEntry = new ConfigurationEntry(authenticationId, + AuthenticationProvider.class.getSimpleName(), authenticationAttributes, Collections.singleton(preferencesId), + _configurationStore); + try + { + AuthenticationProvider authenticationProvider = _recoverer.create(recovererProvider, authenticationProviderEntry, + _broker); + assertNotNull("Authentication provider was not recovered", authenticationProvider); + assertEquals("Unexpected name", "test-authenticator", authenticationProvider.getName()); + assertEquals("Unexpected id", authenticationId, authenticationProvider.getId()); + PreferencesProvider preferencesProvider = authenticationProvider.getPreferencesProvider(); + assertNotNull("Preferences provider was not recovered", preferencesProvider); + assertEquals("Unexpected path", file.getAbsolutePath(), + preferencesProvider.getAttribute(FileSystemPreferencesProvider.PATH)); + } + finally + { + file.delete(); + } + } + finally + { + authenticationProviderFile.delete(); + } + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java index 589f0fc5af..e6db5af222 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/BrokerRecovererTest.java @@ -55,6 +55,8 @@ import org.apache.qpid.server.model.adapter.AccessControlProviderFactory; import org.apache.qpid.server.model.adapter.AuthenticationProviderFactory; import org.apache.qpid.server.model.adapter.GroupProviderFactory; import org.apache.qpid.server.model.adapter.PortFactory; +import org.apache.qpid.server.model.adapter.PreferencesProviderCreator; +import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; @@ -76,7 +78,9 @@ public class BrokerRecovererTest extends TestCase super.setUp(); _brokerRecoverer = new BrokerRecoverer(mock(AuthenticationProviderFactory.class), mock(GroupProviderFactory.class), mock(AccessControlProviderFactory.class), mock(PortFactory.class), - mock(StatisticsGatherer.class), mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class), mock(BrokerOptions.class)); + mock(PreferencesProviderCreator.class), + mock(StatisticsGatherer.class), mock(VirtualHostRegistry.class), mock(LogRecorder.class), mock(RootMessageLogger.class), mock(TaskExecutor.class), mock(BrokerOptions.class), + mock(StoreConfigurationChangeListener.class)); when(_brokerEntry.getId()).thenReturn(_brokerId); when(_brokerEntry.getChildren()).thenReturn(_brokerEntryChildren); when(_brokerEntry.getAttributes()).thenReturn(Collections.<String, Object>singletonMap(Broker.MODEL_VERSION, Model.MODEL_VERSION)); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java index b958ba1f56..9e2f2fcf32 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/DefaultRecovererProviderTest.java @@ -35,6 +35,7 @@ import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; @@ -55,7 +56,9 @@ public class DefaultRecovererProviderTest extends TestCase RootMessageLogger rootMessageLogger = mock(RootMessageLogger.class); TaskExecutor taskExecutor = mock(TaskExecutor.class); - DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, logRecorder, rootMessageLogger, taskExecutor, mock(BrokerOptions.class)); + DefaultRecovererProvider provider = new DefaultRecovererProvider(statisticsGatherer, virtualHostRegistry, + logRecorder, rootMessageLogger, taskExecutor, mock(BrokerOptions.class), + mock(StoreConfigurationChangeListener.class)); for (String configuredObjectType : supportedTypes) { ConfiguredObjectRecoverer<?> recovever = provider.getRecoverer(configuredObjectType); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecovererTest.java new file mode 100644 index 0000000000..8c316b5f53 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/PreferencesProviderRecovererTest.java @@ -0,0 +1,96 @@ +/* + * + * 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 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 org.apache.qpid.server.configuration.ConfigurationEntry; +import org.apache.qpid.server.configuration.ConfigurationEntryStore; +import org.apache.qpid.server.configuration.RecovererProvider; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.server.model.adapter.PreferencesProviderCreator; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +public class PreferencesProviderRecovererTest extends QpidTestCase +{ + private AuthenticationProvider _authenticationProvider; + private Broker _broker; + + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _authenticationProvider = mock(AuthenticationProvider.class); + _broker = BrokerTestHelper.createBrokerMock(); + when(_authenticationProvider.getParent(Broker.class)).thenReturn(_broker); + } + + public void tearDown() throws Exception + { + try + { + BrokerTestHelper.tearDown(); + } + finally + { + super.tearDown(); + } + } + + public void testRecoverFileSystemPreferencesProvider() + { + PreferencesProviderRecoverer recoverer = new PreferencesProviderRecoverer(new PreferencesProviderCreator()); + + Map<String, Object> attributes = new HashMap<String, Object>(); + UUID id = UUID.randomUUID(); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.class); + attributes.put(PreferencesProvider.NAME, "test-provider"); + File file = TestFileUtils.createTempFile(this, ".prefs.json", "{\"test_user\":{\"pref1\": \"pref1Value\", \"pref2\": 1.0} }"); + try + { + attributes.put(FileSystemPreferencesProvider.PATH, file.getAbsolutePath()); + ConfigurationEntry entry = new ConfigurationEntry(id, PreferencesProvider.class.getSimpleName(), attributes, Collections.<UUID>emptySet(), mock(ConfigurationEntryStore.class)); + PreferencesProvider provider = recoverer.create(mock(RecovererProvider.class), entry, _authenticationProvider); + assertNotNull("Preferences provider was not recovered", provider); + assertEquals("Unexpected name", "test-provider", provider.getName()); + assertEquals("Unexpected id", id, provider.getId()); + assertEquals("Unexpected path", file.getAbsolutePath(), provider.getAttribute(FileSystemPreferencesProvider.PATH)); + } + finally + { + file.delete(); + } + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java index 042abca9c4..f00d12b77d 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/configuration/startup/VirtualHostRecovererTest.java @@ -78,7 +78,7 @@ public class VirtualHostRecovererTest extends TestCase attributes.put(VirtualHost.NAME, getName()); attributes.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); - attributes.put(VirtualHost.STORE_TYPE, "MEMORY"); + attributes.put(VirtualHost.STORE_TYPE, "TESTMEMORY"); when(entry.getAttributes()).thenReturn(attributes); VirtualHost host = recoverer.create(null, entry, parent); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java index cf6e98d6ca..86ae3e6e9c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java @@ -95,7 +95,7 @@ public class DefaultExchangeFactoryTest extends QpidTestCase } catch (IllegalStateException e) { - assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _directExchangeType.getName(), e.getMessage()); + assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _directExchangeType.getType(), e.getMessage()); } } @@ -112,7 +112,7 @@ public class DefaultExchangeFactoryTest extends QpidTestCase } catch (IllegalStateException e) { - assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _topicExchangeType.getName(), e.getMessage()); + assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _topicExchangeType.getType(), e.getMessage()); } } @@ -129,7 +129,7 @@ public class DefaultExchangeFactoryTest extends QpidTestCase } catch (IllegalStateException e) { - assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _fanoutExchangeType.getName(), e.getMessage()); + assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _fanoutExchangeType.getType(), e.getMessage()); } } @@ -146,7 +146,7 @@ public class DefaultExchangeFactoryTest extends QpidTestCase } catch (IllegalStateException e) { - assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _headersExchangeType.getName(), e.getMessage()); + assertEquals("Unexpected exception message", "Did not find expected exchange type: " + _headersExchangeType.getType(), e.getMessage()); } } @@ -163,7 +163,7 @@ public class DefaultExchangeFactoryTest extends QpidTestCase catch (IllegalStateException e) { assertTrue( "Unexpected exception message", e.getMessage().contains("ExchangeType with type name '" - + _directExchangeType.getName() + "' is already registered using class '" + + _directExchangeType.getType() + "' is already registered using class '" + DirectExchangeType.class.getName())); } } @@ -175,24 +175,18 @@ public class DefaultExchangeFactoryTest extends QpidTestCase @Override public String getType() { - return getName().toString(); + return "my-custom-exchange"; } @Override - public AMQShortString getName() - { - return new AMQShortString("my-custom-exchange"); - } - - @Override - public Exchange newInstance(UUID id, VirtualHost host, AMQShortString name, boolean durable, + public Exchange newInstance(UUID id, VirtualHost host, String name, boolean durable, boolean autoDelete) throws AMQException { return null; } @Override - public AMQShortString getDefaultExchangeName() + public String getDefaultExchangeName() { return null; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java index f608bc8cb0..7335d43b2e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java @@ -22,11 +22,13 @@ package org.apache.qpid.server.exchange; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anySet; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; import junit.framework.TestCase; @@ -61,22 +63,22 @@ public class FanoutExchangeTest extends TestCase _virtualHost = mock(VirtualHost.class); SecurityManager securityManager = mock(SecurityManager.class); when(_virtualHost.getSecurityManager()).thenReturn(securityManager); - when(securityManager.authoriseBind(any(Exchange.class), any(AMQQueue.class), any(AMQShortString.class))).thenReturn(true); - when(securityManager.authoriseUnbind(any(Exchange.class), any(AMQShortString.class), any(AMQQueue.class))).thenReturn(true); + when(securityManager.authoriseBind(any(Exchange.class), any(AMQQueue.class), anyString())).thenReturn(true); + when(securityManager.authoriseUnbind(any(Exchange.class), anyString(), any(AMQQueue.class))).thenReturn(true); - _exchange.initialise(UUID.randomUUID(), _virtualHost, AMQShortString.valueOf("test"), false, false); + _exchange.initialise(UUID.randomUUID(), _virtualHost, "test", false, false); } - public void testIsBoundAMQShortStringFieldTableAMQQueueWhenQueueIsNull() + public void testIsBoundStringMapAMQQueueWhenQueueIsNull() { assertFalse("calling isBound(AMQShortString,FieldTable,AMQQueue) with null queue should return false", - _exchange.isBound((AMQShortString) null, (FieldTable) null, (AMQQueue) null)); + _exchange.isBound((String) null, (Map) null, (AMQQueue) null)); } - public void testIsBoundAMQShortStringAMQQueueWhenQueueIsNull() + public void testIsBoundStringAMQQueueWhenQueueIsNull() { assertFalse("calling isBound(AMQShortString,AMQQueue) with null queue should return false", - _exchange.isBound((AMQShortString) null, (AMQQueue) null)); + _exchange.isBound((String) null, (AMQQueue) null)); } public void testIsBoundAMQQueueWhenQueueIsNull() @@ -84,18 +86,18 @@ public class FanoutExchangeTest extends TestCase assertFalse("calling isBound(AMQQueue) with null queue should return false", _exchange.isBound((AMQQueue) null)); } - public void testIsBoundAMQShortStringFieldTableAMQQueue() throws AMQSecurityException, AMQInternalException + public void testIsBoundStringMapAMQQueue() throws AMQSecurityException, AMQInternalException { AMQQueue queue = bindQueue(); assertTrue("Should return true for a bound queue", - _exchange.isBound(new AMQShortString("matters"), (FieldTable) null, queue)); + _exchange.isBound("matters", null, queue)); } - public void testIsBoundAMQShortStringAMQQueue() throws AMQSecurityException, AMQInternalException + public void testIsBoundStringAMQQueue() throws AMQSecurityException, AMQInternalException { AMQQueue queue = bindQueue(); assertTrue("Should return true for a bound queue", - _exchange.isBound(new AMQShortString("matters"), queue)); + _exchange.isBound("matters", queue)); } public void testIsBoundAMQQueue() throws AMQSecurityException, AMQInternalException diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java index d76c7d1128..0f1ab65244 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java @@ -65,10 +65,10 @@ public class HeadersExchangeTest extends TestCase _virtualHost = mock(VirtualHost.class); SecurityManager securityManager = mock(SecurityManager.class); when(_virtualHost.getSecurityManager()).thenReturn(securityManager); - when(securityManager.authoriseBind(any(Exchange.class), any(AMQQueue.class), any(AMQShortString.class))).thenReturn(true); - when(securityManager.authoriseUnbind(any(Exchange.class), any(AMQShortString.class), any(AMQQueue.class))).thenReturn(true); + when(securityManager.authoriseBind(any(Exchange.class), any(AMQQueue.class), anyString())).thenReturn(true); + when(securityManager.authoriseUnbind(any(Exchange.class), anyString(), any(AMQQueue.class))).thenReturn(true); - _exchange.initialise(UUID.randomUUID(), _virtualHost, AMQShortString.valueOf("test"), false, false); + _exchange.initialise(UUID.randomUUID(), _virtualHost, "test", false, false); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java index f1bf632235..a84f5e1ecb 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java @@ -20,33 +20,31 @@ */ package org.apache.qpid.server.exchange; +import java.util.List; import junit.framework.Assert; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.BaseQueue; -import org.apache.qpid.server.queue.IncomingMessage; -import org.apache.qpid.server.store.MemoryMessageStore; -import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class TopicExchangeTest extends QpidTestCase { private TopicExchange _exchange; private VirtualHost _vhost; - private MessageStore _store; @Override @@ -56,7 +54,6 @@ public class TopicExchangeTest extends QpidTestCase BrokerTestHelper.setUp(); _exchange = new TopicExchange(); _vhost = BrokerTestHelper.createVirtualHost(getName()); - _store = new MemoryMessageStore(); } @Override @@ -78,37 +75,33 @@ public class TopicExchangeTest extends QpidTestCase public void testNoRoute() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.*.#.b",queue, _exchange, null)); - IncomingMessage message = createMessage("a.b"); - routeMessage(message); + routeMessage("a.b", 0l); Assert.assertEquals(0, queue.getMessageCount()); } public void testDirectMatch() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.b",queue, _exchange, null)); - IncomingMessage message = createMessage("a.b"); - - routeMessage(message); + routeMessage("a.b",0l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 0l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - - message = createMessage("a.c"); - - int queueCount = routeMessage(message); + int queueCount = routeMessage("a.c",1l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); @@ -117,38 +110,30 @@ public class TopicExchangeTest extends QpidTestCase public void testStarMatch() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.*",queue, _exchange, null)); - IncomingMessage message = createMessage("a.b"); - - routeMessage(message); + routeMessage("a.b",0l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 0l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("a.c"); - - int queueCount = routeMessage(message); + routeMessage("a.c",1l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 1l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - - message = createMessage("a"); - - - queueCount = routeMessage(message); + int queueCount = routeMessage("a",2l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); @@ -156,61 +141,49 @@ public class TopicExchangeTest extends QpidTestCase public void testHashMatch() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, false, null); _exchange.registerQueue(new Binding(null, "a.#",queue, _exchange, null)); - IncomingMessage message = createMessage("a.b.c"); - - int queueCount = routeMessage(message); + routeMessage("a.b.c",0l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 0l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - - message = createMessage("a.b"); - - queueCount = routeMessage(message); + routeMessage("a.b",1l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 1l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("a.c"); - - queueCount = routeMessage(message); + routeMessage("a.c",2l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 2l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("a"); - - queueCount = routeMessage(message); + routeMessage("a",3l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 3l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("b"); - - - queueCount = routeMessage(message); + int queueCount = routeMessage("b", 4l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); @@ -219,28 +192,24 @@ public class TopicExchangeTest extends QpidTestCase public void testMidHash() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.*.#.b",queue, _exchange, null)); - - IncomingMessage message = createMessage("a.c.d.b"); - - routeMessage(message); + routeMessage("a.c.d.b",0l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 0l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("a.c.b"); - - routeMessage(message); + routeMessage("a.c.b",1l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 1l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); @@ -249,43 +218,36 @@ public class TopicExchangeTest extends QpidTestCase public void testMatchafterHash() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.*.#.b.c",queue, _exchange, null)); - IncomingMessage message = createMessage("a.c.b.b"); - - int queueCount = routeMessage(message); + int queueCount = routeMessage("a.c.b.b",0l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("a.a.b.c"); - - routeMessage(message); + routeMessage("a.a.b.c",1l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 1l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("a.b.c.b"); - - queueCount = routeMessage(message); + queueCount = routeMessage("a.b.c.b",2l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("a.b.c.b.c"); - - routeMessage(message); + routeMessage("a.b.c.b.c",3l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 3l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); @@ -295,25 +257,20 @@ public class TopicExchangeTest extends QpidTestCase public void testHashAfterHash() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.*.#.b.c.#.d",queue, _exchange, null)); - - IncomingMessage message = createMessage("a.c.b.b.c"); - - int queueCount = routeMessage(message); + int queueCount = routeMessage("a.c.b.b.c",0l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); - - message = createMessage("a.a.b.c.d"); - - routeMessage(message); + routeMessage("a.a.b.c.d",1l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 1l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); @@ -322,24 +279,20 @@ public class TopicExchangeTest extends QpidTestCase public void testHashHash() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.#.*.#.d",queue, _exchange, null)); - - IncomingMessage message = createMessage("a.c.b.b.c"); - - int queueCount = routeMessage(message); + int queueCount = routeMessage("a.c.b.b.c",0l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); - message = createMessage("a.a.b.c.d"); - - routeMessage(message); + routeMessage("a.a.b.c.d",1l); Assert.assertEquals(1, queue.getMessageCount()); - Assert.assertEquals("Wrong message recevied", (Object) message.getMessageNumber(), queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); + Assert.assertEquals("Wrong message received", 1l, queue.getMessagesOnTheQueue().get(0).getMessage().getMessageNumber()); queue.deleteMessageFromTop(); Assert.assertEquals(0, queue.getMessageCount()); @@ -348,43 +301,43 @@ public class TopicExchangeTest extends QpidTestCase public void testSubMatchFails() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.b.c.d",queue, _exchange, null)); - - IncomingMessage message = createMessage("a.b.c"); - - int queueCount = routeMessage(message); + int queueCount = routeMessage("a.b.c",0l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); } - private int routeMessage(final IncomingMessage message) - throws AMQException + private int routeMessage(String routingKey, long messageNumber) throws AMQException { - MessageMetaData mmd = message.headersReceived(System.currentTimeMillis()); - message.setStoredMessage(_store.addMessage(mmd)); - - message.enqueue(_exchange.route(message)); - AMQMessage msg = new AMQMessage(message.getStoredMessage()); - for(BaseQueue q : message.getDestinationQueues()) + InboundMessage inboundMessage = mock(InboundMessage.class); + when(inboundMessage.getRoutingKey()).thenReturn(routingKey); + List<? extends BaseQueue> queues = _exchange.route(inboundMessage); + ServerMessage message = mock(ServerMessage.class); + MessageReference ref = mock(MessageReference.class); + when(ref.getMessage()).thenReturn(message); + when(message.newReference()).thenReturn(ref); + when(message.getMessageNumber()).thenReturn(messageNumber); + for(BaseQueue q : queues) { - q.enqueue(msg); + q.enqueue(message); } - return message.getDestinationQueues().size(); + + return queues.size(); } public void testMoreRouting() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.b",queue, _exchange, null)); - IncomingMessage message = createMessage("a.b.c"); - - int queueCount = routeMessage(message); + int queueCount = routeMessage("a.b.c",0l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); @@ -393,66 +346,16 @@ public class TopicExchangeTest extends QpidTestCase public void testMoreQueue() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); + AMQQueue queue = _vhost.createQueue(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, + false, null); _exchange.registerQueue(new Binding(null, "a.b",queue, _exchange, null)); - IncomingMessage message = createMessage("a"); - - int queueCount = routeMessage(message); + int queueCount = routeMessage("a",0l); Assert.assertEquals("Message should not route to any queues", 0, queueCount); Assert.assertEquals(0, queue.getMessageCount()); } - private IncomingMessage createMessage(String s) throws AMQException - { - MessagePublishInfo info = new PublishInfo(new AMQShortString(s)); - - IncomingMessage message = new IncomingMessage(info); - final ContentHeaderBody chb = new ContentHeaderBody(); - BasicContentHeaderProperties props = new BasicContentHeaderProperties(); - chb.setProperties(props); - message.setContentHeaderBody(chb); - - - return message; - } - - - class PublishInfo implements MessagePublishInfo - { - private AMQShortString _routingkey; - - PublishInfo(AMQShortString routingkey) - { - _routingkey = routingkey; - } - - public AMQShortString getExchange() - { - return null; - } - - public void setExchange(AMQShortString exchange) - { - - } - - public boolean isImmediate() - { - return false; - } - - public boolean isMandatory() - { - return true; - } - - public AMQShortString getRoutingKey() - { - return _routingkey; - } - } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java index e2472dbf01..41b42fac78 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/AMQPChannelActorTest.java @@ -20,7 +20,7 @@ */ package org.apache.qpid.server.logging.actors; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.util.BrokerTestHelper; import java.util.List; @@ -45,7 +45,7 @@ public class AMQPChannelActorTest extends BaseConnectionActorTestCase private void setUpNow() throws Exception { super.setUp(); - AMQChannel channel = BrokerTestHelper.createChannel(1, getSession()); + AMQSessionModel channel = BrokerTestHelper.createSession(1, getConnection()); setAmqpActor(new AMQPChannelActor(channel, getRootLogger())); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java index 09dd48e4d3..1cb6474e41 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/BaseConnectionActorTestCase.java @@ -20,31 +20,43 @@ */ package org.apache.qpid.server.logging.actors; -import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.virtualhost.VirtualHost; public class BaseConnectionActorTestCase extends BaseActorTestCase { - private AMQProtocolSession _session; + private AMQConnectionModel _session; + private VirtualHost _virtualHost; @Override public void setUp() throws Exception { super.setUp(); BrokerTestHelper.setUp(); - _session = BrokerTestHelper.createSession(); - + _session = BrokerTestHelper.createConnection(); + _virtualHost = BrokerTestHelper.createVirtualHost("test"); setAmqpActor(new AMQPConnectionActor(_session, getRootLogger())); } + public VirtualHost getVirtualHost() + { + return _virtualHost; + } + @Override public void tearDown() throws Exception { try { + if(_virtualHost != null) + { + _virtualHost.close(); + } if (_session != null) { - _session.getVirtualHost().close(); + _session.close(AMQConstant.CONNECTION_FORCED, ""); } } finally @@ -54,7 +66,7 @@ public class BaseConnectionActorTestCase extends BaseActorTestCase } } - public AMQProtocolSession getSession() + public AMQConnectionModel getConnection() { return _session; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java index 8ea5510ce6..701ccaab47 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/CurrentActorTest.java @@ -23,9 +23,10 @@ package org.apache.qpid.server.logging.actors; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.AMQException; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.NullRootMessageLogger; +import org.apache.qpid.server.util.BrokerTestHelper; /** * Test : CurrentActorTest @@ -71,7 +72,7 @@ public class CurrentActorTest extends BaseConnectionActorTestCase public void testLIFO() throws AMQException, ConfigurationException { assertTrue("Unexpected actor: " + CurrentActor.get(), CurrentActor.get() instanceof TestLogActor); - AMQPConnectionActor connectionActor = new AMQPConnectionActor(getSession(), + AMQPConnectionActor connectionActor = new AMQPConnectionActor(getConnection(), new NullRootMessageLogger()); /* @@ -98,7 +99,7 @@ public class CurrentActorTest extends BaseConnectionActorTestCase * */ - AMQChannel channel = new AMQChannel(getSession(), 1, getSession().getVirtualHost().getMessageStore()); + AMQSessionModel channel = BrokerTestHelper.createSession(1, getConnection()); AMQPChannelActor channelActor = new AMQPChannelActor(channel, new NullRootMessageLogger()); @@ -214,7 +215,7 @@ public class CurrentActorTest extends BaseConnectionActorTestCase { LogActor defaultActor = CurrentActor.get(); - AMQPConnectionActor actor = new AMQPConnectionActor(getSession(), + AMQPConnectionActor actor = new AMQPConnectionActor(getConnection(), new NullRootMessageLogger()); CurrentActor.set(actor); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/QueueActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/QueueActorTest.java index 2dc44c58ce..55153b7389 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/QueueActorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/QueueActorTest.java @@ -31,7 +31,7 @@ public class QueueActorTest extends BaseConnectionActorTestCase public void setUp() throws Exception { super.setUp(); - setAmqpActor(new QueueActor(BrokerTestHelper.createQueue(getName(), getSession().getVirtualHost()), getRootLogger())); + setAmqpActor(new QueueActor(BrokerTestHelper.createQueue(getName(), getVirtualHost()), getRootLogger())); } /** diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java index 58fca488c4..92915e7092 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/actors/SubscriptionActorTest.java @@ -44,7 +44,7 @@ public class SubscriptionActorTest extends BaseConnectionActorTestCase MockSubscription mockSubscription = new MockSubscription(); - mockSubscription.setQueue(BrokerTestHelper.createQueue(getName(), getSession().getVirtualHost()), false); + mockSubscription.setQueue(BrokerTestHelper.createQueue(getName(), getVirtualHost()), false); setAmqpActor(new SubscriptionActor(getRootLogger(), mockSubscription)); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java index 1cb4da55c3..f1452b8b88 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java @@ -34,8 +34,8 @@ public class ExchangeMessagesTest extends AbstractTestMessages { Exchange exchange = BrokerTestHelper.createExchange("test"); - String type = exchange.getTypeShortString().toString(); - String name = exchange.getNameShortString().toString(); + String type = exchange.getTypeName(); + String name = exchange.getName(); _logMessage = ExchangeMessages.CREATED(type, name, false); List<Object> log = performLog(); @@ -49,8 +49,8 @@ public class ExchangeMessagesTest extends AbstractTestMessages { Exchange exchange = BrokerTestHelper.createExchange("test"); - String type = exchange.getTypeShortString().toString(); - String name = exchange.getNameShortString().toString(); + String type = exchange.getTypeName(); + String name = exchange.getName(); _logMessage = ExchangeMessages.CREATED(type, name, true); List<Object> log = performLog(); @@ -74,7 +74,7 @@ public class ExchangeMessagesTest extends AbstractTestMessages { Exchange exchange = BrokerTestHelper.createExchange("test"); - final String name = exchange.getNameShortString().toString(); + final String name = exchange.getName(); final String routingKey = "routingKey"; _logMessage = ExchangeMessages.DISCARDMSG(name, routingKey); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/AbstractTestLogSubject.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/AbstractTestLogSubject.java index 193e8a490d..cd8f13d52e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/AbstractTestLogSubject.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/AbstractTestLogSubject.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogMessage; @@ -113,7 +112,7 @@ public abstract class AbstractTestLogSubject extends QpidTestCase // This should return us MockProtocolSessionUser@null/test String connectionSlice = getSlice("con:" + connectionID, message); - assertNotNull("Unable to find connection 'con:" + connectionID + "'", + assertNotNull("Unable to find connection 'con:" + connectionID + "' in '"+message+"'", connectionSlice); // Exract the userName @@ -131,7 +130,7 @@ public abstract class AbstractTestLogSubject extends QpidTestCase // We will have three sections assertEquals("Unable to split IP from rest of Connection:" - + userNameParts[1], 3, ipParts.length); + + userNameParts[1] + " in '"+message+"'", 3, ipParts.length); // We need to skip the first '/' split will be empty so validate 1 as IP assertEquals("IP not as expected", ipString, ipParts[1]); @@ -146,14 +145,14 @@ public abstract class AbstractTestLogSubject extends QpidTestCase * @param message The message to check * @param routingKey The routing key to check against */ - protected void verifyRoutingKey(String message, AMQShortString routingKey) + protected void verifyRoutingKey(String message, String routingKey) { String routingKeySlice = getSlice("rk", message); - assertNotNull("Routing Key not found:" + message, routingKey); + assertNotNull("Routing Key not found:" + message, routingKeySlice); assertEquals("Routing key not correct", - routingKey.toString(), routingKeySlice); + routingKey, routingKeySlice); } /** @@ -169,7 +168,7 @@ public abstract class AbstractTestLogSubject extends QpidTestCase assertNotNull("Queue not found:" + message, queueSlice); assertEquals("Queue name not correct", - queue.getNameShortString().toString(), queueSlice); + queue.getName(), queueSlice); } /** @@ -191,10 +190,10 @@ public abstract class AbstractTestLogSubject extends QpidTestCase exchangeParts.length); assertEquals("Exchange type not correct", - exchange.getTypeShortString().toString(), exchangeParts[0]); + exchange.getType().getType(), exchangeParts[0]); assertEquals("Exchange name not correct", - exchange.getNameShortString().toString(), exchangeParts[1]); + exchange.getName(), exchangeParts[1]); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java index e63744af9a..e52ead451e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java @@ -34,7 +34,7 @@ public class BindingLogSubjectTest extends AbstractTestLogSubject { private AMQQueue _queue; - private AMQShortString _routingKey; + private String _routingKey; private Exchange _exchange; private VirtualHost _testVhost; @@ -44,12 +44,12 @@ public class BindingLogSubjectTest extends AbstractTestLogSubject super.setUp(); _testVhost = BrokerTestHelper.createVirtualHost("test"); - _routingKey = new AMQShortString("RoutingKey"); + _routingKey = "RoutingKey"; _exchange = _testVhost.getExchange("amq.direct"); _queue = new MockAMQQueue("BindingLogSubjectTest"); ((MockAMQQueue) _queue).setVirtualHost(_testVhost); - _subject = new BindingLogSubject(String.valueOf(_routingKey), _exchange, _queue); + _subject = new BindingLogSubject(_routingKey, _exchange, _queue); } @Override diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java index d75e033739..a3d96c6d12 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ChannelLogSubjectTest.java @@ -20,7 +20,10 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.AMQSessionModel; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * Validate ChannelLogSubjects are logged as expected @@ -34,10 +37,10 @@ public class ChannelLogSubjectTest extends ConnectionLogSubjectTest { super.setUp(); - - AMQChannel channel = new AMQChannel(getSession(), _channelID, getSession().getVirtualHost().getMessageStore()); - - _subject = new ChannelLogSubject(channel); + AMQSessionModel session = mock(AMQSessionModel.class); + when(session.getConnectionModel()).thenReturn(getConnection()); + when(session.getChannelId()).thenReturn(_channelID); + _subject = new ChannelLogSubject(session); } /** diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java index 7dc4c443ba..e9a9317102 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubjectTest.java @@ -20,8 +20,10 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.protocol.AMQConnectionModel; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; /** * Validate ConnectionLogSubjects are logged as expected @@ -29,25 +31,24 @@ import org.apache.qpid.server.util.BrokerTestHelper; public class ConnectionLogSubjectTest extends AbstractTestLogSubject { - private InternalTestProtocolSession _session; + private static final long CONNECTION_ID = 456l; + private static final String USER = "InternalTestProtocolSession"; + private static final String IP_STRING = "127.0.0.1:1"; + private static final String VHOST = "test"; + + private AMQConnectionModel _connection; @Override public void setUp() throws Exception { super.setUp(); - _session = BrokerTestHelper.createSession("test"); - _subject = new ConnectionLogSubject(_session); - } - - @Override - public void tearDown() throws Exception - { - if (_session != null) - { - _session.getVirtualHost().close(); - } - super.tearDown(); + _connection = mock(AMQConnectionModel.class); + when(_connection.getConnectionId()).thenReturn(CONNECTION_ID); + when(_connection.getPrincipalAsString()).thenReturn(USER); + when(_connection.getRemoteAddressString()).thenReturn("/"+IP_STRING); + when(_connection.getVirtualHostName()).thenReturn(VHOST); + _subject = new ConnectionLogSubject(_connection); } /** @@ -57,12 +58,12 @@ public class ConnectionLogSubjectTest extends AbstractTestLogSubject */ protected void validateLogStatement(String message) { - verifyConnection(_session.getSessionID(), "InternalTestProtocolSession", "127.0.0.1:1", "test", message); + verifyConnection(CONNECTION_ID, USER, IP_STRING, VHOST, message); } - public InternalTestProtocolSession getSession() + public AMQConnectionModel getConnection() { - return _session; + return _connection; } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java index 65fd249d03..3d43ef0f44 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/MessageStoreLogSubjectTest.java @@ -37,7 +37,8 @@ public class MessageStoreLogSubjectTest extends AbstractTestLogSubject _testVhost = BrokerTestHelper.createVirtualHost("test"); - _subject = new MessageStoreLogSubject(_testVhost, _testVhost.getMessageStore().getClass().getSimpleName()); + _subject = new MessageStoreLogSubject(_testVhost.getName(), + _testVhost.getMessageStore().getClass().getSimpleName()); } @Override diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java index 153d01f355..b9efac1ae8 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/subjects/SubscriptionLogSubjectTest.java @@ -20,27 +20,24 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.flow.LimitlessCreditManager; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionFactory; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + /** * Validate SubscriptionLogSubjects are logged as expected */ public class SubscriptionLogSubjectTest extends AbstractTestLogSubject { + private static final long SUBSCRIPTION_ID = 1; private AMQQueue _queue; private VirtualHost _testVhost; - private int _channelID = 1; private Subscription _subscription; @Override @@ -48,23 +45,14 @@ public class SubscriptionLogSubjectTest extends AbstractTestLogSubject { super.setUp(); - InternalTestProtocolSession session = BrokerTestHelper.createSession(); - _testVhost = session.getVirtualHost(); + _testVhost = BrokerTestHelper.createVirtualHost("test"); _queue = new MockAMQQueue("SubscriptionLogSubjectTest"); ((MockAMQQueue) _queue).setVirtualHost(_testVhost); - AMQChannel channel = new AMQChannel(session, _channelID, _testVhost.getMessageStore()); - - session.addChannel(channel); - - SubscriptionFactory factory = new SubscriptionFactoryImpl(); - - _subscription = factory.createSubscription(_channelID, session, new AMQShortString("cTag"), - false, null, false, - new LimitlessCreditManager()); - - _subscription.setQueue(_queue, false); + _subscription = mock(Subscription.class); + when(_subscription.getQueue()).thenReturn(_queue); + when(_subscription.getSubscriptionID()).thenReturn(SUBSCRIPTION_ID); _subject = new SubscriptionLogSubject(_subscription); } @@ -102,7 +90,7 @@ public class SubscriptionLogSubjectTest extends AbstractTestLogSubject // MESSAGE [Blank][sub:0(vh(/ // test)/ // qu(SubscriptionLogSubjectTest))] - // Take the last bit and drop off the extra )] + // Take the last bit and drop off the extra )] String[] parts = message.split("/"); assertEquals("Message part count wrong", 3, parts.length); String subscription = parts[2].substring(0, parts[2].indexOf(")") + 1); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/ConfiguredObjectStateTransitionTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/ConfiguredObjectStateTransitionTest.java index 46a81e6454..72cf09585c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/ConfiguredObjectStateTransitionTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/ConfiguredObjectStateTransitionTest.java @@ -35,6 +35,7 @@ import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.ConfiguredObjectRecoverer; import org.apache.qpid.server.configuration.RecovererProvider; import org.apache.qpid.server.configuration.startup.DefaultRecovererProvider; +import org.apache.qpid.server.configuration.store.StoreConfigurationChangeListener; import org.apache.qpid.server.configuration.updater.TaskExecutor; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; import org.apache.qpid.server.security.group.FileGroupManagerFactory; @@ -62,7 +63,7 @@ public class ConfiguredObjectStateTransitionTest extends QpidTestCase when(_broker.getTaskExecutor()).thenReturn(executor); _recovererProvider = new DefaultRecovererProvider(statisticsGatherer, _broker.getVirtualHostRegistry(), - _broker.getLogRecorder(), _broker.getRootMessageLogger(), executor, new BrokerOptions()); + _broker.getLogRecorder(), _broker.getRootMessageLogger(), executor, new BrokerOptions(), mock(StoreConfigurationChangeListener.class)); _store = mock(ConfigurationEntryStore.class); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java index 05d5d75864..ce213ee582 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/VirtualHostTest.java @@ -38,9 +38,8 @@ import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.TestLogActor; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.MemoryMessageStore; +import org.apache.qpid.server.store.TestMemoryMessageStore; import org.apache.qpid.server.util.BrokerTestHelper; -import org.apache.qpid.server.virtualhost.StandardVirtualHost; import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; public class VirtualHostTest extends TestCase @@ -92,7 +91,7 @@ public class VirtualHostTest extends TestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); attributes.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); - attributes.put(VirtualHost.STORE_TYPE, MemoryMessageStore.TYPE); + attributes.put(VirtualHost.STORE_TYPE, TestMemoryMessageStore.TYPE); attributes.put(VirtualHost.STATE, State.QUIESCED); VirtualHost host = createHost(attributes); @@ -131,7 +130,7 @@ public class VirtualHostTest extends TestCase Map<String, Object> attributes = new HashMap<String, Object>(); attributes.put(VirtualHost.NAME, getName()); attributes.put(VirtualHost.TYPE, StandardVirtualHostFactory.TYPE); - attributes.put(VirtualHost.STORE_TYPE, MemoryMessageStore.TYPE); + attributes.put(VirtualHost.STORE_TYPE, TestMemoryMessageStore.TYPE); VirtualHost host = createHost(attributes); return host; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java index fbb1e4105f..ed22843e07 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/AuthenticationProviderFactoryTest.java @@ -43,6 +43,7 @@ import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticat public class AuthenticationProviderFactoryTest extends TestCase { + private PreferencesProviderCreator _preferencesProviderCreator = mock(PreferencesProviderCreator.class); public void testCreatePasswordCredentialManagingAuthenticationProvider() { @@ -95,7 +96,7 @@ public class AuthenticationProviderFactoryTest extends TestCase Collections.singleton(authenticationManagerFactory)); when(authenticationManagerFactory.createInstance(attributes)).thenReturn(authenticationManager); - AuthenticationProviderFactory providerFactory = new AuthenticationProviderFactory(authManagerFactoryServiceLoader); + AuthenticationProviderFactory providerFactory = new AuthenticationProviderFactory(authManagerFactoryServiceLoader, _preferencesProviderCreator); AuthenticationProvider provider = null; if (create) @@ -124,7 +125,7 @@ public class AuthenticationProviderFactoryTest extends TestCase when(managerFactory.createInstance(any(Map.class))).thenReturn(mock(PrincipalDatabaseAuthenticationManager.class)); when(loader.atLeastOneInstanceOf(AuthenticationManagerFactory.class)).thenReturn(Collections.singleton(managerFactory)); - AuthenticationProviderFactory providerFactory = new AuthenticationProviderFactory(loader); + AuthenticationProviderFactory providerFactory = new AuthenticationProviderFactory(loader, _preferencesProviderCreator); UUID randomUUID = UUID.randomUUID(); AuthenticationProvider provider = providerFactory.create(randomUUID, broker, new HashMap<String, Object>()); @@ -145,7 +146,7 @@ public class AuthenticationProviderFactoryTest extends TestCase when(managerFactory.createInstance(any(Map.class))).thenReturn(mock(AuthenticationManager.class)); when(loader.atLeastOneInstanceOf(AuthenticationManagerFactory.class)).thenReturn(Collections.singleton(managerFactory)); - AuthenticationProviderFactory providerFactory = new AuthenticationProviderFactory(loader); + AuthenticationProviderFactory providerFactory = new AuthenticationProviderFactory(loader, _preferencesProviderCreator); UUID id = UUID.randomUUID(); AuthenticationProvider provider = providerFactory.create(id, broker, new HashMap<String, Object>()); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactoryTest.java new file mode 100644 index 0000000000..64dfad94c3 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderFactoryTest.java @@ -0,0 +1,139 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.model.adapter; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +public class FileSystemPreferencesProviderFactoryTest extends QpidTestCase +{ + private AuthenticationProvider _authenticationProvider; + private Broker _broker; + private FileSystemPreferencesProviderFactory _factory; + + public void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _authenticationProvider = mock(AuthenticationProvider.class); + _broker = BrokerTestHelper.createBrokerMock(); + when(_authenticationProvider.getParent(Broker.class)).thenReturn(_broker); + _factory = new FileSystemPreferencesProviderFactory(); + } + + public void tearDown() throws Exception + { + try + { + BrokerTestHelper.tearDown(); + } + finally + { + super.tearDown(); + } + } + + public void testGetType() + { + assertEquals(FileSystemPreferencesProvider.PROVIDER_TYPE, _factory.getType()); + } + + public void testCreateInstanceRecovering() + { + Map<String, Object> attributes = new HashMap<String, Object>(); + UUID id = UUID.randomUUID(); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.class); + attributes.put(PreferencesProvider.NAME, "test-provider"); + File file = TestFileUtils.createTempFile(this, ".prefs.json", "{\"test_user\":{\"pref1\": \"pref1Value\", \"pref2\": 1.0} }"); + try + { + attributes.put(FileSystemPreferencesProvider.PATH, file.getAbsolutePath()); + PreferencesProvider provider = _factory.createInstance(id, attributes, _authenticationProvider); + assertNotNull("Preferences provider was not instantiated", provider); + assertEquals("Unexpected name", "test-provider", provider.getName()); + assertEquals("Unexpected id", id, provider.getId()); + assertEquals("Unexpected path", file.getAbsolutePath(), + provider.getAttribute(FileSystemPreferencesProvider.PATH)); + } + finally + { + file.delete(); + } + } + + public void testCreateInstanceRecoveringWhenPrefStoreDoesNotExist() + { + Map<String, Object> attributes = new HashMap<String, Object>(); + UUID id = UUID.randomUUID(); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.class); + attributes.put(PreferencesProvider.NAME, "test-provider"); + File file = new File(TMP_FOLDER, UUID.randomUUID() + "prefs.json"); + assertFalse("Preferences store file should not exist", file.exists()); + try + { + attributes.put(FileSystemPreferencesProvider.PATH, file.getAbsolutePath()); + _factory.createInstance(id, attributes, _authenticationProvider); + } + catch (IllegalConfigurationException e) + { + // exception should be thrown if preferences store does not exist + } + } + + public void testCreateInstanceNotRecovering() + { + Map<String, Object> attributes = new HashMap<String, Object>(); + UUID id = UUID.randomUUID(); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.class); + attributes.put(PreferencesProvider.NAME, "test-provider"); + File file = new File(TMP_FOLDER, UUID.randomUUID() + "prefs.json"); + assertFalse("Preferences store file should not exist", file.exists()); + try + { + attributes.put(FileSystemPreferencesProvider.PATH, file.getAbsolutePath()); + PreferencesProvider provider = _factory.createInstance(id, attributes, _authenticationProvider); + assertNotNull("Preferences provider was not recovered", provider); + assertEquals("Unexpected name", "test-provider", provider.getName()); + assertEquals("Unexpected id", id, provider.getId()); + assertEquals("Unexpected path", file.getAbsolutePath(), provider.getAttribute(FileSystemPreferencesProvider.PATH)); + assertTrue("Preferences store file should exist", file.exists()); + } + finally + { + file.delete(); + } + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java new file mode 100644 index 0000000000..0eab93541f --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/model/adapter/FileSystemPreferencesProviderTest.java @@ -0,0 +1,266 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.model.adapter; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +public class FileSystemPreferencesProviderTest extends QpidTestCase +{ + private static final String TEST_PREFERENCES = "{\"user1\":{\"pref1\":\"pref1User1Value\", \"pref2\": true, \"pref3\": 1.0, \"pref4\": 2}," + + "\"user2\":{\"pref1\":\"pref1User2Value\", \"pref2\": false, \"pref3\": 2.0, \"pref4\": 3}}"; + private FileSystemPreferencesProvider _preferencesProvider; + private AuthenticationProvider _authenticationProvider; + private Broker _broker; + private String _user1, _user2; + private File _preferencesFile; + + protected void setUp() throws Exception + { + super.setUp(); + BrokerTestHelper.setUp(); + _authenticationProvider = mock(AuthenticationProvider.class); + _user1 = "user1"; + _user2 = "user2"; + _preferencesFile = TestFileUtils.createTempFile(this, ".prefs.json", TEST_PREFERENCES); + + _broker = BrokerTestHelper.createBrokerMock(); + TaskExecutor taslExecutor = mock(TaskExecutor.class); + when(taslExecutor.isTaskExecutorThread()).thenReturn(true); + when(_broker.getTaskExecutor()).thenReturn(taslExecutor); + when(_authenticationProvider.getParent(Broker.class)).thenReturn(_broker); + } + + protected void tearDown() throws Exception + { + try + { + BrokerTestHelper.tearDown(); + _preferencesFile.delete(); + } + finally + { + super.tearDown(); + } + } + + public void testConstructionWithExistingFile() + { + _preferencesProvider = createPreferencesProvider(); + assertEquals(State.INITIALISING, _preferencesProvider.getActualState()); + } + + public void testConstructionWithNonExistingFile() + { + File nonExistingFile = new File(TMP_FOLDER, "preferences-" + UUID.randomUUID() + ".json"); + assertFalse("Preferences file exists", nonExistingFile.exists()); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(FileSystemPreferencesProvider.PATH, nonExistingFile.getAbsolutePath()); + _preferencesProvider = new FileSystemPreferencesProvider(UUID.randomUUID(), attributes, _authenticationProvider, _broker.getTaskExecutor()); + _preferencesProvider.createStoreIfNotExist(); + assertEquals(State.INITIALISING, _preferencesProvider.getActualState()); + assertTrue("Preferences file was not created", nonExistingFile.exists()); + } + finally + { + nonExistingFile.delete(); + } + } + + public void testConstructionWithEmptyFile() throws Exception + { + File emptyPrefsFile = new File(TMP_FOLDER, "preferences-" + UUID.randomUUID() + ".json"); + emptyPrefsFile.createNewFile(); + assertTrue("Preferences file does notexists", emptyPrefsFile.exists()); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(FileSystemPreferencesProvider.PATH, emptyPrefsFile.getAbsolutePath()); + _preferencesProvider = new FileSystemPreferencesProvider(UUID.randomUUID(), attributes, _authenticationProvider, _broker.getTaskExecutor()); + assertEquals(State.INITIALISING, _preferencesProvider.getActualState()); + } + finally + { + emptyPrefsFile.delete(); + } + } + + public void testActivate() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + assertEquals("Unexpexpected state", State.ACTIVE, _preferencesProvider.getActualState()); + } + + public void testChangeAttributes() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + File newPrefsFile = TestFileUtils.createTempFile(this, ".prefs.json", "{\"user3\":{\"pref1\":\"pref1User3Value\", \"pref3\": 2.0}}"); + try + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(FileSystemPreferencesProvider.PATH, newPrefsFile.getAbsolutePath()); + _preferencesProvider.changeAttributes(attributes); + assertEquals("Unexpected path", newPrefsFile.getAbsolutePath(), + _preferencesProvider.getAttribute(FileSystemPreferencesProvider.PATH)); + + Map<String, Object> preferences1 = _preferencesProvider.getPreferences(_user1); + assertTrue("Unexpected preferences for user1", preferences1.isEmpty()); + + String user3 = "user3"; + Map<String, Object> preferences3 = _preferencesProvider.getPreferences(user3); + assertFalse("No preference found for user3", preferences3.isEmpty()); + assertEquals("Unexpected preference 1 for user 3", "pref1User3Value", preferences3.get("pref1")); + assertEquals("Unexpected preference 3 for user 3", 2.0, ((Number) preferences3.get("pref3")).floatValue(), 0.01); + } + finally + { + newPrefsFile.delete(); + } + } + + public void testGetPreferences() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + Map<String, Object> preferences1 = _preferencesProvider.getPreferences(_user1); + assertUser1Preferences(preferences1); + + Map<String, Object> preferences2 = _preferencesProvider.getPreferences(_user2); + assertUser2Preferences(preferences2); + + String user3 = "user3"; + Map<String, Object> preferences3 = _preferencesProvider.getPreferences(user3); + assertTrue("No preference found for user3", preferences3.isEmpty()); + } + + public void testSetPrefernces() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + Map<String, Object> newPreferences = new HashMap<String, Object>(); + newPreferences.put("pref2", false); + newPreferences.put("pref4", 8); + Map<String, Object> pref5 = new HashMap<String, Object>(); + pref5.put("test1", "test1Value"); + pref5.put("test2", 5); + newPreferences.put("pref5", pref5); + + _preferencesProvider.setPreferences(_user1, newPreferences); + + FileSystemPreferencesProvider newProvider = createPreferencesProvider(); + Map<String, Object> preferences1 = newProvider.getPreferences(_user1); + assertNotNull("Preferences should not be null for user 1", preferences1); + assertEquals("Unexpected preference 1 for user 1", "pref1User1Value", preferences1.get("pref1")); + assertEquals("Unexpected preference 2 for user 1", false, preferences1.get("pref2")); + assertEquals("Unexpected preference 3 for user 1", 1.0, ((Number) preferences1.get("pref3")).floatValue(), 0.01); + assertEquals("Unexpected preference 4 for user 1", 8, preferences1.get("pref4")); + assertNotNull("Unexpected preference 5 for user 1", preferences1.get("pref5")); + assertEquals("Unexpected preference 5 for user 1", pref5, preferences1.get("pref5")); + + Map<String, Object> preferences2 = newProvider.getPreferences(_user2); + assertUser2Preferences(preferences2); + + String user3 = "user3"; + Map<String, Object> preferences3 = newProvider.getPreferences(user3); + assertTrue("No preference found for user3", preferences3.isEmpty()); + } + + public void testDeletePrefernces() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + _preferencesProvider.deletePreferences(_user1); + + FileSystemPreferencesProvider newProvider = createPreferencesProvider(); + Map<String, Object> preferences1 = newProvider.getPreferences(_user1); + assertTrue("Preferences should not be set for user 1", preferences1.isEmpty()); + + Map<String, Object> preferences2 = newProvider.getPreferences(_user2); + assertUser2Preferences(preferences2); + + String user3 = "user3"; + Map<String, Object> preferences3 = newProvider.getPreferences(user3); + assertTrue("No preference found for user3", preferences3.isEmpty()); + } + + public void testListUserNames() + { + _preferencesProvider = createPreferencesProvider(); + _preferencesProvider.setDesiredState(State.INITIALISING, State.ACTIVE); + + Set<String> userNames = _preferencesProvider.listUserIDs(); + + assertEquals("Unexpected user names", new HashSet<String>(Arrays.asList("user1", "user2")), userNames); + } + + private FileSystemPreferencesProvider createPreferencesProvider() + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(FileSystemPreferencesProvider.PATH, _preferencesFile.getAbsolutePath()); + attributes.put(FileSystemPreferencesProvider.NAME, "test"); + return _preferencesProvider = new FileSystemPreferencesProvider(UUID.randomUUID(), attributes, _authenticationProvider, _broker.getTaskExecutor()); + } + + private void assertUser1Preferences(Map<String, Object> preferences1) + { + assertNotNull("Preferences should not be null for user 1", preferences1); + assertEquals("Unexpected preference 1 for user 1", "pref1User1Value", preferences1.get("pref1")); + assertEquals("Unexpected preference 2 for user 1", true, preferences1.get("pref2")); + assertEquals("Unexpected preference 3 for user 1", 1.0, ((Number) preferences1.get("pref3")).floatValue(), 0.01); + assertEquals("Unexpected preference 4 for user 1", 2, preferences1.get("pref4")); + assertNull("Unexpected preference 5 for user 1", preferences1.get("pref5")); + } + + private void assertUser2Preferences(Map<String, Object> preferences2) + { + assertNotNull("Preferences should not be null for user 2", preferences2); + assertEquals("Unexpected preference 1 for user 2", "pref1User2Value", preferences2.get("pref1")); + assertEquals("Unexpected preference 2 for user 2", false, preferences2.get("pref2")); + assertEquals("Unexpected preference 2 for user 2", 2.0, ((Number) preferences2.get("pref3")).floatValue(), 0.01); + assertEquals("Unexpected preference 3 for user 2", 3, preferences2.get("pref4")); + assertNull("Unexpected preference 5 for user 2", preferences2.get("pref5")); + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java index 81ad57c040..a468fa072b 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java @@ -20,15 +20,17 @@ */ package org.apache.qpid.server.queue; +import java.util.Collections; import junit.framework.AssertionFailedError; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.ServerMessage; import java.util.ArrayList; +import org.apache.qpid.server.model.Queue; + +import static org.mockito.Mockito.when; public class AMQPriorityQueueTest extends SimpleAMQQueueTest { @@ -36,9 +38,7 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest @Override public void setUp() throws Exception { - FieldTable arguments = new FieldTable(); - arguments.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), 3); - setArguments(arguments); + setArguments(Collections.singletonMap(Queue.PRIORITIES,(Object)3)); super.setUp(); } @@ -95,16 +95,16 @@ public class AMQPriorityQueueTest extends SimpleAMQQueueTest } - protected AMQMessage createMessage(Long id, byte i) throws AMQException + protected ServerMessage createMessage(Long id, byte i) throws AMQException { - AMQMessage msg = super.createMessage(id); - BasicContentHeaderProperties props = new BasicContentHeaderProperties(); - props.setPriority(i); - msg.getContentHeaderBody().setProperties(props); + + ServerMessage msg = super.createMessage(id); + AMQMessageHeader hdr = msg.getMessageHeader(); + when(hdr.getPriority()).thenReturn(i); return msg; } - protected AMQMessage createMessage(Long id) throws AMQException + protected ServerMessage createMessage(Long id) throws AMQException { return createMessage(id, (byte) 0); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java index c8e0e53d75..9a2c5bc166 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java @@ -20,91 +20,216 @@ */ package org.apache.qpid.server.queue; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyMap; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.PropertiesConfiguration; -import org.apache.commons.configuration.XMLConfiguration; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.util.BrokerTestHelper; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; public class AMQQueueFactoryTest extends QpidTestCase { private QueueRegistry _queueRegistry; private VirtualHost _virtualHost; - private Broker _broker; + private AMQQueueFactory _queueFactory; + private List<AMQQueue> _queues; + private QueueConfiguration _queueConfiguration; @Override public void setUp() throws Exception { super.setUp(); - BrokerTestHelper.setUp(); - XMLConfiguration configXml = new XMLConfiguration(); - configXml.addProperty("store.class", TestableMemoryMessageStore.class.getName()); + _queues = new ArrayList<AMQQueue>(); + _virtualHost = mock(VirtualHost.class); - _broker = BrokerTestHelper.createBrokerMock(); - if (getName().equals("testDeadLetterQueueDoesNotInheritDLQorMDCSettings")) - { - when(_broker.getAttribute(Broker.QUEUE_MAXIMUM_DELIVERY_ATTEMPTS)).thenReturn(5); - when(_broker.getAttribute(Broker.QUEUE_DEAD_LETTER_QUEUE_ENABLED)).thenReturn(true); - } + VirtualHostConfiguration vhostConfig = mock(VirtualHostConfiguration.class); + when(_virtualHost.getConfiguration()).thenReturn(vhostConfig); + _queueConfiguration = mock(QueueConfiguration.class); + when(vhostConfig.getQueueConfiguration(anyString())).thenReturn(_queueConfiguration); + LogActor logActor = mock(LogActor.class); + CurrentActor.set(logActor); + RootMessageLogger rootLogger = mock(RootMessageLogger.class); + when(logActor.getRootMessageLogger()).thenReturn(rootLogger); + DurableConfigurationStore store = mock(DurableConfigurationStore.class); + when(_virtualHost.getDurableConfigurationStore()).thenReturn(store); + + mockExchangeCreation(); + mockQueueRegistry(); + delegateVhostQueueCreation(); + + when(_virtualHost.getQueues()).thenReturn(_queues); + + + _queueFactory = new AMQQueueFactory(_virtualHost, _queueRegistry); - _virtualHost = BrokerTestHelper.createVirtualHost(new VirtualHostConfiguration(getName(), configXml, _broker)); - _queueRegistry = _virtualHost.getQueueRegistry(); } + private void delegateVhostQueueCreation() throws AMQException + { + final ArgumentCaptor<UUID> id = ArgumentCaptor.forClass(UUID.class); + final ArgumentCaptor<String> queueName = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<Boolean> durable = ArgumentCaptor.forClass(Boolean.class); + final ArgumentCaptor<String> owner = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<Boolean> autoDelete = ArgumentCaptor.forClass(Boolean.class); + final ArgumentCaptor<Boolean> exclusive = ArgumentCaptor.forClass(Boolean.class); + final ArgumentCaptor<Boolean> deleteOnNoConsumer = ArgumentCaptor.forClass(Boolean.class); + final ArgumentCaptor<Map> arguments = ArgumentCaptor.forClass(Map.class); + + when(_virtualHost.createQueue(id.capture(), queueName.capture(), durable.capture(), owner.capture(), + autoDelete.capture(), exclusive.capture(), deleteOnNoConsumer.capture(), arguments.capture())).then( + new Answer<AMQQueue>() + { + @Override + public AMQQueue answer(InvocationOnMock invocation) throws Throwable + { + return _queueFactory.createQueue(id.getValue(), + queueName.getValue(), + durable.getValue(), + owner.getValue(), + autoDelete.getValue(), + exclusive.getValue(), + deleteOnNoConsumer.getValue(), + arguments.getValue()); + } + } + ); + } + + private void mockQueueRegistry() + { + _queueRegistry = mock(QueueRegistry.class); + + final ArgumentCaptor<AMQQueue> capturedQueue = ArgumentCaptor.forClass(AMQQueue.class); + doAnswer(new Answer() + { + + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable + { + AMQQueue queue = capturedQueue.getValue(); + when(_queueRegistry.getQueue(eq(queue.getId()))).thenReturn(queue); + when(_queueRegistry.getQueue(eq(queue.getName()))).thenReturn(queue); + when(_virtualHost.getQueue(eq(queue.getId()))).thenReturn(queue); + when(_virtualHost.getQueue(eq(queue.getName()))).thenReturn(queue); + _queues.add(queue); + + return null; + } + }).when(_queueRegistry).registerQueue(capturedQueue.capture()); + } + + private void mockExchangeCreation() throws AMQException + { + final ArgumentCaptor<UUID> idCapture = ArgumentCaptor.forClass(UUID.class); + final ArgumentCaptor<String> exchangeNameCapture = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<String> type = ArgumentCaptor.forClass(String.class); + + when(_virtualHost.createExchange(idCapture.capture(), exchangeNameCapture.capture(), type.capture(), + anyBoolean(), anyBoolean(), anyString())).then( + new Answer<Exchange>() + { + @Override + public Exchange answer(InvocationOnMock invocation) throws Throwable + { + final String name = exchangeNameCapture.getValue(); + final UUID id = idCapture.getValue(); + + final Exchange exchange = mock(Exchange.class); + ExchangeType exType = mock(ExchangeType.class); + + when(exchange.getName()).thenReturn(name); + when(exchange.getId()).thenReturn(id); + when(exchange.getType()).thenReturn(exType); + + final String typeName = type.getValue(); + when(exType.getType()).thenReturn(typeName); + when(exchange.getTypeName()).thenReturn(typeName); + + when(_virtualHost.getExchange(eq(name))).thenReturn(exchange); + when(_virtualHost.getExchange(eq(id))).thenReturn(exchange); + + final ArgumentCaptor<AMQQueue> queue = ArgumentCaptor.forClass(AMQQueue.class); + + when(exchange.addBinding(anyString(),queue.capture(),anyMap())).then(new Answer<Boolean>() { + + @Override + public Boolean answer(InvocationOnMock invocation) throws Throwable + { + when(exchange.isBound(eq(queue.getValue()))).thenReturn(true); + return true; + } + }); + + return exchange; + } + } + ); + } + @Override public void tearDown() throws Exception { - try - { - _virtualHost.close(); - } - finally - { - BrokerTestHelper.tearDown(); - super.tearDown(); - } + super.tearDown(); } private void verifyRegisteredQueueCount(int count) { - assertEquals("Queue was not registered in virtualhost", count, _queueRegistry.getQueues().size()); + assertEquals("Queue was not registered in virtualhost", count, _virtualHost.getQueues().size()); } private void verifyQueueRegistered(String queueName) { - assertNotNull("Queue " + queueName + " was not created", _queueRegistry.getQueue(queueName)); + assertNotNull("Queue " + queueName + " was not created", _virtualHost.getQueue(queueName)); } public void testPriorityQueueRegistration() throws Exception { - FieldTable fieldTable = new FieldTable(); - fieldTable.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), 5); + Map<String,Object> attributes = Collections.singletonMap(Queue.PRIORITIES, (Object) 5); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testPriorityQueue", false, "owner", false, - false, _virtualHost, FieldTable.convertToMap(fieldTable)); + AMQQueue queue = _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), + "testPriorityQueue", + false, + "owner", + false, + false, + false, + attributes); assertEquals("Queue not a priorty queue", AMQPriorityQueue.class, queue.getClass()); verifyQueueRegistered("testPriorityQueue"); @@ -115,53 +240,57 @@ public class AMQQueueFactoryTest extends QpidTestCase public void testSimpleQueueRegistration() throws Exception { String queueName = getName(); - AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); + String dlQueueName = queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX; - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, - false, _virtualHost, null); + AMQQueue queue = _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, + false, + false, + null); assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass()); verifyQueueRegistered(queueName); //verify that no alternate exchange or DLQ were produced - QueueRegistry qReg = _virtualHost.getQueueRegistry(); assertNull("Queue should not have an alternate exchange as DLQ wasnt enabled", queue.getAlternateExchange()); - assertNull("The DLQ should not exist", qReg.getQueue(dlQueueName)); + assertNull("The DLQ should not exist", _virtualHost.getQueue(dlQueueName)); verifyRegisteredQueueCount(1); } /** - * Tests that setting the {@link AMQQueueFactory#X_QPID_DLQ_ENABLED} argument true does + * Tests that setting the {@link QueueArgumentsConverter#X_QPID_DLQ_ENABLED} argument true does * cause the alternate exchange to be set and DLQ to be produced. * @throws AMQException */ public void testDeadLetterQueueEnabled() throws AMQException { - FieldTable fieldTable = new FieldTable(); - fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); + Map<String,Object> attributes = Collections.singletonMap(Queue.CREATE_DLQ_ON_CREATION, (Object) true); String queueName = "testDeadLetterQueueEnabled"; String dlExchangeName = queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX; String dlQueueName = queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX; - QueueRegistry qReg = _virtualHost.getQueueRegistry(); - - assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName)); + assertNull("The DLQ should not yet exist", _virtualHost.getQueue(dlQueueName)); assertNull("The alternate exchange should not yet exist", _virtualHost.getExchange(dlExchangeName)); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false, - _virtualHost, FieldTable.convertToMap(fieldTable)); + AMQQueue queue = _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), + queueName, + false, + "owner", + false, + false, + false, + attributes); Exchange altExchange = queue.getAlternateExchange(); assertNotNull("Queue should have an alternate exchange as DLQ is enabled", altExchange); assertEquals("Alternate exchange name was not as expected", dlExchangeName, altExchange.getName()); - assertEquals("Alternate exchange type was not as expected", ExchangeDefaults.FANOUT_EXCHANGE_CLASS, altExchange.getType().getName()); + assertEquals("Alternate exchange type was not as expected", ExchangeDefaults.FANOUT_EXCHANGE_CLASS, altExchange.getTypeName()); assertNotNull("The alternate exchange was not registered as expected", _virtualHost.getExchange(dlExchangeName)); assertEquals("The registered exchange was not the expected exchange instance", altExchange, _virtualHost.getExchange(dlExchangeName)); - AMQQueue dlQueue = qReg.getQueue(dlQueueName); + AMQQueue dlQueue = _virtualHost.getQueue(dlQueueName); assertNotNull("The DLQ was not registered as expected", dlQueue); assertTrue("DLQ should have been bound to the alternate exchange", altExchange.isBound(dlQueue)); assertNull("DLQ should have no alternate exchange", dlQueue.getAlternateExchange()); @@ -178,28 +307,36 @@ public class AMQQueueFactoryTest extends QpidTestCase */ public void testDeadLetterQueueDoesNotInheritDLQorMDCSettings() throws Exception { + String queueName = "testDeadLetterQueueEnabled"; String dlExchangeName = queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX; String dlQueueName = queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX; - QueueRegistry qReg = _virtualHost.getQueueRegistry(); + when(_queueConfiguration.getMaxDeliveryCount()).thenReturn(5); + when(_queueConfiguration.isDeadLetterQueueEnabled()).thenReturn(true); - assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName)); + assertNull("The DLQ should not yet exist", _virtualHost.getQueue(dlQueueName)); assertNull("The alternate exchange should not yet exist", _virtualHost.getExchange(dlExchangeName)); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false, - _virtualHost, null); + AMQQueue queue = _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), + queueName, + false, + "owner", + false, + false, + false, + null); assertEquals("Unexpected maximum delivery count", 5, queue.getMaximumDeliveryCount()); Exchange altExchange = queue.getAlternateExchange(); assertNotNull("Queue should have an alternate exchange as DLQ is enabled", altExchange); assertEquals("Alternate exchange name was not as expected", dlExchangeName, altExchange.getName()); - assertEquals("Alternate exchange type was not as expected", ExchangeDefaults.FANOUT_EXCHANGE_CLASS, altExchange.getType().getName()); + assertEquals("Alternate exchange type was not as expected", ExchangeDefaults.FANOUT_EXCHANGE_CLASS, altExchange.getTypeName()); assertNotNull("The alternate exchange was not registered as expected", _virtualHost.getExchange(dlExchangeName)); assertEquals("The registered exchange was not the expected exchange instance", altExchange, _virtualHost.getExchange(dlExchangeName)); - AMQQueue dlQueue = qReg.getQueue(dlQueueName); + AMQQueue dlQueue = _virtualHost.getQueue(dlQueueName); assertNotNull("The DLQ was not registered as expected", dlQueue); assertTrue("DLQ should have been bound to the alternate exchange", altExchange.isBound(dlQueue)); assertNull("DLQ should have no alternate exchange", dlQueue.getAlternateExchange()); @@ -210,81 +347,92 @@ public class AMQQueueFactoryTest extends QpidTestCase } /** - * Tests that setting the {@link AMQQueueFactory#X_QPID_DLQ_ENABLED} argument false does not + * Tests that setting the {@link QueueArgumentsConverter#X_QPID_DLQ_ENABLED} argument false does not * result in the alternate exchange being set and DLQ being created. * @throws AMQException */ public void testDeadLetterQueueDisabled() throws AMQException { - FieldTable fieldTable = new FieldTable(); - fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, false); + Map<String,Object> attributes = Collections.singletonMap(Queue.CREATE_DLQ_ON_CREATION, (Object) false); String queueName = "testDeadLetterQueueDisabled"; String dlExchangeName = queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX; String dlQueueName = queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX; - QueueRegistry qReg = _virtualHost.getQueueRegistry(); - - assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName)); + assertNull("The DLQ should not yet exist", _virtualHost.getQueue(dlQueueName)); assertNull("The alternate exchange should not exist", _virtualHost.getExchange(dlExchangeName)); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false, - _virtualHost, FieldTable.convertToMap(fieldTable)); + AMQQueue queue = _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), + queueName, + false, + "owner", + false, + false, + false, + attributes); assertNull("Queue should not have an alternate exchange as DLQ is disabled", queue.getAlternateExchange()); assertNull("The alternate exchange should still not exist", _virtualHost.getExchange(dlExchangeName)); - assertNull("The DLQ should still not exist", qReg.getQueue(dlQueueName)); + assertNull("The DLQ should still not exist", _virtualHost.getQueue(dlQueueName)); //only 1 queue should have been registered verifyRegisteredQueueCount(1); } /** - * Tests that setting the {@link AMQQueueFactory#X_QPID_DLQ_ENABLED} argument true but + * Tests that setting the {@link QueueArgumentsConverter#X_QPID_DLQ_ENABLED} argument true but * creating an auto-delete queue, does not result in the alternate exchange * being set and DLQ being created. * @throws AMQException */ public void testDeadLetterQueueNotCreatedForAutodeleteQueues() throws AMQException { - FieldTable fieldTable = new FieldTable(); - fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); + Map<String,Object> attributes = Collections.singletonMap(Queue.CREATE_DLQ_ON_CREATION, (Object) true); String queueName = "testDeadLetterQueueNotCreatedForAutodeleteQueues"; String dlExchangeName = queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX; String dlQueueName = queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX; - QueueRegistry qReg = _virtualHost.getQueueRegistry(); - - assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName)); + assertNull("The DLQ should not yet exist", _virtualHost.getQueue(dlQueueName)); assertNull("The alternate exchange should not exist", _virtualHost.getExchange(dlExchangeName)); //create an autodelete queue - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", true, false, - _virtualHost, FieldTable.convertToMap(fieldTable)); + AMQQueue queue = _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), + queueName, + false, + "owner", + true, + false, + false, + attributes); assertTrue("Queue should be autodelete", queue.isAutoDelete()); //ensure that the autodelete property overrides the request to enable DLQ assertNull("Queue should not have an alternate exchange as queue is autodelete", queue.getAlternateExchange()); assertNull("The alternate exchange should not exist as queue is autodelete", _virtualHost.getExchange(dlExchangeName)); - assertNull("The DLQ should not exist as queue is autodelete", qReg.getQueue(dlQueueName)); + assertNull("The DLQ should not exist as queue is autodelete", _virtualHost.getQueue(dlQueueName)); //only 1 queue should have been registered verifyRegisteredQueueCount(1); } /** - * Tests that setting the {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument has + * Tests that setting the {@link QueueArgumentsConverter#X_QPID_MAXIMUM_DELIVERY_COUNT} argument has * the desired effect. */ public void testMaximumDeliveryCount() throws Exception { - final FieldTable fieldTable = new FieldTable(); - fieldTable.setInteger(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, 5); + Map<String,Object> attributes = Collections.singletonMap(Queue.MAXIMUM_DELIVERY_ATTEMPTS, (Object) 5); - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testMaximumDeliveryCount", false, "owner", false, false, - _virtualHost, FieldTable.convertToMap(fieldTable)); + final AMQQueue queue = _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), + "testMaximumDeliveryCount", + false, + "owner", + false, + false, + false, + attributes); assertNotNull("The queue was not registered as expected ", queue); assertEquals("Maximum delivery count not as expected", 5, queue.getMaximumDeliveryCount()); @@ -293,13 +441,19 @@ public class AMQQueueFactoryTest extends QpidTestCase } /** - * Tests that omitting the {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument means + * Tests that omitting the {@link QueueArgumentsConverter#X_QPID_MAXIMUM_DELIVERY_COUNT} argument means * that queue is created with a default maximumDeliveryCount of zero (unless set in config). */ public void testMaximumDeliveryCountDefault() throws Exception { - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testMaximumDeliveryCount", false, "owner", false, false, - _virtualHost, null); + final AMQQueue queue = _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), + "testMaximumDeliveryCount", + false, + "owner", + false, + false, + false, + null); assertNotNull("The queue was not registered as expected ", queue); assertEquals("Maximum delivery count not as expected", 0, queue.getMaximumDeliveryCount()); @@ -314,7 +468,9 @@ public class AMQQueueFactoryTest extends QpidTestCase { try { - AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), null, false, "owner", true, false, _virtualHost, null); + _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), null, false, "owner", true, false, + false, + null); fail("queue with null name can not be created!"); } catch (Exception e) @@ -336,10 +492,9 @@ public class AMQQueueFactoryTest extends QpidTestCase // change DLQ name to make its length bigger than exchange name setTestSystemProperty(BrokerProperties.PROPERTY_DEAD_LETTER_EXCHANGE_SUFFIX, "_DLE"); setTestSystemProperty(BrokerProperties.PROPERTY_DEAD_LETTER_QUEUE_SUFFIX, "_DLQUEUE"); - FieldTable fieldTable = new FieldTable(); - fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); - AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", - false, false, _virtualHost, FieldTable.convertToMap(fieldTable)); + Map<String,Object> attributes = Collections.singletonMap(Queue.CREATE_DLQ_ON_CREATION, (Object) true); + _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", + false, false, false, attributes); fail("queue with DLQ name having more than 255 characters can not be created!"); } catch (Exception e) @@ -362,10 +517,9 @@ public class AMQQueueFactoryTest extends QpidTestCase // change DLQ name to make its length bigger than exchange name setTestSystemProperty(BrokerProperties.PROPERTY_DEAD_LETTER_EXCHANGE_SUFFIX, "_DLEXCHANGE"); setTestSystemProperty(BrokerProperties.PROPERTY_DEAD_LETTER_QUEUE_SUFFIX, "_DLQ"); - FieldTable fieldTable = new FieldTable(); - fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); - AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", - false, false, _virtualHost, FieldTable.convertToMap(fieldTable)); + Map<String,Object> attributes = Collections.singletonMap(Queue.CREATE_DLQ_ON_CREATION, (Object) true); + _queueFactory.createQueue(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", + false, false, false, attributes); fail("queue with DLE name having more than 255 characters can not be created!"); } catch (Exception e) @@ -379,16 +533,17 @@ public class AMQQueueFactoryTest extends QpidTestCase public void testMessageGroupFromConfig() throws Exception { - PropertiesConfiguration queueConfig = new PropertiesConfiguration(); - queueConfig.addProperty("queues.queue.test.argument", "qpid.group_header_key=mykey"); - queueConfig.addProperty("queues.queue.test.argument", "qpid.shared_msg_group=1"); + Map<String,String> arguments = new HashMap<String, String>(); + arguments.put("qpid.group_header_key","mykey"); + arguments.put("qpid.shared_msg_group","1"); + QueueConfiguration qConf = mock(QueueConfiguration.class); + when(qConf.getArguments()).thenReturn(arguments); + when(qConf.getName()).thenReturn("test"); - final VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration("test", queueConfig, _broker);; - QueueConfiguration qConf = new QueueConfiguration("test", vhostConfig); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(qConf, _virtualHost); - assertEquals("mykey", queue.getArguments().get(SimpleAMQQueue.QPID_GROUP_HEADER_KEY)); - assertEquals("1", queue.getArguments().get(SimpleAMQQueue.QPID_SHARED_MSG_GROUP)); + AMQQueue queue = _queueFactory.createAMQQueueImpl(qConf); + assertEquals("mykey", queue.getAttribute(Queue.MESSAGE_GROUP_KEY)); + assertEquals(Boolean.TRUE, queue.getAttribute(Queue.MESSAGE_GROUP_SHARED_GROUPS)); } private String generateStringWithLength(char ch, int length) diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java index a94548f1c3..6538724a71 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java @@ -23,10 +23,8 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import junit.framework.TestCase; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.AMQMessageHeader; -import org.apache.qpid.server.message.AMQMessageReference; -import org.apache.qpid.server.message.MessageMetaData; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -56,7 +54,7 @@ public class ConflationQueueListTest extends TestCase public void testAddMessageWithoutConflationKeyValue() { - ServerMessage<MessageMetaData> message = createTestServerMessage(null); + ServerMessage message = createTestServerMessage(null); _list.add(message); int numberOfEntries = countEntries(_list); @@ -65,7 +63,7 @@ public class ConflationQueueListTest extends TestCase public void testAddAndDiscardMessageWithoutConflationKeyValue() { - ServerMessage<MessageMetaData> message = createTestServerMessage(null); + ServerMessage message = createTestServerMessage(null); QueueEntry addedEntry = _list.add(message); addedEntry.discard(); @@ -76,7 +74,7 @@ public class ConflationQueueListTest extends TestCase public void testAddMessageWithConflationKeyValue() { - ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage message = createTestServerMessage(TEST_KEY_VALUE); _list.add(message); int numberOfEntries = countEntries(_list); @@ -85,7 +83,7 @@ public class ConflationQueueListTest extends TestCase public void testAddAndRemoveMessageWithConflationKeyValue() { - ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage message = createTestServerMessage(TEST_KEY_VALUE); QueueEntry addedEntry = _list.add(message); addedEntry.discard(); @@ -96,8 +94,8 @@ public class ConflationQueueListTest extends TestCase public void testAddTwoMessagesWithDifferentConflationKeyValue() { - ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE1); - ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE2); + ServerMessage message1 = createTestServerMessage(TEST_KEY_VALUE1); + ServerMessage message2 = createTestServerMessage(TEST_KEY_VALUE2); _list.add(message1); _list.add(message2); @@ -108,8 +106,8 @@ public class ConflationQueueListTest extends TestCase public void testAddTwoMessagesWithSameConflationKeyValue() { - ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE); - ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage message1 = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage message2 = createTestServerMessage(TEST_KEY_VALUE); _list.add(message1); _list.add(message2); @@ -120,8 +118,8 @@ public class ConflationQueueListTest extends TestCase public void testSupersededEntryIsDiscardedOnRelease() { - ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE); - ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage message1 = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage message2 = createTestServerMessage(TEST_KEY_VALUE); QueueEntry entry1 = _list.add(message1); entry1.acquire(); // simulate an in-progress delivery to consumer @@ -141,7 +139,7 @@ public class ConflationQueueListTest extends TestCase { assertEquals(0, _list.getLatestValuesMap().size()); - ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage message = createTestServerMessage(TEST_KEY_VALUE); QueueEntry addedEntry = _list.add(message); @@ -159,8 +157,8 @@ public class ConflationQueueListTest extends TestCase assertEquals(0, _list.getLatestValuesMap().size()); - ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE1); - ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE2); + ServerMessage message1 = createTestServerMessage(TEST_KEY_VALUE1); + ServerMessage message2 = createTestServerMessage(TEST_KEY_VALUE2); QueueEntry addedEntry1 = _list.add(message1); QueueEntry addedEntry2 = _list.add(message2); @@ -186,16 +184,17 @@ public class ConflationQueueListTest extends TestCase return count; } - private ServerMessage<MessageMetaData> createTestServerMessage(String conflationKeyValue) + private ServerMessage createTestServerMessage(String conflationKeyValue) { - AMQMessage mockMessage = mock(AMQMessage.class); + ServerMessage mockMessage = mock(ServerMessage.class); AMQMessageHeader messageHeader = mock(AMQMessageHeader.class); when(messageHeader.getHeader(CONFLATION_KEY)).thenReturn(conflationKeyValue); when(mockMessage.getMessageHeader()).thenReturn(messageHeader); - AMQMessageReference messageReference = new AMQMessageReference(mockMessage); + MessageReference messageReference = mock(MessageReference.class); when(mockMessage.newReference()).thenReturn(messageReference); + when(messageReference.getMessage()).thenReturn(mockMessage); return mockMessage; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java index 2f160678ba..584e26d88f 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java @@ -53,14 +53,6 @@ public class InboundMessageAdapterTest extends QpidTestCase assertEquals("Unexpected value for routing key", routingKey, _inboundMessageAdapter.getRoutingKey()); } - public void testGetRoutingKeyShortString() throws Exception - { - String routingKey = getTestName(); - when(_mockMessage.getRoutingKey()).thenReturn(routingKey); - - AMQShortString routingKeyShortString = AMQShortString.valueOf(routingKey); - assertEquals("Unexpected value for routing key short string", routingKeyShortString, _inboundMessageAdapter.getRoutingKeyShortString()); - } public void testGetMessageHeader() throws Exception { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java index 358246330a..2a0c12ff3e 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java @@ -24,7 +24,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.configuration.QueueConfiguration; -import org.apache.qpid.server.configuration.plugins.AbstractConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.message.ServerMessage; @@ -44,7 +43,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class MockAMQQueue implements AMQQueue { private boolean _deleted = false; - private AMQShortString _name; + private String _name; private VirtualHost _virtualhost; private AuthorizationHolder _authorizationHolder; @@ -55,7 +54,7 @@ public class MockAMQQueue implements AMQQueue public MockAMQQueue(String name) { - _name = new AMQShortString(name); + _name = name; } public boolean getDeleteOnNoConsumers() @@ -164,11 +163,6 @@ public class MockAMQQueue implements AMQQueue return 0; } - public AMQShortString getNameShortString() - { - return _name; - } - public void setNoLocal(boolean b) { @@ -195,7 +189,7 @@ public class MockAMQQueue implements AMQQueue } - public AMQShortString getOwner() + public String getOwner() { return null; } @@ -212,7 +206,7 @@ public class MockAMQQueue implements AMQQueue public String getName() { - return _name.asString(); + return _name; } public void registerSubscription(Subscription subscription, boolean exclusive) throws AMQException @@ -470,7 +464,14 @@ public class MockAMQQueue implements AMQQueue } - public Map<String, Object> getArguments() + @Override + public Collection<String> getAvailableAttributes() + { + return null; + } + + @Override + public Object getAttribute(String attrName) { return null; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java index 525093ccbd..f5d4f1219d 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/MockQueueEntry.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.subscription.Subscription; @@ -29,7 +28,7 @@ import org.apache.qpid.server.subscription.Subscription; public class MockQueueEntry implements QueueEntry { - private AMQMessage _message; + private ServerMessage _message; public boolean acquire() { @@ -209,7 +208,7 @@ public class MockQueueEntry implements QueueEntry return 0; } - public void setMessage(AMQMessage msg) + public void setMessage(ServerMessage msg) { _message = msg; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java index 8be6061b45..d348c3e67b 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryImplTestBase.java @@ -21,13 +21,16 @@ package org.apache.qpid.server.queue; import junit.framework.TestCase; import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.queue.QueueEntry.EntryState; import org.apache.qpid.server.subscription.MockSubscription; import org.apache.qpid.server.subscription.Subscription; import java.lang.reflect.Field; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + /** * Tests for {@link QueueEntryImpl} */ @@ -211,8 +214,9 @@ public abstract class QueueEntryImplTestBase extends TestCase // create test entries for(int i = 0; i < numberOfEntries ; i++) { - AMQMessage message = new MockAMQMessage(i); - QueueEntryImpl entry = (QueueEntryImpl)queueEntryList.add(message); + ServerMessage message = mock(ServerMessage.class); + when(message.getMessageNumber()).thenReturn((long)i); + QueueEntryImpl entry = queueEntryList.add(message); entries[i] = entry; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java index 4b40c3b552..beb5bda7ff 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/QueueEntryListTestBase.java @@ -22,8 +22,13 @@ package org.apache.qpid.server.queue; import junit.framework.TestCase; import org.apache.qpid.AMQException; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + /** * Abstract test class for QueueEntryList implementations. */ @@ -66,13 +71,13 @@ public abstract class QueueEntryListTestBase extends TestCase * Test to add a generic mock message. * @see QueueEntryListTestBase#getTestList() * @see QueueEntryListTestBase#getExpectedListLength() - * @see MockAMQMessage * @throws AMQException */ public void testAddGenericMessage() throws AMQException { final QueueEntryList<QueueEntry> list = getTestList(); - list.add(new MockAMQMessage(666)); + final ServerMessage message = createServerMessage(666l); + list.add(message); final QueueEntryIterator<?> iter = list.iterator(); int count = 0; @@ -85,6 +90,18 @@ public abstract class QueueEntryListTestBase extends TestCase } + private ServerMessage createServerMessage(long number) + { + final ServerMessage message = mock(ServerMessage.class); + when(message.getMessageNumber()).thenReturn(number); + MessageReference ref = mock(MessageReference.class); + AMQMessageHeader hdr = mock(AMQMessageHeader.class); + when(ref.getMessage()).thenReturn(message); + when(message.newReference()).thenReturn(ref); + when(message.getMessageHeader()).thenReturn(hdr); + return message; + } + /** * Test for getting the next element in a queue list. * @see QueueEntryListTestBase#getTestList() @@ -201,8 +218,8 @@ public abstract class QueueEntryListTestBase extends TestCase QueueEntryList<QueueEntry> list = getTestList(true); int i = 0; - QueueEntry queueEntry1 = list.add(new MockAMQMessage(i++)); - QueueEntry queueEntry2 = list.add(new MockAMQMessage(i++)); + QueueEntry queueEntry1 = list.add(createServerMessage(i++)); + QueueEntry queueEntry2 = list.add(createServerMessage(i++)); assertSame(queueEntry2, list.next(queueEntry1)); assertNull(list.next(queueEntry2)); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java index c37e6da729..3a41bb9c72 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java @@ -27,30 +27,24 @@ import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Matchers.contains; import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.when; +import java.util.Map; import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.DirectExchange; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.BaseQueue.PostEnqueueAction; import org.apache.qpid.server.queue.SimpleAMQQueue.QueueEntryFilter; -import org.apache.qpid.server.store.StoredMessage; -import org.apache.qpid.server.store.TestableMemoryMessageStore; import org.apache.qpid.server.subscription.MockSubscription; import org.apache.qpid.server.subscription.Subscription; -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.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; @@ -66,40 +60,12 @@ public class SimpleAMQQueueTest extends QpidTestCase private SimpleAMQQueue _queue; private VirtualHost _virtualHost; - private AMQShortString _qname = new AMQShortString("qname"); - private AMQShortString _owner = new AMQShortString("owner"); - private AMQShortString _routingKey = new AMQShortString("routing key"); + private String _qname = "qname"; + private String _owner = "owner"; + private String _routingKey = "routing key"; private DirectExchange _exchange; private MockSubscription _subscription = new MockSubscription(); - private FieldTable _arguments = null; - - private MessagePublishInfo info = new MessagePublishInfo() - { - - public AMQShortString getExchange() - { - return null; - } - - public void setExchange(AMQShortString exchange) - { - } - - public boolean isImmediate() - { - return false; - } - - public boolean isMandatory() - { - return false; - } - - public AMQShortString getRoutingKey() - { - return null; - } - }; + private Map<String,Object> _arguments = null; @Override public void setUp() throws Exception @@ -109,10 +75,10 @@ public class SimpleAMQQueueTest extends QpidTestCase _virtualHost = BrokerTestHelper.createVirtualHost(getClass().getName()); - _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), _qname.asString(), false, _owner.asString(), - false, false, _virtualHost, FieldTable.convertToMap(_arguments)); + _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner, + false, false, false, _arguments); - _exchange = (DirectExchange) _virtualHost.getExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME.toString()); + _exchange = (DirectExchange) _virtualHost.getExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME); } @Override @@ -133,8 +99,11 @@ public class SimpleAMQQueueTest extends QpidTestCase public void testCreateQueue() throws AMQException { _queue.stop(); - try { - _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), null, false, _owner.asString(), false, false, _virtualHost, FieldTable.convertToMap(_arguments)); + try + { + _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), null, + false, _owner, false, + false, false, _arguments); assertNull("Queue was created", _queue); } catch (IllegalArgumentException e) @@ -143,7 +112,8 @@ public class SimpleAMQQueueTest extends QpidTestCase e.getMessage().contains("name")); } - try { + try + { _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner, false,false, null, Collections.EMPTY_MAP); assertNull("Queue was created", _queue); } @@ -153,8 +123,10 @@ public class SimpleAMQQueueTest extends QpidTestCase e.getMessage().contains("Host")); } - _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), _qname.asString(), false, _owner.asString(), false, - false, _virtualHost, FieldTable.convertToMap(_arguments)); + _queue = (SimpleAMQQueue) _virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), + "differentName", false, + _owner, false, + false, false, _arguments); assertNotNull("Queue was not created", _queue); } @@ -165,7 +137,7 @@ public class SimpleAMQQueueTest extends QpidTestCase public void testBinding() throws AMQSecurityException, AMQInternalException { - _exchange.addBinding(String.valueOf(_routingKey), _queue, Collections.EMPTY_MAP); + _exchange.addBinding(_routingKey, _queue, Collections.EMPTY_MAP); assertTrue("Routing key was not bound", _exchange.isBound(_routingKey)); @@ -173,12 +145,12 @@ public class SimpleAMQQueueTest extends QpidTestCase _exchange.isBound(_routingKey,_queue)); assertEquals("Exchange binding count", 1, _queue.getBindings().size()); - assertEquals("Wrong exchange bound", String.valueOf(_routingKey), + assertEquals("Wrong exchange bound", _routingKey, _queue.getBindings().get(0).getBindingKey()); assertEquals("Wrong exchange bound", _exchange, _queue.getBindings().get(0).getExchange()); - _exchange.removeBinding(String.valueOf(_routingKey), _queue, Collections.EMPTY_MAP); + _exchange.removeBinding(_routingKey, _queue, Collections.EMPTY_MAP); assertFalse("Routing key was still bound", _exchange.isBound(_routingKey)); @@ -196,7 +168,7 @@ public class SimpleAMQQueueTest extends QpidTestCase _queue.getActiveConsumerCount()); // Check sending a message ends up with the subscriber - AMQMessage messageA = createMessage(new Long(24)); + ServerMessage messageA = createMessage(new Long(24)); _queue.enqueue(messageA); try { @@ -215,7 +187,7 @@ public class SimpleAMQQueueTest extends QpidTestCase assertFalse("Queue still has active consumer", 1 == _queue.getActiveConsumerCount()); - AMQMessage messageB = createMessage(new Long (25)); + ServerMessage messageB = createMessage(new Long (25)); _queue.enqueue(messageB); assertNull(_subscription.getQueueContext()); @@ -223,7 +195,7 @@ public class SimpleAMQQueueTest extends QpidTestCase public void testEnqueueMessageThenRegisterSubscription() throws AMQException, InterruptedException { - AMQMessage messageA = createMessage(new Long(24)); + ServerMessage messageA = createMessage(new Long(24)); _queue.enqueue(messageA); _queue.registerSubscription(_subscription, false); Thread.sleep(150); @@ -236,8 +208,8 @@ public class SimpleAMQQueueTest extends QpidTestCase */ public void testEnqueueTwoMessagesThenRegisterSubscription() throws Exception { - AMQMessage messageA = createMessage(new Long(24)); - AMQMessage messageB = createMessage(new Long(25)); + ServerMessage messageA = createMessage(new Long(24)); + ServerMessage messageB = createMessage(new Long(25)); _queue.enqueue(messageA); _queue.enqueue(messageB); _queue.registerSubscription(_subscription, false); @@ -263,9 +235,9 @@ public class SimpleAMQQueueTest extends QpidTestCase } }; - AMQMessage messageA = createMessage(new Long(24)); - AMQMessage messageB = createMessage(new Long(25)); - AMQMessage messageC = createMessage(new Long(26)); + ServerMessage messageA = createMessage(new Long(24)); + ServerMessage messageB = createMessage(new Long(25)); + ServerMessage messageC = createMessage(new Long(26)); /* Enqueue three messages */ @@ -313,9 +285,10 @@ public class SimpleAMQQueueTest extends QpidTestCase /* Enqueue one message with expiration set for a short time in the future */ - AMQMessage messageA = createMessage(new Long(24)); + ServerMessage messageA = createMessage(new Long(24)); int messageExpirationOffset = 200; - messageA.setExpiration(System.currentTimeMillis() + messageExpirationOffset); + final long expiration = System.currentTimeMillis() + messageExpirationOffset; + when(messageA.getExpiration()).thenReturn(expiration); _queue.enqueue(messageA, postEnqueueAction); @@ -357,9 +330,9 @@ public class SimpleAMQQueueTest extends QpidTestCase } }; - AMQMessage messageA = createMessage(new Long(24)); - AMQMessage messageB = createMessage(new Long(25)); - AMQMessage messageC = createMessage(new Long(26)); + ServerMessage messageA = createMessage(new Long(24)); + ServerMessage messageB = createMessage(new Long(25)); + ServerMessage messageC = createMessage(new Long(26)); /* Enqueue three messages */ @@ -410,8 +383,8 @@ public class SimpleAMQQueueTest extends QpidTestCase } }; - AMQMessage messageA = createMessage(new Long(24)); - AMQMessage messageB = createMessage(new Long(25)); + ServerMessage messageA = createMessage(new Long(24)); + ServerMessage messageB = createMessage(new Long(25)); /* Enqueue two messages */ @@ -444,7 +417,7 @@ public class SimpleAMQQueueTest extends QpidTestCase _queue.getActiveConsumerCount()); // Check sending a message ends up with the subscriber - AMQMessage messageA = createMessage(new Long(24)); + ServerMessage messageA = createMessage(new Long(24)); _queue.enqueue(messageA); try { @@ -489,7 +462,7 @@ public class SimpleAMQQueueTest extends QpidTestCase _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP); _queue.setDeleteOnNoConsumers(true); _queue.registerSubscription(_subscription, false); - AMQMessage message = createMessage(new Long(25)); + ServerMessage message = createMessage(new Long(25)); _queue.enqueue(message); _queue.unregisterSubscription(_subscription); assertTrue("Queue was not deleted when subscription was removed", @@ -500,7 +473,7 @@ public class SimpleAMQQueueTest extends QpidTestCase { _queue.registerSubscription(_subscription, false); Long id = new Long(26); - AMQMessage message = createMessage(id); + ServerMessage message = createMessage(id); _queue.enqueue(message); QueueEntry entry = _subscription.getQueueContext().getLastSeenEntry(); entry.setRedelivered(); @@ -512,7 +485,7 @@ public class SimpleAMQQueueTest extends QpidTestCase { // Create message Long messageId = new Long(23); - AMQMessage message = createMessage(messageId); + ServerMessage message = createMessage(messageId); // Put message on queue _queue.enqueue(message); @@ -529,7 +502,7 @@ public class SimpleAMQQueueTest extends QpidTestCase { // Create message Long messageId = new Long(i); - AMQMessage message = createMessage(messageId); + ServerMessage message = createMessage(messageId); // Put message on queue _queue.enqueue(message); } @@ -550,7 +523,7 @@ public class SimpleAMQQueueTest extends QpidTestCase { // Create message Long messageId = new Long(i); - AMQMessage message = createMessage(messageId); + ServerMessage message = createMessage(messageId); // Put message on queue _queue.enqueue(message); } @@ -571,7 +544,7 @@ public class SimpleAMQQueueTest extends QpidTestCase { // Create message Long messageId = new Long(i); - AMQMessage message = createMessage(messageId); + ServerMessage message = createMessage(messageId); // Put message on queue _queue.enqueue(message); } @@ -628,56 +601,6 @@ public class SimpleAMQQueueTest extends QpidTestCase assertEquals("Message ID was wrong", msgID, 10L); } - public void testEnqueueDequeueOfPersistentMessageToNonDurableQueue() throws AMQException - { - // Create IncomingMessage and nondurable queue - final IncomingMessage msg = new IncomingMessage(info); - ContentHeaderBody contentHeaderBody = new ContentHeaderBody(); - contentHeaderBody.setProperties(new BasicContentHeaderProperties()); - ((BasicContentHeaderProperties) contentHeaderBody.getProperties()).setDeliveryMode((byte) 2); - msg.setContentHeaderBody(contentHeaderBody); - - final ArrayList<BaseQueue> qs = new ArrayList<BaseQueue>(); - - // Send persistent message - - qs.add(_queue); - MessageMetaData metaData = msg.headersReceived(System.currentTimeMillis()); - TestableMemoryMessageStore store = (TestableMemoryMessageStore) _virtualHost.getMessageStore(); - StoredMessage handle = store.addMessage(metaData); - msg.setStoredMessage(handle); - - - ServerTransaction txn = new AutoCommitTransaction(store); - - txn.enqueue(qs, msg, new ServerTransaction.Action() - { - public void postCommit() - { - msg.enqueue(qs); - } - - public void onRollback() - { - } - }); - - // Check that it is enqueued - AMQQueue data = store.getMessages().get(1L); - assertNull(data); - - // Dequeue message - MockQueueEntry entry = new MockQueueEntry(); - AMQMessage amqmsg = new AMQMessage(handle); - - entry.setMessage(amqmsg); - _queue.dequeue(entry,null); - - // Check that it is dequeued - data = store.getMessages().get(1L); - assertNull(data); - } - /** * processQueue() is used when asynchronously delivering messages to @@ -784,7 +707,7 @@ public class SimpleAMQQueueTest extends QpidTestCase int expectedId = 0; for (int i = 0; i < messageNumber - 1; i++) { - Long id = ((AMQMessage) entries.get(i).getMessage()).getMessageId(); + Long id = ( entries.get(i).getMessage()).getMessageNumber(); if (i == dequeueMessageIndex) { assertFalse("Message with id " + dequeueMessageIndex @@ -832,7 +755,7 @@ public class SimpleAMQQueueTest extends QpidTestCase int expectedId = 0; for (int i = 0; i < messageNumber - 1; i++) { - Long id = ((AMQMessage) entries.get(i).getMessage()).getMessageId(); + Long id = (entries.get(i).getMessage()).getMessageNumber(); if (i == dequeueMessageIndex) { assertFalse("Message with id " + dequeueMessageIndex @@ -874,8 +797,8 @@ public class SimpleAMQQueueTest extends QpidTestCase assertNotNull("Null is returned from getMessagesOnTheQueue", entries); assertEquals("Expected " + (messageNumber - 2) + " number of messages but recieved " + entries.size(), messageNumber - 2, entries.size()); - assertEquals("Expected first entry with id 2", new Long(2), - ((AMQMessage) entries.get(0).getMessage()).getMessageId()); + assertEquals("Expected first entry with id 2", 2l, + (entries.get(0).getMessage()).getMessageNumber()); } /** @@ -922,8 +845,8 @@ public class SimpleAMQQueueTest extends QpidTestCase int dequeueMessageIndex = 1; // create queue with overridden method deliverAsync - SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("test"), - false, new AMQShortString("testOwner"), false, false, _virtualHost, null) + SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "test", + false, "testOwner", false, false, _virtualHost, null) { @Override public void deliverAsync(Subscription sub) @@ -993,8 +916,8 @@ public class SimpleAMQQueueTest extends QpidTestCase public void testEnqueueDequeuedEntry() { // create a queue where each even entry is considered a dequeued - SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("test"), false, - new AMQShortString("testOwner"), false, false, _virtualHost, new QueueEntryListFactory() + SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "test", false, + "testOwner", false, false, _virtualHost, new QueueEntryListFactory() { public QueueEntryList createQueueEntryList(AMQQueue queue) { @@ -1014,23 +937,23 @@ public class SimpleAMQQueueTest extends QpidTestCase { public boolean isDequeued() { - return (((AMQMessage) message).getMessageId().longValue() % 2 == 0); + return (message.getMessageNumber() % 2 == 0); } public boolean isDispensed() { - return (((AMQMessage) message).getMessageId().longValue() % 2 == 0); + return (message.getMessageNumber() % 2 == 0); } public boolean isAvailable() { - return !(((AMQMessage) message).getMessageId().longValue() % 2 == 0); + return !(message.getMessageNumber() % 2 == 0); } @Override public boolean acquire(Subscription sub) { - if(((AMQMessage) message).getMessageId().longValue() % 2 == 0) + if(message.getMessageNumber() % 2 == 0) { return false; } @@ -1063,16 +986,16 @@ public class SimpleAMQQueueTest extends QpidTestCase // assert received messages List<QueueEntry> messages = subscription.getMessages(); assertEquals("Only 2 messages should be returned", 2, messages.size()); - assertEquals("ID of first message should be 1", new Long(1), - ((AMQMessage) messages.get(0).getMessage()).getMessageId()); - assertEquals("ID of second message should be 3", new Long(3), - ((AMQMessage) messages.get(1).getMessage()).getMessageId()); + assertEquals("ID of first message should be 1", 1l, + (messages.get(0).getMessage()).getMessageNumber()); + assertEquals("ID of second message should be 3", 3l, + (messages.get(1).getMessage()).getMessageNumber()); } public void testActiveConsumerCount() throws Exception { - final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("testActiveConsumerCount"), false, - new AMQShortString("testOwner"), false, false, _virtualHost, new SimpleQueueEntryList.Factory(), null); + final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "testActiveConsumerCount", false, + "testOwner", false, false, _virtualHost, new SimpleQueueEntryList.Factory(), null); //verify adding an active subscription increases the count final MockSubscription subscription1 = new MockSubscription(); @@ -1177,7 +1100,7 @@ public class SimpleAMQQueueTest extends QpidTestCase assertEquals(messageNumber, entries.size()); for (int i = 0; i < messageNumber; i++) { - assertEquals(new Long(i), ((AMQMessage)entries.get(i).getMessage()).getMessageId()); + assertEquals((long)i, (entries.get(i).getMessage()).getMessageNumber()); } return entries; } @@ -1200,7 +1123,7 @@ public class SimpleAMQQueueTest extends QpidTestCase { // Create message Long messageId = new Long(i); - AMQMessage message = null; + ServerMessage message = null; try { message = createMessage(messageId); @@ -1280,55 +1203,31 @@ public class SimpleAMQQueueTest extends QpidTestCase return _subscription; } - public FieldTable getArguments() + public Map<String,Object> getArguments() { return _arguments; } - public void setArguments(FieldTable arguments) + public void setArguments(Map<String,Object> arguments) { _arguments = arguments; } - public class TestMessage extends AMQMessage - { - private final long _tag; - private int _count; - TestMessage(long tag, long messageId, MessagePublishInfo publishBody) - throws AMQException - { - this(tag, messageId, publishBody, new ContentHeaderBody(1, 1, new BasicContentHeaderProperties(), 0)); + protected ServerMessage createMessage(Long id) throws AMQException + { + ServerMessage message = mock(ServerMessage.class); + when(message.getMessageNumber()).thenReturn(id); - } - TestMessage(long tag, long messageId, MessagePublishInfo publishBody, ContentHeaderBody chb) - throws AMQException - { - super(new MockStoredMessage(messageId, publishBody, chb)); - _tag = tag; - } + MessageReference ref = mock(MessageReference.class); + when(ref.getMessage()).thenReturn(message); - public boolean incrementReference() - { - _count++; - return true; - } + AMQMessageHeader hdr = mock(AMQMessageHeader.class); + when(message.getMessageHeader()).thenReturn(hdr); - public void decrementReference() - { - _count--; - } - - void assertCountEquals(int expected) - { - assertEquals("Wrong count for message with tag " + _tag, expected, _count); - } - } + when(message.newReference()).thenReturn(ref); - protected AMQMessage createMessage(Long id) throws AMQException - { - AMQMessage messageA = new TestMessage(id, id, info); - return messageA; + return message; } class TestSimpleQueueEntryListFactory implements QueueEntryListFactory diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java index 4abb7233dc..c115af5a38 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java @@ -50,8 +50,8 @@ public class SimpleAMQQueueThreadPoolTest extends QpidTestCase try { - SimpleAMQQueue queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "test", false, - "owner", false, false, test, null); + SimpleAMQQueue queue = (SimpleAMQQueue) + test.createQueue(UUIDGenerator.generateRandomUUID(), "test", false, "owner", false, false, false, null); assertFalse("Creation did not start Pool.", ReferenceCountingExecutorService.getInstance().getPool().isShutdown()); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java index ac18bbe687..c2c2fc4b98 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryImplTest.java @@ -23,12 +23,16 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; import org.apache.qpid.server.message.ServerMessage; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class SimpleQueueEntryImplTest extends QueueEntryImplTestBase { private SimpleQueueEntryList queueEntryList = new SimpleQueueEntryList(new MockAMQQueue("test")); public QueueEntryImpl getQueueEntryImpl(int msgId) throws AMQException { - ServerMessage message = new MockAMQMessage(msgId); + ServerMessage message = mock(ServerMessage.class); + when(message.getMessageNumber()).thenReturn((long)msgId); return queueEntryList.add(message); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java index caf1eea09f..63b3a7d165 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleQueueEntryListTest.java @@ -21,13 +21,15 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.SimpleQueueEntryList.QueueEntryIteratorImpl; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class SimpleQueueEntryListTest extends QueueEntryListTestBase { private SimpleQueueEntryList _sqel; @@ -42,12 +44,17 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase _sqel = new SimpleQueueEntryList(_testQueue); for(int i = 1; i <= 100; i++) { - final ServerMessage msg = new MockAMQMessage(i); - final QueueEntry bleh = _sqel.add(msg); + final ServerMessage message = mock(ServerMessage.class); + when(message.getMessageNumber()).thenReturn((long) i); + MessageReference ref = mock(MessageReference.class); + when(ref.getMessage()).thenReturn(message); + when(message.newReference()).thenReturn(ref); + + final QueueEntry bleh = _sqel.add(message); assertNotNull("QE should not have been null", bleh); } } - + @Override protected void tearDown() { @@ -93,35 +100,41 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase } @Override - public AMQMessage getTestMessageToAdd() throws AMQException + public ServerMessage getTestMessageToAdd() throws AMQException { - return new MockAMQMessage(1l); + ServerMessage msg = mock(ServerMessage.class); + when(msg.getMessageNumber()).thenReturn(1l); + return msg; } public void testScavenge() throws Exception { SimpleQueueEntryList sqel = new SimpleQueueEntryList(null); ConcurrentHashMap<Integer,QueueEntry> entriesMap = new ConcurrentHashMap<Integer,QueueEntry>(); - - + + //Add messages to generate QueueEntry's for(int i = 1; i <= 100 ; i++) { - AMQMessage msg = new MockAMQMessage(i); - QueueEntry bleh = sqel.add(msg); + ServerMessage message = mock(ServerMessage.class); + when(message.getMessageNumber()).thenReturn((long) i); + MessageReference ref = mock(MessageReference.class); + when(ref.getMessage()).thenReturn(message); + when(message.newReference()).thenReturn(ref); + QueueEntry bleh = sqel.add(message); assertNotNull("QE should not have been null", bleh); entriesMap.put(i,bleh); } - + SimpleQueueEntryImpl head = sqel.getHead(); - - //We shall now delete some specific messages mid-queue that will lead to + + //We shall now delete some specific messages mid-queue that will lead to //requiring a scavenge once the requested threshold of 9 deletes is passed - + //Delete the 2nd message only assertTrue("Failed to delete QueueEntry", entriesMap.remove(2).delete()); verifyDeletedButPresentBeforeScavenge(head, 2); - + //Delete messages 12 to 14 assertTrue("Failed to delete QueueEntry", entriesMap.remove(12).delete()); verifyDeletedButPresentBeforeScavenge(head, 12); @@ -147,7 +160,7 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase //Delete message 99 - this is the 10th message deleted that is after the queue head //and so will invoke the scavenge() which is set to go after 9 previous deletions assertTrue("Failed to delete QueueEntry", entriesMap.remove(99).delete()); - + verifyAllDeletedMessagedNotPresent(head, entriesMap); } @@ -173,9 +186,9 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase assertNotNull("Initial entry should not have been null", entry); int count = 0; - + while (entry != null) - { + { assertFalse("Entry " + entry.getMessage().getMessageNumber() + " should not have been deleted", entry.isDeleted()); assertNotNull("QueueEntry "+entry.getMessage().getMessageNumber()+" was not found in the list of remaining entries " + remainingMessages, remainingMessages.get((int)(entry.getMessage().getMessageNumber()))); @@ -196,7 +209,8 @@ public class SimpleQueueEntryListTest extends QueueEntryListTestBase // create test entries for(int i = 0; i < numberOfEntries; i++) { - AMQMessage message = new MockAMQMessage(i); + ServerMessage message = mock(ServerMessage.class); + when(message.getMessageNumber()).thenReturn((long)i); entries[i] = queueEntryList.add(message); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java index 99e05851ca..acd0ccbdeb 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryImplTest.java @@ -19,9 +19,15 @@ */ package org.apache.qpid.server.queue; +import java.util.Collections; import org.apache.qpid.AMQException; +import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.ServerMessage; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class SortedQueueEntryImplTest extends QueueEntryImplTestBase { public final static String keys[] = { "CCC", "AAA", "BBB" }; @@ -29,7 +35,13 @@ public class SortedQueueEntryImplTest extends QueueEntryImplTestBase { private SelfValidatingSortedQueueEntryList queueEntryList = new SelfValidatingSortedQueueEntryList(new MockAMQQueue("test"),"KEY"); public QueueEntryImpl getQueueEntryImpl(int msgId) throws AMQException { - final ServerMessage message = new MockAMQMessage(msgId, "KEY", keys[msgId-1]); + final ServerMessage message = mock(ServerMessage.class); + AMQMessageHeader hdr = mock(AMQMessageHeader.class); + when(message.getMessageHeader()).thenReturn(hdr); + when(hdr.getHeader(eq("KEY"))).thenReturn(keys[msgId-1]); + when(hdr.containsHeader(eq("KEY"))).thenReturn(true); + when(hdr.getHeaderNames()).thenReturn(Collections.singleton("KEY")); + return queueEntryList.add(message); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java index 38b12f8250..7add2d4d43 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/queue/SortedQueueEntryListTest.java @@ -19,12 +19,18 @@ */ package org.apache.qpid.server.queue; +import java.util.Collections; import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import java.util.Arrays; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + public class SortedQueueEntryListTest extends QueueEntryListTestBase { private static SelfValidatingSortedQueueEntryList _sqel; @@ -113,7 +119,18 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase private ServerMessage generateTestMessage(final long id, final String keyValue) throws AMQException { - return new AMQMessage(new MockStoredMessage(id, "KEY", keyValue)); + final ServerMessage message = mock(ServerMessage.class); + AMQMessageHeader hdr = mock(AMQMessageHeader.class); + when(message.getMessageHeader()).thenReturn(hdr); + when(hdr.getHeader(eq("KEY"))).thenReturn(keyValue); + when(hdr.containsHeader(eq("KEY"))).thenReturn(true); + when(hdr.getHeaderNames()).thenReturn(Collections.singleton("KEY")); + MessageReference ref = mock(MessageReference.class); + when(ref.getMessage()).thenReturn(message); + when(message.newReference()).thenReturn(ref); + when(message.getMessageNumber()).thenReturn(id); + + return message; } public void testIterator() @@ -132,12 +149,12 @@ public class SortedQueueEntryListTest extends QueueEntryListTestBase private Object getSortedKeyValue(QueueEntryIterator<?> iter) { - return ((SortedQueueEntryImpl) iter.getNode()).getMessage().getMessageHeader().getHeader("KEY"); + return (iter.getNode()).getMessage().getMessageHeader().getHeader("KEY"); } private Long getMessageId(QueueEntryIterator<?> iter) { - return ((SortedQueueEntryImpl) iter.getNode()).getMessage().getMessageNumber(); + return (iter.getNode()).getMessage().getMessageNumber(); } public void testNonUniqueSortKeys() throws Exception diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java index a5d087593a..61506777c5 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java @@ -114,7 +114,7 @@ public class ExternalAuthenticationManagerTest extends QpidTestCase result.getStatus()); assertOnlyContainsWrapped(expectedPrincipal, result.getPrincipals()); - // Null princial + // Null principal saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", null); result = _manager.authenticate(saslServer, new byte[0]); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java index c6d166bc4c..fd8148f2ce 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java @@ -38,8 +38,6 @@ import java.util.UUID; import org.apache.commons.configuration.Configuration; import org.apache.qpid.AMQStoreException; import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.message.EnqueableMessage; @@ -48,15 +46,22 @@ 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.queue.AMQQueue; -import org.apache.qpid.server.queue.MockStoredMessage; import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler; import org.apache.qpid.server.store.Transaction.Record; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTestCase { private static final String EXCHANGE_NAME = "exchangeName"; + + private static final String EXCHANGE = org.apache.qpid.server.model.Exchange.class.getSimpleName(); + private static final String BINDING = org.apache.qpid.server.model.Binding.class.getSimpleName(); + private static final String QUEUE = Queue.class.getSimpleName(); + private String _storePath; private String _storeName; private MessageStore _messageStore; @@ -73,7 +78,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest private Exchange _exchange = mock(Exchange.class); private static final String ROUTING_KEY = "routingKey"; private static final String QUEUE_NAME = "queueName"; - private FieldTable _bindingArgs; + private Map<String,Object> _bindingArgs; private UUID _queueId; private UUID _exchangeId; private DurableConfigurationStore _configStore; @@ -101,14 +106,15 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest when(_messageStoreRecoveryHandler.begin()).thenReturn(_storedMessageRecoveryHandler); when(_logRecoveryHandler.begin(any(MessageStore.class))).thenReturn(_queueEntryRecoveryHandler); when(_queueEntryRecoveryHandler.completeQueueEntryRecovery()).thenReturn(_dtxRecordRecoveryHandler); - when(_exchange.getNameShortString()).thenReturn(AMQShortString.valueOf(EXCHANGE_NAME)); + when(_exchange.getName()).thenReturn(EXCHANGE_NAME); + when(_exchange.getId()).thenReturn(_exchangeId); when(_configuration.getString(eq(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY), anyString())).thenReturn( _storePath); when(_virtualHost.getAttribute(eq(VirtualHost.STORE_PATH))).thenReturn(_storePath); - _bindingArgs = new FieldTable(); - AMQShortString argKey = AMQPFilterTypes.JMS_SELECTOR.getValue(); + _bindingArgs = new HashMap<String, Object>(); + String argKey = AMQPFilterTypes.JMS_SELECTOR.toString(); String argValue = "some selector expression"; _bindingArgs.put(argKey, argValue); @@ -117,8 +123,16 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest public void tearDown() throws Exception { - FileUtils.delete(new File(_storePath), true); - super.tearDown(); + try + { + closeMessageStore(); + closeConfigStore(); + FileUtils.delete(new File(_storePath), true); + } + finally + { + super.tearDown(); + } } public void testCreateExchange() throws Exception @@ -127,7 +141,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest DurableConfigurationStoreHelper.createExchange(_configStore, exchange); reopenStore(); - verify(_recoveryHandler).configuredObject(eq(_exchangeId), eq(org.apache.qpid.server.model.Exchange.class.getName()), + verify(_recoveryHandler).configuredObject(eq(_exchangeId), eq(EXCHANGE), eq(map( org.apache.qpid.server.model.Exchange.NAME, getName(), org.apache.qpid.server.model.Exchange.TYPE, getName()+"Type", org.apache.qpid.server.model.Exchange.LIFETIME_POLICY, LifetimePolicy.AUTO_DELETE.toString()))); @@ -166,9 +180,9 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest public void testBindQueue() throws Exception { - AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false); + AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false, null); Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), ROUTING_KEY, queue, - _exchange, FieldTable.convertToMap(_bindingArgs)); + _exchange, _bindingArgs); DurableConfigurationStoreHelper.createBinding(_configStore, binding); reopenStore(); @@ -177,49 +191,48 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest map.put(org.apache.qpid.server.model.Binding.EXCHANGE, _exchange.getId().toString()); map.put(org.apache.qpid.server.model.Binding.QUEUE, queue.getId().toString()); map.put(org.apache.qpid.server.model.Binding.NAME, ROUTING_KEY); - map.put(org.apache.qpid.server.model.Binding.ARGUMENTS,FieldTable.convertToMap(_bindingArgs)); + map.put(org.apache.qpid.server.model.Binding.ARGUMENTS,_bindingArgs); - verify(_recoveryHandler).configuredObject(eq(binding.getId()), eq(org.apache.qpid.server.model.Binding.class.getName()), + verify(_recoveryHandler).configuredObject(eq(binding.getId()), eq(BINDING), eq(map)); } public void testUnbindQueue() throws Exception { - AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false); + AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false, null); Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), ROUTING_KEY, queue, - _exchange, FieldTable.convertToMap(_bindingArgs)); + _exchange, _bindingArgs); DurableConfigurationStoreHelper.createBinding(_configStore, binding); DurableConfigurationStoreHelper.removeBinding(_configStore, binding); reopenStore(); verify(_recoveryHandler, never()).configuredObject(any(UUID.class), - eq(org.apache.qpid.server.model.Binding.class.getName()), + eq(BINDING), anyMap()); } public void testCreateQueueAMQQueue() throws Exception { - AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true); - DurableConfigurationStoreHelper.createQueue(_configStore, queue, null); + AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, null); + DurableConfigurationStoreHelper.createQueue(_configStore, queue); reopenStore(); Map<String, Object> queueAttributes = new HashMap<String, Object>(); queueAttributes.put(Queue.NAME, getName()); queueAttributes.put(Queue.OWNER, getName()+"Owner"); queueAttributes.put(Queue.EXCLUSIVE, Boolean.TRUE); - verify(_recoveryHandler).configuredObject(eq(_queueId), eq(Queue.class.getName()), eq(queueAttributes)); + verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes)); } public void testCreateQueueAMQQueueFieldTable() throws Exception { - AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put("x-qpid-dlq-enabled", Boolean.TRUE); - attributes.put("x-qpid-maximum-delivery-count", new Integer(10)); + attributes.put(Queue.CREATE_DLQ_ON_CREATION, Boolean.TRUE); + attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 10); + AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, attributes); - FieldTable arguments = FieldTable.convertToFieldTable(attributes); - DurableConfigurationStoreHelper.createQueue(_configStore, queue, arguments); + DurableConfigurationStoreHelper.createQueue(_configStore, queue); reopenStore(); @@ -229,17 +242,17 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest queueAttributes.put(Queue.NAME, getName()); queueAttributes.put(Queue.OWNER, getName()+"Owner"); queueAttributes.put(Queue.EXCLUSIVE, Boolean.TRUE); - queueAttributes.put(Queue.ARGUMENTS, attributes); + queueAttributes.putAll(attributes); - verify(_recoveryHandler).configuredObject(eq(_queueId), eq(Queue.class.getName()), eq(queueAttributes)); + verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes)); } public void testCreateQueueAMQQueueWithAlternateExchange() throws Exception { Exchange alternateExchange = createTestAlternateExchange(); - AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, alternateExchange); - DurableConfigurationStoreHelper.createQueue(_configStore, queue, null); + AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, alternateExchange, null); + DurableConfigurationStoreHelper.createQueue(_configStore, queue); reopenStore(); @@ -249,7 +262,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest queueAttributes.put(Queue.EXCLUSIVE, Boolean.TRUE); queueAttributes.put(Queue.ALTERNATE_EXCHANGE, alternateExchange.getId().toString()); - verify(_recoveryHandler).configuredObject(eq(_queueId), eq(Queue.class.getName()), eq(queueAttributes)); + verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes)); } private Exchange createTestAlternateExchange() @@ -263,16 +276,15 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest public void testUpdateQueueExclusivity() throws Exception { // create queue - AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put("x-qpid-dlq-enabled", Boolean.TRUE); - attributes.put("x-qpid-maximum-delivery-count", new Integer(10)); - FieldTable arguments = FieldTable.convertToFieldTable(attributes); - DurableConfigurationStoreHelper.createQueue(_configStore, queue, arguments); + attributes.put(Queue.CREATE_DLQ_ON_CREATION, Boolean.TRUE); + attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 10); + AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, attributes); + + DurableConfigurationStoreHelper.createQueue(_configStore, queue); // update the queue to have exclusive=false - queue = createTestQueue(getName(), getName() + "Owner", false); - when(queue.getArguments()).thenReturn(attributes); + queue = createTestQueue(getName(), getName() + "Owner", false, attributes); DurableConfigurationStoreHelper.updateQueue(_configStore, queue); @@ -283,26 +295,24 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest queueAttributes.put(Queue.NAME, getName()); queueAttributes.put(Queue.OWNER, getName()+"Owner"); queueAttributes.put(Queue.EXCLUSIVE, Boolean.FALSE); - queueAttributes.put(Queue.ARGUMENTS, attributes); + queueAttributes.putAll(attributes); - verify(_recoveryHandler).configuredObject(eq(_queueId), eq(Queue.class.getName()), eq(queueAttributes)); + verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes)); } public void testUpdateQueueAlternateExchange() throws Exception { // create queue - AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put("x-qpid-dlq-enabled", Boolean.TRUE); - attributes.put("x-qpid-maximum-delivery-count", new Integer(10)); - FieldTable arguments = FieldTable.convertToFieldTable(attributes); - DurableConfigurationStoreHelper.createQueue(_configStore, queue, arguments); + attributes.put(Queue.CREATE_DLQ_ON_CREATION, Boolean.TRUE); + attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 10); + AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, attributes); + DurableConfigurationStoreHelper.createQueue(_configStore, queue); // update the queue to have exclusive=false Exchange alternateExchange = createTestAlternateExchange(); - queue = createTestQueue(getName(), getName() + "Owner", false, alternateExchange); - when(queue.getArguments()).thenReturn(attributes); + queue = createTestQueue(getName(), getName() + "Owner", false, alternateExchange, attributes); DurableConfigurationStoreHelper.updateQueue(_configStore, queue); @@ -313,21 +323,20 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest queueAttributes.put(Queue.NAME, getName()); queueAttributes.put(Queue.OWNER, getName()+"Owner"); queueAttributes.put(Queue.EXCLUSIVE, Boolean.FALSE); - queueAttributes.put(Queue.ARGUMENTS, attributes); + queueAttributes.putAll(attributes); queueAttributes.put(Queue.ALTERNATE_EXCHANGE, alternateExchange.getId().toString()); - verify(_recoveryHandler).configuredObject(eq(_queueId), eq(Queue.class.getName()), eq(queueAttributes)); + verify(_recoveryHandler).configuredObject(eq(_queueId), eq(QUEUE), eq(queueAttributes)); } public void testRemoveQueue() throws Exception { // create queue - AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put("x-qpid-dlq-enabled", Boolean.TRUE); - attributes.put("x-qpid-maximum-delivery-count", new Integer(10)); - FieldTable arguments = FieldTable.convertToFieldTable(attributes); - DurableConfigurationStoreHelper.createQueue(_configStore, queue, arguments); + attributes.put(Queue.CREATE_DLQ_ON_CREATION, Boolean.TRUE); + attributes.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, 10); + AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, attributes); + DurableConfigurationStoreHelper.createQueue(_configStore, queue); // remove queue DurableConfigurationStoreHelper.removeQueue(_configStore,queue); @@ -337,29 +346,51 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest anyMap()); } - private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive) throws AMQStoreException + private AMQQueue createTestQueue(String queueName, + String queueOwner, + boolean exclusive, + final Map<String, Object> arguments) throws AMQStoreException { - return createTestQueue(queueName, queueOwner, exclusive, null); + return createTestQueue(queueName, queueOwner, exclusive, null, arguments); } - private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive, Exchange alternateExchange) throws AMQStoreException + private AMQQueue createTestQueue(String queueName, + String queueOwner, + boolean exclusive, + Exchange alternateExchange, + final Map<String, Object> arguments) throws AMQStoreException { AMQQueue queue = mock(AMQQueue.class); when(queue.getName()).thenReturn(queueName); - when(queue.getNameShortString()).thenReturn(AMQShortString.valueOf(queueName)); - when(queue.getOwner()).thenReturn(AMQShortString.valueOf(queueOwner)); + when(queue.getOwner()).thenReturn(queueOwner); when(queue.isExclusive()).thenReturn(exclusive); when(queue.getId()).thenReturn(_queueId); when(queue.getAlternateExchange()).thenReturn(alternateExchange); + if(arguments != null && !arguments.isEmpty()) + { + when(queue.getAvailableAttributes()).thenReturn(arguments.keySet()); + final ArgumentCaptor<String> requestedAttribute = ArgumentCaptor.forClass(String.class); + when(queue.getAttribute(requestedAttribute.capture())).then( + new Answer() + { + + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable + { + String attrName = requestedAttribute.getValue(); + return arguments.get(attrName); + } + }); + } + return queue; } private Exchange createTestExchange() { Exchange exchange = mock(Exchange.class); - when(exchange.getNameShortString()).thenReturn(AMQShortString.valueOf(getName())); when(exchange.getName()).thenReturn(getName()); - when(exchange.getTypeShortString()).thenReturn(AMQShortString.valueOf(getName() + "Type")); + when(exchange.getTypeName()).thenReturn(getName() + "Type"); when(exchange.isAutoDelete()).thenReturn(true); when(exchange.getId()).thenReturn(_exchangeId); return exchange; @@ -367,53 +398,21 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest private void reopenStore() throws Exception { - onReopenStore(); - if (_messageStore != null) - { - _messageStore.close(); - } + closeMessageStore(); + closeConfigStore(); _messageStore = createMessageStore(); _configStore = createConfigStore(); - _configStore.configureConfigStore(_storeName, _recoveryHandler, _virtualHost); - _messageStore.configureMessageStore(_storeName, _messageStoreRecoveryHandler, _logRecoveryHandler); + _configStore.configureConfigStore(_virtualHost, _recoveryHandler); + _messageStore.configureMessageStore(_virtualHost, _messageStoreRecoveryHandler, _logRecoveryHandler); _messageStore.activate(); } - protected abstract void onReopenStore(); + protected abstract MessageStore createMessageStore() throws Exception; + protected abstract DurableConfigurationStore createConfigStore() throws Exception; + protected abstract void closeMessageStore() throws Exception; + protected abstract void closeConfigStore() throws Exception; - abstract protected MessageStore createMessageStore() throws Exception; - /*{ - String storeClass = System.getProperty(MESSAGE_STORE_CLASS_NAME_KEY); - if (storeClass == null) - { - storeClass = DerbyMessageStore.class.getName(); - } - CurrentActor.set(new TestLogActor(new SystemOutMessageLogger())); - MessageStore messageStore = (MessageStore) Class.forName(storeClass).newInstance(); - return messageStore; - } -*/ - abstract protected DurableConfigurationStore createConfigStore() throws Exception; - /*{ - String storeClass = System.getProperty(CONFIGURATION_STORE_CLASS_NAME_KEY); - if (storeClass == null) - { - storeClass = DerbyMessageStore.class.getName(); - } - Class<DurableConfigurationStore> clazz = (Class<DurableConfigurationStore>) Class.forName(storeClass); - DurableConfigurationStore configurationStore ; - if(clazz.isInstance(_messageStore)) - { - configurationStore = (DurableConfigurationStore) _messageStore; - } - else - { - configurationStore = (DurableConfigurationStore) Class.forName(storeClass).newInstance(); - } - return configurationStore; - } -*/ public void testRecordXid() throws Exception { Record enqueueRecord = getTestRecord(1); @@ -445,7 +444,9 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest EnqueableMessage message1 = mock(EnqueableMessage.class); when(message1.isPersistent()).thenReturn(true); when(message1.getMessageNumber()).thenReturn(messageNumber); - when(message1.getStoredMessage()).thenReturn(new MockStoredMessage(messageNumber)); + final StoredMessage storedMessage = mock(StoredMessage.class); + when(storedMessage.getMessageNumber()).thenReturn(messageNumber); + when(message1.getStoredMessage()).thenReturn(storedMessage); Record enqueueRecord = new TestRecord(queue1, message1); return enqueueRecord; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java new file mode 100644 index 0000000000..b6300e6f48 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java @@ -0,0 +1,299 @@ +/* + * + * 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.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.test.utils.QpidTestCase; +import org.mockito.InOrder; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyMap; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class JsonFileConfigStoreTest extends QpidTestCase +{ + private final ConfigurationRecoveryHandler _recoveryHandler = mock(ConfigurationRecoveryHandler.class); + private VirtualHost _virtualHost; + private JsonFileConfigStore _store; + + @Override + public void setUp() throws Exception + { + super.setUp(); + removeStoreFile(); + _virtualHost = mock(VirtualHost.class); + when(_virtualHost.getName()).thenReturn(getName()); + when(_virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH)).thenReturn(TMP_FOLDER); + _store = new JsonFileConfigStore(); + } + + @Override + public void tearDown() throws Exception + { + removeStoreFile(); + } + + private void removeStoreFile() + { + File file = new File(TMP_FOLDER, getName() + ".json"); + if(file.exists()) + { + file.delete(); + } + } + + public void testNoStorePath() throws Exception + { + when(_virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH)).thenReturn(null); + try + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + fail("Store should not successfully configure if there is no path set"); + } + catch (AMQStoreException e) + { + // pass + } + } + + + public void testInvalidStorePath() throws Exception + { + when(_virtualHost.getAttribute(VirtualHost.CONFIG_STORE_PATH)).thenReturn(System.getProperty("file.separator")); + try + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + fail("Store should not successfully configure if there is an invalid path set"); + } + catch (AMQStoreException e) + { + // pass + } + } + + public void testStartFromNoStore() throws Exception + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + InOrder inorder = inOrder(_recoveryHandler); + inorder.verify(_recoveryHandler).beginConfigurationRecovery(eq(_store), eq(0)); + inorder.verify(_recoveryHandler,never()).configuredObject(any(UUID.class),anyString(),anyMap()); + inorder.verify(_recoveryHandler).completeConfigurationRecovery(); + _store.close(); + } + + public void testUpdatedConfigVersionIsRetained() throws Exception + { + final int NEW_CONFIG_VERSION = 42; + when(_recoveryHandler.completeConfigurationRecovery()).thenReturn(NEW_CONFIG_VERSION); + + _store.configureConfigStore(_virtualHost, _recoveryHandler); + _store.close(); + + _store.configureConfigStore(_virtualHost, _recoveryHandler); + InOrder inorder = inOrder(_recoveryHandler); + + // first time the config version should be the initial version - 0 + inorder.verify(_recoveryHandler).beginConfigurationRecovery(eq(_store), eq(0)); + + // second time the config version should be the updated version + inorder.verify(_recoveryHandler).beginConfigurationRecovery(eq(_store), eq(NEW_CONFIG_VERSION)); + + _store.close(); + } + + public void testCreateObject() throws Exception + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + 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(queueId, queueType, queueAttr); + _store.close(); + + _store.configureConfigStore(_virtualHost, _recoveryHandler); + verify(_recoveryHandler).configuredObject(eq(queueId), eq(queueType), eq(queueAttr)); + _store.close(); + } + + public void testCreateAndUpdateObject() throws Exception + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + final UUID queueId = new UUID(0, 1); + final String queueType = Queue.class.getSimpleName(); + Map<String,Object> queueAttr = Collections.singletonMap("name", (Object) "q1"); + + _store.create(queueId, queueType, queueAttr); + + + queueAttr = new HashMap<String,Object>(queueAttr); + queueAttr.put("owner", "theowner"); + _store.update(queueId, queueType, queueAttr); + + _store.close(); + + _store.configureConfigStore(_virtualHost, _recoveryHandler); + verify(_recoveryHandler).configuredObject(eq(queueId), eq(queueType), eq(queueAttr)); + _store.close(); + } + + + public void testCreateAndRemoveObject() throws Exception + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + final UUID queueId = new UUID(0, 1); + final String queueType = Queue.class.getSimpleName(); + Map<String,Object> queueAttr = Collections.singletonMap("name", (Object) "q1"); + + _store.create(queueId, queueType, queueAttr); + + + _store.remove(queueId, queueType); + + _store.close(); + + _store.configureConfigStore(_virtualHost, _recoveryHandler); + verify(_recoveryHandler, never()).configuredObject(any(UUID.class), anyString(), anyMap()); + _store.close(); + } + + public void testCreateUnknownObjectType() throws Exception + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + try + { + _store.create(UUID.randomUUID(), "wibble", Collections.<String, Object>emptyMap()); + fail("Should not be able to create instance of type wibble"); + } + catch (AMQStoreException e) + { + // pass + } + } + + public void testTwoObjectsWithSameId() throws Exception + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + final UUID id = UUID.randomUUID(); + _store.create(id, "Queue", Collections.<String, Object>emptyMap()); + try + { + _store.create(id, "Exchange", Collections.<String, Object>emptyMap()); + fail("Should not be able to create two objects with same id"); + } + catch (AMQStoreException e) + { + // pass + } + } + + + public void testChangeTypeOfObject() throws Exception + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + final UUID id = UUID.randomUUID(); + _store.create(id, "Queue", Collections.<String, Object>emptyMap()); + _store.close(); + _store.configureConfigStore(_virtualHost, _recoveryHandler); + + try + { + _store.update(id, "Exchange", Collections.<String, Object>emptyMap()); + fail("Should not be able to update object to different type"); + } + catch (AMQStoreException e) + { + // pass + } + } + + public void testLockFileGuaranteesExclusiveAccess() throws Exception + { + _store.configureConfigStore(_virtualHost, _recoveryHandler); + + JsonFileConfigStore secondStore = new JsonFileConfigStore(); + + try + { + secondStore.configureConfigStore(_virtualHost, _recoveryHandler); + fail("Should not be able to open a second store with the same path"); + } + catch(AMQStoreException e) + { + // pass + } + _store.close(); + secondStore.configureConfigStore(_virtualHost, _recoveryHandler); + + + } + + public void testCreatedNestedObjects() throws Exception + { + + _store.configureConfigStore(_virtualHost, _recoveryHandler); + final UUID queueId = new UUID(0, 1); + final UUID queue2Id = new UUID(1, 1); + + final Map<String, Object> EMPTY_ATTR = Collections.emptyMap(); + final UUID exchangeId = new UUID(0, 2); + final Map<String, Object> bindingAttributes = new HashMap<String, Object>(); + bindingAttributes.put(Binding.EXCHANGE, exchangeId); + bindingAttributes.put(Binding.QUEUE, queueId); + final Map<String, Object> binding2Attributes = new HashMap<String, Object>(); + binding2Attributes.put(Binding.EXCHANGE, exchangeId); + binding2Attributes.put(Binding.QUEUE, queue2Id); + + final UUID bindingId = new UUID(0, 3); + final UUID binding2Id = new UUID(1, 3); + + _store.create(queueId, "Queue", EMPTY_ATTR); + _store.create(queue2Id, "Queue", EMPTY_ATTR); + _store.create(exchangeId, "Exchange", EMPTY_ATTR); + _store.update(true, + new ConfiguredObjectRecord(bindingId, "Binding", bindingAttributes), + new ConfiguredObjectRecord(binding2Id, "Binding", binding2Attributes)); + _store.close(); + _store.configureConfigStore(_virtualHost, _recoveryHandler); + verify(_recoveryHandler).configuredObject(eq(queueId), eq("Queue"), eq(EMPTY_ATTR)); + verify(_recoveryHandler).configuredObject(eq(queue2Id), eq("Queue"), eq(EMPTY_ATTR)); + verify(_recoveryHandler).configuredObject(eq(exchangeId), eq("Exchange"), eq(EMPTY_ATTR)); + verify(_recoveryHandler).configuredObject(eq(bindingId),eq("Binding"), eq(bindingAttributes)); + verify(_recoveryHandler).configuredObject(eq(binding2Id),eq("Binding"), eq(binding2Attributes)); + _store.close(); + + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java index f57195b2d7..b23890b10c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java @@ -27,15 +27,8 @@ import java.util.List; import java.util.UUID; import org.apache.log4j.Logger; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.framing.ProtocolVersion; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl; import org.apache.qpid.server.message.EnqueableMessage; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.plugin.MessageMetaDataType; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; @@ -73,10 +66,13 @@ public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase imple VirtualHost vhost = mock(VirtualHost.class); when(vhost.getAttribute(eq(VirtualHost.STORE_PATH))).thenReturn(_storeLocation.getAbsolutePath()); + when(vhost.getName()).thenReturn("test"); + applyStoreSpecificConfiguration(vhost); _store = createStore(); - ((DurableConfigurationStore)_store).configureConfigStore("test", null, vhost); + ((DurableConfigurationStore)_store).configureConfigStore(vhost, null); + _store.configureMessageStore(vhost, null, null); _transactionResource = UUID.randomUUID(); _events = new ArrayList<Event>(); @@ -86,8 +82,18 @@ public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase imple @Override public void tearDown() throws Exception { - super.tearDown(); - FileUtils.delete(_storeLocation, true); + try + { + super.tearDown(); + } + finally + { + if (_store != null) + { + _store.close(); + } + FileUtils.delete(_storeLocation, true); + } } public void testOverflow() throws Exception @@ -115,23 +121,25 @@ public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase imple protected EnqueableMessage addMessage(long id) { - MessagePublishInfo pubInfoBody = new MessagePublishInfoImpl(new AMQShortString(getName()), false, false, - new AMQShortString(getName())); - BasicContentHeaderProperties props = new BasicContentHeaderProperties(); - props.setDeliveryMode(Integer.valueOf(BasicContentHeaderProperties.PERSISTENT).byteValue()); - props.setContentType(getTestName()); - - MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9); - int classForBasic = methodRegistry.createBasicQosOkBody().getClazz(); - ContentHeaderBody contentHeaderBody = new ContentHeaderBody(classForBasic, 1, props, MESSAGE_DATA.length); - - MessageMetaData metaData = new MessageMetaData(pubInfoBody, contentHeaderBody, 1); - StoredMessage<MessageMetaData> handle = _store.addMessage(metaData); + StorableMessageMetaData metaData = createMetaData(id, MESSAGE_DATA.length); + StoredMessage handle = _store.addMessage(metaData); handle.addContent(0, ByteBuffer.wrap(MESSAGE_DATA)); TestMessage message = new TestMessage(id, handle); return message; } + private StorableMessageMetaData createMetaData(long id, int length) + { + StorableMessageMetaData metaData = mock(StorableMessageMetaData.class); + when(metaData.isPersistent()).thenReturn(true); + when(metaData.getContentSize()).thenReturn(length); + when(metaData.getStorableSize()).thenReturn(0); + MessageMetaDataType type = mock(MessageMetaDataType.class); + when(type.ordinal()).thenReturn(-1); + when(metaData.getType()).thenReturn(type); + return metaData; + } + @Override public void event(Event event) { diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java index 2d68e94fcd..7ebfd54df6 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTestCase.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.store; import static org.mockito.Matchers.any; -import static org.mockito.Matchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -53,16 +52,18 @@ public abstract class MessageStoreTestCase extends QpidTestCase _dtxRecordRecoveryHandler = mock(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler.class); _virtualHost = mock(VirtualHost.class); + when(_messageStoreRecoveryHandler.begin()).thenReturn(_storedMessageRecoveryHandler); when(_logRecoveryHandler.begin(any(MessageStore.class))).thenReturn(_queueEntryRecoveryHandler); when(_queueEntryRecoveryHandler.completeQueueEntryRecovery()).thenReturn(_dtxRecordRecoveryHandler); setUpStoreConfiguration(_virtualHost); + when(_virtualHost.getName()).thenReturn(getTestName()); _store = createMessageStore(); - ((DurableConfigurationStore)_store).configureConfigStore(getTestName(), _recoveryHandler, _virtualHost); + ((DurableConfigurationStore)_store).configureConfigStore(_virtualHost, _recoveryHandler); - _store.configureMessageStore(getTestName(), _messageStoreRecoveryHandler, _logRecoveryHandler); + _store.configureMessageStore(_virtualHost, _messageStoreRecoveryHandler, _logRecoveryHandler); } protected abstract void setUpStoreConfiguration(VirtualHost virtualHost) throws Exception; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java new file mode 100644 index 0000000000..32df355c07 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStore.java @@ -0,0 +1,34 @@ +/* + * + * 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; + + +/** A simple message store that stores the messages in a thread-safe structure in memory. */ +public class TestMemoryMessageStore extends AbstractMemoryMessageStore +{ + public static final String TYPE = "TestMemory"; + + @Override + public String getStoreType() + { + return TYPE; + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java new file mode 100644 index 0000000000..fd2d4215ab --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestMemoryMessageStoreFactory.java @@ -0,0 +1,54 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.server.store; + +import java.util.Collections; +import java.util.Map; +import org.apache.commons.configuration.Configuration; +import org.apache.qpid.server.plugin.MessageStoreFactory; + +public class TestMemoryMessageStoreFactory implements MessageStoreFactory +{ + + @Override + public String getType() + { + return TestMemoryMessageStore.TYPE; + } + + @Override + public MessageStore createMessageStore() + { + return new TestMemoryMessageStore(); + } + + @Override + public Map<String, Object> convertStoreConfiguration(Configuration configuration) + { + return Collections.emptyMap(); + } + + @Override + public void validateAttributes(Map<String, Object> attributes) + { + } +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java index 210408f490..bb3c0cf535 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStore.java @@ -32,7 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger; /** * Adds some extra methods to the memory message store for testing purposes. */ -public class TestableMemoryMessageStore extends MemoryMessageStore +public class TestableMemoryMessageStore extends TestMemoryMessageStore { private final Map<Long, AMQQueue> _messages = new HashMap<Long, AMQQueue>(); private final AtomicInteger _messageCount = new AtomicInteger(0); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java index ed60d5374b..b26d7530aa 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java @@ -47,7 +47,7 @@ public class MockSubscription implements Subscription { private boolean _closed = false; - private AMQShortString tag = new AMQShortString("mocktag"); + private String tag = "mocktag"; private AMQQueue queue = null; private StateListener _listener = null; private volatile AMQQueue.Context _queueContext = null; @@ -84,7 +84,7 @@ public class MockSubscription implements Subscription public String getConsumerName() { - return tag == null ? null : tag.asString(); + return tag; } public long getSubscriptionID() @@ -569,5 +569,11 @@ public class MockSubscription implements Subscription { return false; } + + @Override + public String getVirtualHostName() + { + return null; + } } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java index 24cdf34360..cb1fc2737d 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java @@ -31,11 +31,8 @@ import java.util.UUID; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.configuration.store.JsonConfigurationEntryStore; import org.apache.qpid.server.exchange.DefaultExchangeFactory; @@ -47,8 +44,6 @@ import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.logging.actors.TestLogActor; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.protocol.AMQProtocolSession; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.security.SecurityManager; @@ -143,33 +138,35 @@ public class BrokerTestHelper return vhostConfig; } - public static AMQChannel createChannel(int channelId, AMQProtocolSession session) throws AMQException + public static AMQSessionModel createSession(int channelId, AMQConnectionModel connection) throws AMQException { - AMQChannel channel = new AMQChannel(session, channelId, session.getVirtualHost().getMessageStore()); - session.addChannel(channel); - return channel; + AMQSessionModel session = mock(AMQSessionModel.class); + when(session.getConnectionModel()).thenReturn(connection); + when(session.getChannelId()).thenReturn(channelId); + return session; } - public static AMQChannel createChannel(int channelId) throws Exception + public static AMQSessionModel createSession(int channelId) throws Exception { - InternalTestProtocolSession session = createSession(); - return createChannel(channelId, session); + AMQConnectionModel session = createConnection(); + return createSession(channelId, session); } - public static AMQChannel createChannel() throws Exception + public static AMQSessionModel createSession() throws Exception { - return createChannel(1); + return createSession(1); } - public static InternalTestProtocolSession createSession() throws Exception + public static AMQConnectionModel createConnection() throws Exception { - return createSession("test"); + return createConnection("test"); } - public static InternalTestProtocolSession createSession(String hostName) throws Exception + public static AMQConnectionModel createConnection(String hostName) throws Exception { VirtualHost virtualHost = createVirtualHost(hostName); - return new InternalTestProtocolSession(virtualHost, createBrokerMock()); + AMQConnectionModel connection = mock(AMQConnectionModel.class); + return connection; } public static Exchange createExchange(String hostName) throws Exception @@ -182,44 +179,10 @@ public class BrokerTestHelper return factory.createExchange("amp.direct", "direct", false, false); } - public static void publishMessages(AMQChannel channel, int numberOfMessages, String queueName, String exchangeName) throws AMQException - { - AMQShortString rouningKey = new AMQShortString(queueName); - AMQShortString exchangeNameAsShortString = new AMQShortString(exchangeName); - MessagePublishInfo info = mock(MessagePublishInfo.class); - when(info.getExchange()).thenReturn(exchangeNameAsShortString); - when(info.getRoutingKey()).thenReturn(rouningKey); - - Exchange exchange = channel.getVirtualHost().getExchange(exchangeName); - for (int count = 0; count < numberOfMessages; count++) - { - channel.setPublishFrame(info, exchange); - - // Set the body size - ContentHeaderBody _headerBody = new ContentHeaderBody(); - _headerBody.setBodySize(0); - - // Set Minimum properties - BasicContentHeaderProperties properties = new BasicContentHeaderProperties(); - - properties.setExpiration(0L); - properties.setTimestamp(System.currentTimeMillis()); - - // Make Message Persistent - properties.setDeliveryMode((byte) 2); - - _headerBody.setProperties(properties); - - channel.publishContentHeader(_headerBody); - } - channel.sync(); - } - public static SimpleAMQQueue createQueue(String queueName, VirtualHost virtualHost) throws AMQException { - SimpleAMQQueue queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, null, - false, false, virtualHost, Collections.<String, Object>emptyMap()); - virtualHost.getQueueRegistry().registerQueue(queue); + SimpleAMQQueue queue = (SimpleAMQQueue) virtualHost.createQueue(UUIDGenerator.generateRandomUUID(), queueName, false, null, + false, false, false, Collections.<String, Object>emptyMap()); return queue; } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java new file mode 100644 index 0000000000..987a541d05 --- /dev/null +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/DurableConfigurationRecovererTest.java @@ -0,0 +1,479 @@ +/* + * + * 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.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.apache.qpid.AMQStoreException; +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.exchange.DirectExchange; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.exchange.ExchangeFactory; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.exchange.HeadersExchange; +import org.apache.qpid.server.exchange.TopicExchange; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.plugin.ExchangeType; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueFactory; +import org.apache.qpid.server.store.ConfiguredObjectRecord; +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.test.utils.QpidTestCase; +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyBoolean; +import static org.mockito.Matchers.anyString; +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 static org.apache.qpid.server.model.VirtualHost.CURRENT_CONFIG_VERSION; + +public class DurableConfigurationRecovererTest extends QpidTestCase +{ + private static final UUID QUEUE_ID = new UUID(0,0); + private static final UUID TOPIC_EXCHANGE_ID = new UUID(0,1); + private static final UUID DIRECT_EXCHANGE_ID = new UUID(0,2); + private static final String CUSTOM_EXCHANGE_NAME = "customExchange"; + + private DurableConfigurationRecoverer _durableConfigurationRecoverer; + private Exchange _directExchange; + private Exchange _topicExchange; + private VirtualHost _vhost; + private DurableConfigurationStore _store; + private ExchangeFactory _exchangeFactory; + private ExchangeRegistry _exchangeRegistry; + private QueueFactory _queueFactory; + + @Override + public void setUp() throws Exception + { + super.setUp(); + + + _directExchange = mock(Exchange.class); + when(_directExchange.getType()).thenReturn(DirectExchange.TYPE); + + + _topicExchange = mock(Exchange.class); + when(_topicExchange.getType()).thenReturn(TopicExchange.TYPE); + + AMQQueue queue = mock(AMQQueue.class); + + _vhost = mock(VirtualHost.class); + + _exchangeRegistry = mock(ExchangeRegistry.class); + when(_exchangeRegistry.getExchange(eq(DIRECT_EXCHANGE_ID))).thenReturn(_directExchange); + when(_exchangeRegistry.getExchange(eq(TOPIC_EXCHANGE_ID))).thenReturn(_topicExchange); + + when(_vhost.getQueue(eq(QUEUE_ID))).thenReturn(queue); + + final ArgumentCaptor<Exchange> registeredExchange = ArgumentCaptor.forClass(Exchange.class); + doAnswer(new Answer() + { + + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable + { + Exchange exchange = registeredExchange.getValue(); + when(_exchangeRegistry.getExchange(eq(exchange.getId()))).thenReturn(exchange); + when(_exchangeRegistry.getExchange(eq(exchange.getName()))).thenReturn(exchange); + return null; + } + }).when(_exchangeRegistry).registerExchange(registeredExchange.capture()); + + + + final ArgumentCaptor<UUID> idArg = ArgumentCaptor.forClass(UUID.class); + final ArgumentCaptor<String> queueArg = ArgumentCaptor.forClass(String.class); + final ArgumentCaptor<Map> argsArg = ArgumentCaptor.forClass(Map.class); + + _queueFactory = mock(QueueFactory.class); + + when(_queueFactory.restoreQueue(idArg.capture(), queueArg.capture(), + anyString(), anyBoolean(), anyBoolean(), anyBoolean(), argsArg.capture())).then( + new Answer() + { + + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable + { + final AMQQueue queue = mock(AMQQueue.class); + + final String queueName = queueArg.getValue(); + final UUID queueId = idArg.getValue(); + + when(queue.getName()).thenReturn(queueName); + when(queue.getId()).thenReturn(queueId); + when(_vhost.getQueue(eq(queueName))).thenReturn(queue); + when(_vhost.getQueue(eq(queueId))).thenReturn(queue); + + final ArgumentCaptor<Exchange> altExchangeArg = ArgumentCaptor.forClass(Exchange.class); + doAnswer( + new Answer() + { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable + { + final Exchange value = altExchangeArg.getValue(); + when(queue.getAlternateExchange()).thenReturn(value); + return null; + } + } + ).when(queue).setAlternateExchange(altExchangeArg.capture()); + + Map args = argsArg.getValue(); + if(args.containsKey(Queue.ALTERNATE_EXCHANGE)) + { + final UUID exchangeId = UUID.fromString(args.get(Queue.ALTERNATE_EXCHANGE).toString()); + final Exchange exchange = _exchangeRegistry.getExchange(exchangeId); + queue.setAlternateExchange(exchange); + } + return queue; + } + }); + + _exchangeFactory = mock(ExchangeFactory.class); + + + DurableConfiguredObjectRecoverer[] recoverers = { + new QueueRecoverer(_vhost, _exchangeRegistry, _queueFactory), + new ExchangeRecoverer(_exchangeRegistry, _exchangeFactory), + new BindingRecoverer(_vhost, _exchangeRegistry) + }; + + 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, _exchangeRegistry)); + + _store = mock(DurableConfigurationStore.class); + + CurrentActor.set(mock(LogActor.class)); + } + + public void testUpgradeEmptyStore() throws Exception + { + _durableConfigurationRecoverer.beginConfigurationRecovery(_store, 0); + assertEquals("Did not upgrade to the expected version", + CURRENT_CONFIG_VERSION, + _durableConfigurationRecoverer.completeConfigurationRecovery()); + } + + public void testUpgradeNewerStoreFails() throws Exception + { + try + { + _durableConfigurationRecoverer.beginConfigurationRecovery(_store, CURRENT_CONFIG_VERSION + 1); + _durableConfigurationRecoverer.completeConfigurationRecovery(); + fail("Should not be able to start when config model is newer than current"); + } + catch (IllegalStateException e) + { + // pass + } + } + + public void testUpgradeRemovesBindingsToNonTopicExchanges() throws Exception + { + + _durableConfigurationRecoverer.beginConfigurationRecovery(_store, 0); + + _durableConfigurationRecoverer.configuredObject(new UUID(1, 0), + "org.apache.qpid.server.model.Binding", + createBinding("key", + DIRECT_EXCHANGE_ID, + QUEUE_ID, + "x-filter-jms-selector", + "wibble")); + + final ConfiguredObjectRecord[] expected = { + new ConfiguredObjectRecord(new UUID(1, 0), "Binding", + createBinding("key", DIRECT_EXCHANGE_ID, QUEUE_ID)) + }; + + verifyCorrectUpdates(expected); + + _durableConfigurationRecoverer.completeConfigurationRecovery(); + } + + + + public void testUpgradeOnlyRemovesSelectorBindings() throws Exception + { + + _durableConfigurationRecoverer.beginConfigurationRecovery(_store, 0); + + _durableConfigurationRecoverer.configuredObject(new UUID(1, 0), + "org.apache.qpid.server.model.Binding", + createBinding("key", + DIRECT_EXCHANGE_ID, + QUEUE_ID, + "x-filter-jms-selector", + "wibble", + "not-a-selector", + "moo")); + + + final UUID customExchangeId = new UUID(3,0); + + _durableConfigurationRecoverer.configuredObject(new UUID(2, 0), + "org.apache.qpid.server.model.Binding", + createBinding("key", + customExchangeId, + QUEUE_ID, + "x-filter-jms-selector", + "wibble", + "not-a-selector", + "moo")); + + _durableConfigurationRecoverer.configuredObject(customExchangeId, + "org.apache.qpid.server.model.Exchange", + createExchange(CUSTOM_EXCHANGE_NAME, HeadersExchange.TYPE)); + + final Exchange customExchange = mock(Exchange.class); + + when(_exchangeFactory.restoreExchange(eq(customExchangeId), + eq(CUSTOM_EXCHANGE_NAME), + eq(HeadersExchange.TYPE.getType()), + anyBoolean())).thenReturn(customExchange); + + final ConfiguredObjectRecord[] expected = { + new ConfiguredObjectRecord(new UUID(1, 0), "org.apache.qpid.server.model.Binding", + createBinding("key", DIRECT_EXCHANGE_ID, QUEUE_ID, "not-a-selector", "moo")), + new ConfiguredObjectRecord(new UUID(2, 0), "org.apache.qpid.server.model.Binding", + createBinding("key", customExchangeId, QUEUE_ID, "not-a-selector", "moo")) + }; + + verifyCorrectUpdates(expected); + + _durableConfigurationRecoverer.completeConfigurationRecovery(); + } + + + public void testUpgradeKeepsBindingsToTopicExchanges() throws Exception + { + + _durableConfigurationRecoverer.beginConfigurationRecovery(_store, 0); + + _durableConfigurationRecoverer.configuredObject(new UUID(1, 0), + "org.apache.qpid.server.model.Binding", + createBinding("key", + TOPIC_EXCHANGE_ID, + QUEUE_ID, + "x-filter-jms-selector", + "wibble")); + + final ConfiguredObjectRecord[] expected = { + new ConfiguredObjectRecord(new UUID(1, 0), "Binding", + createBinding("key", TOPIC_EXCHANGE_ID, QUEUE_ID, "x-filter-jms-selector", "wibble")) + }; + + verifyCorrectUpdates(expected); + + _durableConfigurationRecoverer.completeConfigurationRecovery(); + } + + public void testUpgradeDoesNotRecur() throws Exception + { + + _durableConfigurationRecoverer.beginConfigurationRecovery(_store, 2); + + _durableConfigurationRecoverer.configuredObject(new UUID(1, 0), + "Binding", + createBinding("key", + DIRECT_EXCHANGE_ID, + QUEUE_ID, + "x-filter-jms-selector", + "wibble")); + + doThrow(new RuntimeException("Update Should not be called")).when(_store).update(any(ConfiguredObjectRecord[].class)); + + _durableConfigurationRecoverer.completeConfigurationRecovery(); + } + + public void testFailsWithUnresolvedObjects() + { + _durableConfigurationRecoverer.beginConfigurationRecovery(_store, 2); + + + _durableConfigurationRecoverer.configuredObject(new UUID(1, 0), + "Binding", + createBinding("key", + new UUID(3,0), + QUEUE_ID, + "x-filter-jms-selector", + "wibble")); + + 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, 2); + + + try + { + final Map<String, Object> emptyArguments = Collections.emptyMap(); + _durableConfigurationRecoverer.configuredObject(new UUID(1, 0), + "Wibble", emptyArguments); + _durableConfigurationRecoverer.completeConfigurationRecovery(); + fail("Expected resolution to fail due to unknown object type"); + } + catch(IllegalConfigurationException e) + { + assertEquals("Unkown 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); + + final Exchange customExchange = mock(Exchange.class); + + when(customExchange.getId()).thenReturn(exchangeId); + when(customExchange.getName()).thenReturn(CUSTOM_EXCHANGE_NAME); + + when(_exchangeFactory.restoreExchange(eq(exchangeId), + eq(CUSTOM_EXCHANGE_NAME), + eq(HeadersExchange.TYPE.getType()), + anyBoolean())).thenReturn(customExchange); + + _durableConfigurationRecoverer.beginConfigurationRecovery(_store, 2); + + _durableConfigurationRecoverer.configuredObject(queueId, Queue.class.getSimpleName(), + createQueue("testQueue", exchangeId)); + _durableConfigurationRecoverer.configuredObject(exchangeId, + org.apache.qpid.server.model.Exchange.class.getSimpleName(), + createExchange(CUSTOM_EXCHANGE_NAME, HeadersExchange.TYPE)); + + _durableConfigurationRecoverer.completeConfigurationRecovery(); + + assertEquals(customExchange, _vhost.getQueue(queueId).getAlternateExchange()); + } + + private void verifyCorrectUpdates(final ConfiguredObjectRecord[] expected) throws AMQStoreException + { + doAnswer(new Answer() + { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable + { + Object[] args = invocation.getArguments(); + assertEquals("Updated records are not as expected", new HashSet(Arrays.asList( + expected)), new HashSet(Arrays.asList(args))); + + return null; + } + }).when(_store).update(any(ConfiguredObjectRecord[].class)); + } + + private Map<String,Object> createBinding(String bindingKey, UUID exchangeId, UUID queueId, String... args) + { + Map<String, Object> binding = new LinkedHashMap<String, Object>(); + + binding.put("name", bindingKey); + binding.put(Binding.EXCHANGE, exchangeId.toString()); + binding.put(Binding.QUEUE, queueId.toString()); + Map<String,String> argumentMap = new LinkedHashMap<String, String>(); + if(args != null && args.length != 0) + { + 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, 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()); + } + queue.put(Queue.EXCLUSIVE, false); + + return queue; + + } + +} diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java index 78d55c42bf..1ca7ff1b65 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java @@ -21,16 +21,15 @@ package org.apache.qpid.server.virtualhost; import java.util.Collection; +import java.util.Map; import java.util.concurrent.ScheduledFuture; import org.apache.qpid.AMQException; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.connection.IConnectionRegistry; -import org.apache.qpid.server.exchange.AbstractExchange; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeFactory; -import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.plugin.ExchangeType; -import org.apache.qpid.server.protocol.v1_0.LinkRegistry; +import org.apache.qpid.server.protocol.LinkRegistry; +import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; @@ -122,6 +121,43 @@ public class MockVirtualHost implements VirtualHost } @Override + public AMQQueue getQueue(String name) + { + return null; + } + + @Override + public AMQQueue getQueue(UUID id) + { + return null; + } + + @Override + public Collection<AMQQueue> getQueues() + { + return null; + } + + @Override + public int removeQueue(AMQQueue queue) throws AMQException + { + return 0; + } + + @Override + public AMQQueue createQueue(UUID id, + String queueName, + boolean durable, + String owner, + boolean autoDelete, + boolean exclusive, + boolean deleteOnNoConsumer, + Map<String, Object> arguments) throws AMQException + { + return null; + } + + @Override public Exchange createExchange(UUID id, String exchange, String type, @@ -144,6 +180,12 @@ public class MockVirtualHost implements VirtualHost } @Override + public Exchange getExchange(UUID id) + { + return null; + } + + @Override public Exchange getDefaultExchange() { return null; diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/StandardVirtualHostTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/StandardVirtualHostTest.java index 6b8ea0e80b..03cb483e40 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/StandardVirtualHostTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/virtualhost/StandardVirtualHostTest.java @@ -20,7 +20,9 @@ */ package org.apache.qpid.server.virtualhost; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; @@ -34,7 +36,7 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.stats.StatisticsGatherer; -import org.apache.qpid.server.store.MemoryMessageStore; +import org.apache.qpid.server.store.TestMemoryMessageStore; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.test.utils.QpidTestCase; @@ -242,7 +244,7 @@ public class StandardVirtualHostTest extends QpidTestCase VirtualHost vhost = createVirtualHost(vhostName, config); assertNotNull("virtualhost should exist", vhost); - AMQQueue queue = vhost.getQueueRegistry().getQueue(queueName); + AMQQueue queue = vhost.getQueue(queueName); assertNotNull("queue should exist", queue); Exchange defaultExch = vhost.getDefaultExchange(); @@ -306,7 +308,7 @@ public class StandardVirtualHostTest extends QpidTestCase writer.write(" <" + vhostName + ">"); writer.write(" <type>" + StandardVirtualHostFactory.TYPE + "</type>"); writer.write(" <store>"); - writer.write(" <class>" + MemoryMessageStore.class.getName() + "</class>"); + writer.write(" <class>" + TestMemoryMessageStore.class.getName() + "</class>"); writer.write(" </store>"); if(exchangeName != null && !dontDeclare) { @@ -363,10 +365,11 @@ public class StandardVirtualHostTest extends QpidTestCase _virtualHostRegistry = broker.getVirtualHostRegistry(); Configuration config = new PropertiesConfiguration(); - config.setProperty("store.type", MemoryMessageStore.TYPE); VirtualHostConfiguration configuration = new VirtualHostConfiguration(virtualHostName, config, broker); + final org.apache.qpid.server.model.VirtualHost virtualHost = mock(org.apache.qpid.server.model.VirtualHost.class); + when(virtualHost.getAttribute(eq(org.apache.qpid.server.model.VirtualHost.STORE_TYPE))).thenReturn(TestMemoryMessageStore.TYPE); VirtualHost host = new StandardVirtualHostFactory().createVirtualHost(_virtualHostRegistry, mock(StatisticsGatherer.class), new SecurityManager(mock(Broker.class), false), configuration, - mock(org.apache.qpid.server.model.VirtualHost.class)); + virtualHost); _virtualHostRegistry.registerVirtualHost(host); return host; } diff --git a/qpid/java/broker/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory b/qpid/java/broker/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory new file mode 100644 index 0000000000..9512fb8117 --- /dev/null +++ b/qpid/java/broker/src/test/resources/META-INF/services/org.apache.qpid.server.plugin.MessageStoreFactory @@ -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/qpid/java/build.deps b/qpid/java/build.deps index 630932638a..ebb6517738 100644 --- a/qpid/java/build.deps +++ b/qpid/java/build.deps @@ -98,6 +98,10 @@ broker-plugins-management-http.test.libs=${test.libs} broker-plugins-management-jmx.test.libs=${test.libs} broker-plugins-jdbc-store.test.libs=${test.libs} broker-plugins-derby-store.test.libs=${test.libs} +broker-plugins-memory-store.test.libs=${test.libs} +broker-plugins-amqp-0-8-protocol.test.libs=${test.libs} +broker-plugins-amqp-0-10-protocol.test.libs=${test.libs} +broker-plugins-amqp-1-0-protocol.test.libs=${test.libs} management-common.test.libs=${test.libs} @@ -106,7 +110,7 @@ jca.libs=${geronimo-j2ee} ${geronimo-jta} ${geronimo-jms} ${geronimo-openejb} ${ jca.test.libs=${test.libs} # optional bdbstore module deps -bdb-je=lib/bdbstore/je-5.0.73.jar +bdb-je=lib/bdbstore/je-5.0.84.jar bdbstore.libs=${bdb-je} bdbstore.test.libs=${test.libs} diff --git a/qpid/java/client/src/main/java/client.bnd b/qpid/java/client/src/main/java/client.bnd index 1d78bee554..5cc63b8d51 100755 --- a/qpid/java/client/src/main/java/client.bnd +++ b/qpid/java/client/src/main/java/client.bnd @@ -17,7 +17,7 @@ # under the License. # -ver: 0.23.0 +ver: 0.25.0 Bundle-SymbolicName: qpid-client Bundle-Version: ${ver} diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java index 74c9878a8e..0dc5cc68c1 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java @@ -126,7 +126,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect /** The virtual path to connect to on the AMQ server */ private String _virtualHost; - private ExceptionListener _exceptionListener; + /** The exception listener for this connection object. */ + private volatile ExceptionListener _exceptionListener; private ConnectionListener _connectionListener; @@ -151,10 +152,10 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect */ private QpidConnectionMetaData _connectionMetaData; - private AMQShortString _defaultTopicExchangeName = ExchangeDefaults.TOPIC_EXCHANGE_NAME; - private AMQShortString _defaultQueueExchangeName = ExchangeDefaults.DIRECT_EXCHANGE_NAME; - private AMQShortString _temporaryTopicExchangeName = ExchangeDefaults.TOPIC_EXCHANGE_NAME; - private AMQShortString _temporaryQueueExchangeName = ExchangeDefaults.DIRECT_EXCHANGE_NAME; + private AMQShortString _defaultTopicExchangeName = AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_NAME); + private AMQShortString _defaultQueueExchangeName = AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_NAME); + private AMQShortString _temporaryTopicExchangeName = AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_NAME); + private AMQShortString _temporaryQueueExchangeName = AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_NAME); /** Thread Pool for executing connection level processes. Such as returning bounced messages. */ private final ExecutorService _taskPool = Executors.newCachedThreadPool(); @@ -784,13 +785,13 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect public ExceptionListener getExceptionListener() throws JMSException { checkNotClosed(); - - return _exceptionListener; + return getExceptionListenerNoCheck(); } public void setExceptionListener(ExceptionListener listener) throws JMSException { checkNotClosed(); + _exceptionListener = listener; } @@ -1307,45 +1308,56 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect _protocolHandler.getProtocolSession().notifyError(je); } - // get the failover mutex before trying to close - synchronized (getFailoverMutex()) + try { - // decide if we are going to close the session - if (hardError(cause)) + // get the failover mutex before trying to close + synchronized (getFailoverMutex()) { - closer = (!setClosed()) || closer; + // decide if we are going to close the session + if (hardError(cause)) { - _logger.info("Closing AMQConnection due to :" + cause); + closer = (!setClosed()) || closer; + { + _logger.info("Closing AMQConnection due to :" + cause); + } } - } - else - { - _logger.info("Not a hard-error connection not closing: " + cause); - } - - // deliver the exception if there is a listener - if (_exceptionListener != null) - { - _exceptionListener.onException(je); - } - else - { - _logger.error("Throwable Received but no listener set: " + cause); - } - - // if we are closing the connection, close sessions first - if (closer) - { - try + else { - closeAllSessions(cause, -1, -1); // FIXME: when doing this end up with RejectedExecutionException from executor. + _logger.info("Not a hard-error connection not closing: " + cause); } - catch (JMSException e) + + // if we are closing the connection, close sessions first + if (closer) { - _logger.error("Error closing all sessions: " + e, e); + try + { + closeAllSessions(cause, -1, -1); // FIXME: when doing this end up with RejectedExecutionException from executor. + } + catch (JMSException e) + { + _logger.error("Error closing all sessions: " + e, e); + } } } } + finally + { + deliverJMSExceptionToExceptionListenerOrLog(je, cause); + } + } + + private void deliverJMSExceptionToExceptionListenerOrLog(final JMSException je, final Throwable cause) + { + // deliver the exception if there is a listener + ExceptionListener exceptionListener = getExceptionListenerNoCheck(); + if (exceptionListener != null) + { + exceptionListener.onException(je); + } + else + { + _logger.error("Throwable Received but no listener set: " + cause); + } } private boolean hardError(Throwable cause) diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java index fc7762e77d..91c23ff384 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java @@ -47,7 +47,7 @@ import java.util.concurrent.atomic.AtomicLong; public abstract class AMQDestination implements Destination, Referenceable { private static final Logger _logger = LoggerFactory.getLogger(AMQDestination.class); - + private AMQShortString _exchangeName; private AMQShortString _exchangeClass; @@ -65,7 +65,7 @@ public abstract class AMQDestination implements Destination, Referenceable private boolean _isAutoDelete; private boolean _browseOnly; - + private AtomicLong _addressResolved = new AtomicLong(0); private AMQShortString _queueName; @@ -113,10 +113,10 @@ public abstract class AMQDestination implements Destination, Referenceable } // ----- Fields required to support new address syntax ------- - - public enum DestSyntax { + + public enum DestSyntax { BURL,ADDR; - + public static DestSyntax getSyntaxType(String s) { if (("BURL").equals(s)) @@ -133,11 +133,11 @@ public abstract class AMQDestination implements Destination, Referenceable " should be one of {BURL|ADDR}"); } } - } - - public enum AddressOption { - ALWAYS, NEVER, SENDER, RECEIVER; - + } + + public enum AddressOption { + ALWAYS, NEVER, SENDER, RECEIVER; + public static AddressOption getOption(String str) { if ("always".equals(str)) @@ -162,9 +162,9 @@ public abstract class AMQDestination implements Destination, Referenceable } } } - + private final static DestSyntax defaultDestSyntax; - + private DestSyntax _destSyntax = DestSyntax.ADDR; private AddressHelper _addrHelper; @@ -179,25 +179,25 @@ public abstract class AMQDestination implements Destination, Referenceable private Node _node; private Link _link; - + // ----- / Fields required to support new address syntax ------- - + static { defaultDestSyntax = DestSyntax.getSyntaxType( System.getProperty(ClientProperties.DEST_SYNTAX, DestSyntax.ADDR.toString())); - - + + } - + public static DestSyntax getDefaultDestSyntax() { return defaultDestSyntax; } protected AMQDestination() - { + { } protected AMQDestination(Address address) throws Exception @@ -207,10 +207,10 @@ public abstract class AMQDestination implements Destination, Referenceable _destSyntax = DestSyntax.ADDR; _logger.debug("Based on " + address + " the selected destination syntax is " + _destSyntax); } - + public static DestSyntax getDestType(String str) { - if (str.startsWith("BURL:") || + if (str.startsWith("BURL:") || (!str.startsWith("ADDR:") && defaultDestSyntax == DestSyntax.BURL)) { return DestSyntax.BURL; @@ -220,7 +220,7 @@ public abstract class AMQDestination implements Destination, Referenceable return DestSyntax.ADDR; } } - + public static String stripSyntaxPrefix(String str) { if (str.startsWith("BURL:") || str.startsWith("ADDR:")) @@ -232,7 +232,7 @@ public abstract class AMQDestination implements Destination, Referenceable return str; } } - + protected AMQDestination(String str) throws URISyntaxException { parseDestinationString(str); @@ -243,8 +243,8 @@ public abstract class AMQDestination implements Destination, Referenceable _destSyntax = getDestType(str); str = stripSyntaxPrefix(str); if (_destSyntax == DestSyntax.BURL) - { - getInfoFromBindingURL(new AMQBindingURL(str)); + { + getInfoFromBindingURL(new AMQBindingURL(str)); } else { @@ -262,7 +262,7 @@ public abstract class AMQDestination implements Destination, Referenceable } _logger.debug("Based on " + str + " the selected destination syntax is " + _destSyntax); } - + //retained for legacy support protected AMQDestination(BindingURL binding) { @@ -331,8 +331,8 @@ public abstract class AMQDestination implements Destination, Referenceable protected AMQDestination(AMQShortString exchangeName, AMQShortString exchangeClass, AMQShortString routingKey, boolean isExclusive, boolean isAutoDelete, AMQShortString queueName, boolean isDurable,AMQShortString[] bindingKeys, boolean browseOnly) { - if ( (ExchangeDefaults.DIRECT_EXCHANGE_CLASS.equals(exchangeClass) || - ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(exchangeClass)) + if ( (AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS).equals(exchangeClass) || + AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS).equals(exchangeClass)) && routingKey == null) { throw new IllegalArgumentException("routing/binding key must not be null"); @@ -376,16 +376,16 @@ public abstract class AMQDestination implements Destination, Referenceable return toString(); } - public DestSyntax getDestSyntax() + public DestSyntax getDestSyntax() { return _destSyntax; } - + protected void setDestSyntax(DestSyntax syntax) { _destSyntax = syntax; } - + public AMQShortString getEncodedName() { if(_urlAsShortString == null) @@ -431,12 +431,12 @@ public abstract class AMQDestination implements Destination, Referenceable public boolean isTopic() { - return ExchangeDefaults.TOPIC_EXCHANGE_CLASS.equals(_exchangeClass); + return AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS).equals(_exchangeClass); } public boolean isQueue() { - return ExchangeDefaults.DIRECT_EXCHANGE_CLASS.equals(_exchangeClass); + return AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS).equals(_exchangeClass); } public String getQueueName() @@ -481,7 +481,7 @@ public abstract class AMQDestination implements Destination, Referenceable { return _isExclusive; } - + public boolean isAutoDelete() { return _isAutoDelete; @@ -720,15 +720,15 @@ public abstract class AMQDestination implements Destination, Referenceable { AMQShortString type = binding.getExchangeClass(); - if (type.equals(ExchangeDefaults.DIRECT_EXCHANGE_CLASS)) + if (type.equals(AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS))) { return new AMQQueue(binding); } - else if (type.equals(ExchangeDefaults.TOPIC_EXCHANGE_CLASS)) + else if (type.equals(AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS))) { return new AMQTopic(binding); } - else if (type.equals(ExchangeDefaults.HEADERS_EXCHANGE_CLASS)) + else if (type.equals(AMQShortString.valueOf(ExchangeDefaults.HEADERS_EXCHANGE_CLASS))) { return new AMQHeadersExchange(binding); } @@ -743,8 +743,8 @@ public abstract class AMQDestination implements Destination, Referenceable DestSyntax syntax = getDestType(str); str = stripSyntaxPrefix(str); if (syntax == DestSyntax.BURL) - { - return createDestination(new AMQBindingURL(str)); + { + return createDestination(new AMQBindingURL(str)); } else { @@ -752,16 +752,16 @@ public abstract class AMQDestination implements Destination, Referenceable return new AMQAnyDestination(address); } } - + // ----- new address syntax ----------- - + public static class Binding { private String exchange; private String bindingKey; private String queue; private Map<String,Object> args; - + public Binding(String exchange, String queue, String bindingKey, @@ -772,36 +772,36 @@ public abstract class AMQDestination implements Destination, Referenceable this.bindingKey = bindingKey; this.args = args; } - - public String getExchange() + + public String getExchange() { return exchange; } - public String getQueue() + public String getQueue() { return queue; } - - public String getBindingKey() + + public String getBindingKey() { return bindingKey; } - - public Map<String, Object> getArgs() + + public Map<String, Object> getArgs() { return args; } } - + public Address getAddress() { return _address; } - + protected void setAddress(Address addr) { _address = addr; } - + public int getAddressType(){ return _addressType; } @@ -809,11 +809,11 @@ public abstract class AMQDestination implements Destination, Referenceable public void setAddressType(int addressType){ _addressType = addressType; } - + public String getAddressName() { return _name; } - + public void setAddressName(String name){ _name = name; } @@ -825,15 +825,15 @@ public abstract class AMQDestination implements Destination, Referenceable public void setSubject(String subject) { _subject = subject; } - + public AddressOption getCreate() { return _create; } - + public void setCreate(AddressOption option) { _create = option; } - + public AddressOption getAssert() { return _assert; } @@ -841,7 +841,7 @@ public abstract class AMQDestination implements Destination, Referenceable public void setAssert(AddressOption option) { _assert = option; } - + public AddressOption getDelete() { return _delete; } @@ -869,22 +869,22 @@ public abstract class AMQDestination implements Destination, Referenceable { _link = link; } - + public void setExchangeName(AMQShortString name) { this._exchangeName = name; } - + public void setExchangeClass(AMQShortString type) { this._exchangeClass = type; } - + public void setRoutingKey(AMQShortString rk) { this._routingKey = rk; } - + public boolean isAddressResolved() { return _addressResolved.get() > 0; @@ -894,80 +894,80 @@ public abstract class AMQDestination implements Destination, Referenceable { _addressResolved.set(addressResolved); } - + private static Address createAddressFromString(String str) { return Address.parse(str); } - + private void getInfoFromAddress() throws Exception { _name = _address.getName(); _subject = _address.getSubject(); - + _addrHelper = new AddressHelper(_address); - + _create = _addrHelper.getCreate() != null ? AddressOption.getOption(_addrHelper.getCreate()):AddressOption.NEVER; - + _assert = _addrHelper.getAssert() != null ? AddressOption.getOption(_addrHelper.getAssert()):AddressOption.NEVER; _delete = _addrHelper.getDelete() != null ? AddressOption.getOption(_addrHelper.getDelete()):AddressOption.NEVER; - + _browseOnly = _addrHelper.isBrowseOnly(); - + _addressType = _addrHelper.getNodeType(); _node = _addrHelper.getNode(); - _link = _addrHelper.getLink(); + _link = _addrHelper.getLink(); } - - // ----- / new address syntax ----------- + + // ----- / new address syntax ----------- public boolean isBrowseOnly() { return _browseOnly; } - + private void setBrowseOnly(boolean b) { _browseOnly = b; } - + public AMQDestination copyDestination() { - AMQDestination dest = + AMQDestination dest = new AMQAnyDestination(_exchangeName, _exchangeClass, _routingKey, - _isExclusive, + _isExclusive, _isAutoDelete, - _queueName, + _queueName, _isDurable, _bindingKeys ); - + dest.setDestSyntax(_destSyntax); dest.setAddress(_address); dest.setAddressName(_name); dest.setSubject(_subject); - dest.setCreate(_create); - dest.setAssert(_assert); - dest.setDelete(_delete); + dest.setCreate(_create); + dest.setAssert(_assert); + dest.setDelete(_delete); dest.setBrowseOnly(_browseOnly); dest.setAddressType(_addressType); dest.setNode(_node); dest.setLink(_link); dest.setAddressResolved(_addressResolved.get()); - return dest; + return dest; } - + protected void setAutoDelete(boolean b) { _isAutoDelete = b; } - + protected void setDurable(boolean b) { _isDurable = b; diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQHeadersExchange.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQHeadersExchange.java index 922cc1e2a7..714c38d37b 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQHeadersExchange.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQHeadersExchange.java @@ -41,7 +41,7 @@ public class AMQHeadersExchange extends AMQDestination public AMQHeadersExchange(AMQShortString queueName) { - super(queueName, ExchangeDefaults.HEADERS_EXCHANGE_CLASS, queueName, true, true, null); + super(queueName, AMQShortString.valueOf(ExchangeDefaults.HEADERS_EXCHANGE_CLASS), queueName, true, true, null); } public boolean isNameRequired() diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQQueue.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQQueue.java index 4e9b53c814..0f375e4921 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQQueue.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQQueue.java @@ -38,7 +38,7 @@ public class AMQQueue extends AMQDestination implements Queue { super(address); } - + /** * Create a reference to a non temporary queue using a BindingURL object. * Note this does not actually imply the queue exists. @@ -70,13 +70,13 @@ public class AMQQueue extends AMQDestination implements Queue public AMQQueue(AMQShortString exchangeName, AMQShortString routingKey, AMQShortString queueName) { - super(exchangeName, ExchangeDefaults.DIRECT_EXCHANGE_CLASS, routingKey, false, + super(exchangeName, AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS), routingKey, false, false, queueName, false); } public AMQQueue(AMQShortString exchangeName, AMQShortString routingKey, AMQShortString queueName,AMQShortString[] bindingKeys) { - super(exchangeName, ExchangeDefaults.DIRECT_EXCHANGE_CLASS, routingKey, false, + super(exchangeName, AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS), routingKey, false, false, queueName, false,bindingKeys); } @@ -149,7 +149,7 @@ public class AMQQueue extends AMQDestination implements Queue public AMQQueue(AMQShortString exchangeName, AMQShortString routingKey, AMQShortString queueName, boolean exclusive, boolean autoDelete, boolean durable,AMQShortString[] bindingKeys) { - super(exchangeName, ExchangeDefaults.DIRECT_EXCHANGE_CLASS, routingKey, exclusive, + super(exchangeName, AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS), routingKey, exclusive, autoDelete, queueName, durable, bindingKeys); } @@ -167,9 +167,8 @@ public class AMQQueue extends AMQDestination implements Queue public boolean isNameRequired() { - //If the name is null, we require one to be generated by the client so that it will# - //remain valid if we failover (see BLZ-24) - return getQueueName() == null; + AMQShortString queueName = getAMQQueueName(); + return queueName == null || AMQShortString.EMPTY_STRING.equals(queueName); } @Override diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java index 6b87316e87..9657a49d98 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession_0_10.java @@ -1380,7 +1380,7 @@ public class AMQSession_0_10 extends AMQSession<BasicMessageConsumer_0_10, Basic dest.setExchangeName(new AMQShortString(dest.getAddressName())); Node node = dest.getNode(); dest.setExchangeClass(node.getExchangeType() == null? - ExchangeDefaults.TOPIC_EXCHANGE_CLASS: + AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS): new AMQShortString(node.getExchangeType())); dest.setRoutingKey(new AMQShortString(dest.getSubject())); } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java index d78e725a5d..4cc32022dc 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java @@ -60,12 +60,12 @@ public class AMQTopic extends AMQDestination implements Topic public AMQTopic(AMQShortString exchange, AMQShortString routingKey, AMQShortString queueName) { - super(exchange, ExchangeDefaults.TOPIC_EXCHANGE_CLASS, routingKey, true, true, queueName, false); + super(exchange, AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS), routingKey, true, true, queueName, false); } public AMQTopic(AMQShortString exchange, AMQShortString routingKey, AMQShortString queueName,AMQShortString[] bindingKeys) { - super(exchange, ExchangeDefaults.TOPIC_EXCHANGE_CLASS, routingKey, true, true, queueName, false,bindingKeys); + super(exchange, AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS), routingKey, true, true, queueName, false,bindingKeys); } public AMQTopic(AMQConnection conn, String routingKey) @@ -73,6 +73,10 @@ public class AMQTopic extends AMQDestination implements Topic this(conn.getDefaultTopicExchangeName(), new AMQShortString(routingKey)); } + public AMQTopic(String exchangeName, String routingKey) + { + this(AMQShortString.valueOf(exchangeName), new AMQShortString(routingKey)); + } public AMQTopic(AMQShortString exchangeName, String routingKey) { @@ -86,7 +90,7 @@ public class AMQTopic extends AMQDestination implements Topic public AMQTopic(AMQShortString exchangeName, AMQShortString name, boolean isAutoDelete, AMQShortString queueName, boolean isDurable) { - super(exchangeName, ExchangeDefaults.TOPIC_EXCHANGE_CLASS, name, true, isAutoDelete, queueName, isDurable); + super(exchangeName, AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS), name, true, isAutoDelete, queueName, isDurable); } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java index 98fa6de675..5acaa5c543 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java @@ -440,7 +440,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac { if (!(destination instanceof AMQDestination)) { - throw new JMSException("Unsupported destination class: " + throw new InvalidDestinationException("Unsupported destination class: " + ((destination != null) ? destination.getClass() : null)); } @@ -453,7 +453,7 @@ public abstract class BasicMessageProducer extends Closeable implements org.apac } catch(Exception e) { - JMSException ex = new JMSException("Error validating destination"); + JMSException ex = new InvalidDestinationException("Error validating destination"); ex.initCause(e); ex.setLinkedException(e); diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java index ef92a9281e..b26d67783d 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10.java @@ -125,7 +125,6 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate String subject = null; if (isStrictJMS && messageProps != null && messageProps.getApplicationHeaders() != null) { - System.out.println("%%%% Going to set subject"); subject = (String)messageProps.getApplicationHeaders().get(QpidMessageProperties.QPID_SUBJECT); if (subject != null) { @@ -207,7 +206,7 @@ public class AMQMessageDelegate_0_10 extends AbstractAMQMessageDelegate } else { - throw new JMSException("MessageId '"+messageId+"' is not of the correct format, it must be ID: followed by a UUID"); + throw new JMSException("MessageId '"+messageId+"' is not of the correct format, it must be prefixed with 'ID:'"); } } } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java index 1395f39b99..ad19b0e620 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java @@ -46,7 +46,7 @@ import java.util.concurrent.ConcurrentHashMap; public abstract class AbstractAMQMessageDelegate implements AMQMessageDelegate { - private static Map<String, Integer> _exchangeTypeToDestinationType = new ConcurrentHashMap<String, Integer>(); + private static Map<String, Integer> _exchangeTypeToDestinationType = new ConcurrentHashMap<String, Integer>(); private static Map<String,ExchangeInfo> _exchangeMap = new ConcurrentHashMap<String, ExchangeInfo>(); /** @@ -55,32 +55,32 @@ public abstract class AbstractAMQMessageDelegate implements AMQMessageDelegate static { _exchangeTypeToDestinationType.put("", AMQDestination.QUEUE_TYPE); - _exchangeTypeToDestinationType.put(ExchangeDefaults.DIRECT_EXCHANGE_CLASS.toString(), AMQDestination.QUEUE_TYPE); - _exchangeTypeToDestinationType.put(ExchangeDefaults.TOPIC_EXCHANGE_CLASS.toString(), AMQDestination.TOPIC_TYPE); - _exchangeTypeToDestinationType.put(ExchangeDefaults.FANOUT_EXCHANGE_CLASS.toString(), AMQDestination.TOPIC_TYPE); - _exchangeTypeToDestinationType.put(ExchangeDefaults.HEADERS_EXCHANGE_CLASS.toString(), AMQDestination.QUEUE_TYPE); - + _exchangeTypeToDestinationType.put(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, AMQDestination.QUEUE_TYPE); + _exchangeTypeToDestinationType.put(ExchangeDefaults.TOPIC_EXCHANGE_CLASS, AMQDestination.TOPIC_TYPE); + _exchangeTypeToDestinationType.put(ExchangeDefaults.FANOUT_EXCHANGE_CLASS, AMQDestination.TOPIC_TYPE); + _exchangeTypeToDestinationType.put(ExchangeDefaults.HEADERS_EXCHANGE_CLASS, AMQDestination.QUEUE_TYPE); + _exchangeMap.put("", new ExchangeInfo("","",AMQDestination.QUEUE_TYPE)); - - _exchangeMap.put(ExchangeDefaults.DIRECT_EXCHANGE_NAME.toString(), - new ExchangeInfo(ExchangeDefaults.DIRECT_EXCHANGE_NAME.toString(), - ExchangeDefaults.DIRECT_EXCHANGE_CLASS.toString(), + + _exchangeMap.put(ExchangeDefaults.DIRECT_EXCHANGE_NAME, + new ExchangeInfo(ExchangeDefaults.DIRECT_EXCHANGE_NAME, + ExchangeDefaults.DIRECT_EXCHANGE_CLASS, AMQDestination.QUEUE_TYPE)); - - _exchangeMap.put(ExchangeDefaults.TOPIC_EXCHANGE_NAME.toString(), - new ExchangeInfo(ExchangeDefaults.TOPIC_EXCHANGE_NAME.toString(), - ExchangeDefaults.TOPIC_EXCHANGE_CLASS.toString(), + + _exchangeMap.put(ExchangeDefaults.TOPIC_EXCHANGE_NAME, + new ExchangeInfo(ExchangeDefaults.TOPIC_EXCHANGE_NAME, + ExchangeDefaults.TOPIC_EXCHANGE_CLASS, AMQDestination.TOPIC_TYPE)); - - _exchangeMap.put(ExchangeDefaults.FANOUT_EXCHANGE_NAME.toString(), - new ExchangeInfo(ExchangeDefaults.FANOUT_EXCHANGE_NAME.toString(), - ExchangeDefaults.FANOUT_EXCHANGE_CLASS.toString(), + + _exchangeMap.put(ExchangeDefaults.FANOUT_EXCHANGE_NAME, + new ExchangeInfo(ExchangeDefaults.FANOUT_EXCHANGE_NAME, + ExchangeDefaults.FANOUT_EXCHANGE_CLASS, AMQDestination.TOPIC_TYPE)); - - _exchangeMap.put(ExchangeDefaults.HEADERS_EXCHANGE_NAME.toString(), - new ExchangeInfo(ExchangeDefaults.HEADERS_EXCHANGE_NAME.toString(), - ExchangeDefaults.HEADERS_EXCHANGE_CLASS.toString(), - AMQDestination.QUEUE_TYPE)); + + _exchangeMap.put(ExchangeDefaults.HEADERS_EXCHANGE_NAME, + new ExchangeInfo(ExchangeDefaults.HEADERS_EXCHANGE_NAME, + ExchangeDefaults.HEADERS_EXCHANGE_CLASS, + AMQDestination.QUEUE_TYPE)); } /** If the acknowledge mode is CLIENT_ACKNOWLEDGE the session is required */ @@ -115,19 +115,19 @@ public abstract class AbstractAMQMessageDelegate implements AMQMessageDelegate { AMQDestination dest; ExchangeInfo exchangeInfo = _exchangeMap.get(exchange.asString()); - + if (exchangeInfo == null) { exchangeInfo = new ExchangeInfo(exchange.asString(),"",AMQDestination.UNKNOWN_TYPE); } - + if ("topic".equals(exchangeInfo.getExchangeType())) { dest = new AMQTopic(exchange, routingKey, null); } else if ("direct".equals(exchangeInfo.getExchangeType())) { - dest = new AMQQueue(exchange, routingKey, routingKey); + dest = new AMQQueue(exchange, routingKey, routingKey); } else { @@ -161,7 +161,7 @@ public abstract class AbstractAMQMessageDelegate implements AMQMessageDelegate { type = AMQDestination.UNKNOWN_TYPE; } - + _exchangeMap.put(exchange, new ExchangeInfo(exchange,newtype,type)); } @@ -226,7 +226,7 @@ class ExchangeInfo private String exchangeName; private String exchangeType; private int destType = AMQDestination.QUEUE_TYPE; - + public ExchangeInfo(String exchangeName, String exchangeType, int destType) { diff --git a/qpid/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java b/qpid/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java index f17fb9b5f5..8c23ddad5e 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactory.java @@ -274,11 +274,11 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor { if (value instanceof AMQShortString) { - return new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, (AMQShortString) value); + return new AMQQueue(AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_NAME), (AMQShortString) value); } else if (value instanceof String) { - return new AMQQueue(ExchangeDefaults.DIRECT_EXCHANGE_NAME, new AMQShortString((String) value)); + return new AMQQueue(AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_NAME), new AMQShortString((String) value)); } else if (value instanceof BindingURL) { @@ -295,7 +295,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor { if (value instanceof AMQShortString) { - return new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, (AMQShortString) value); + return new AMQTopic(AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_NAME), (AMQShortString) value); } else if (value instanceof String) { @@ -309,7 +309,7 @@ public class PropertiesFileInitialContextFactory implements InitialContextFactor } // The Destination has a dual nature. If this was used for a producer the key is used // for the routing key. If it was used for the consumer it becomes the bindingKey - return new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME,bindings[0],null,bindings); + return new AMQTopic(AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_NAME),bindings[0],null,bindings); } else if (value instanceof BindingURL) { diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_8Test.java b/qpid/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_8Test.java new file mode 100644 index 0000000000..d9caa68ef8 --- /dev/null +++ b/qpid/java/client/src/test/java/org/apache/qpid/client/AMQSession_0_8Test.java @@ -0,0 +1,73 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.client; + +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.amqp_0_91.QueueDeclareOkBodyImpl; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.transport.TestNetworkConnection; +import org.apache.qpid.transport.network.NetworkConnection; +import org.apache.qpid.url.AMQBindingURL; + +public class AMQSession_0_8Test extends QpidTestCase +{ + private AMQConnection _connection; + + public void setUp() throws Exception + { + _connection = new MockAMQConnection("amqp://guest:guest@/test?brokerlist='tcp://localhost:5672'"); + NetworkConnection network = new TestNetworkConnection(); + _connection.getProtocolHandler().setNetworkConnection(network); + } + + public void testQueueNameIsGeneratedOnDeclareQueueWithEmptyQueueName() throws Exception + { + final AMQShortString testQueueName = AMQShortString.valueOf("tmp_127_0_0_1_1_1"); + + _connection.setConnectionListener(new ConnectionListenerSupport() + { + @Override + public void bytesSent(long count) + { + try + { + _connection.getProtocolHandler().methodBodyReceived(1, new QueueDeclareOkBodyImpl(testQueueName, 0, 0)); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } + }); + + AMQSession_0_8 session = new AMQSession_0_8(_connection, 1, true, 0, 1, 1); + + AMQBindingURL bindingURL = new AMQBindingURL("topic://amq.topic//?routingkey='testTopic'"); + AMQQueue queue = new AMQQueue(bindingURL); + + assertEquals("Unexpected queue name", AMQShortString.EMPTY_STRING, queue.getAMQQueueName()); + + session.declareQueue(queue, true); + + assertEquals("Unexpected queue name", testQueueName, queue.getAMQQueueName()); + } +} diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/ConnectionListenerSupport.java b/qpid/java/client/src/test/java/org/apache/qpid/client/ConnectionListenerSupport.java new file mode 100644 index 0000000000..fc66e60bc0 --- /dev/null +++ b/qpid/java/client/src/test/java/org/apache/qpid/client/ConnectionListenerSupport.java @@ -0,0 +1,55 @@ +/* + * + * 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.client; + +import org.apache.qpid.jms.ConnectionListener; + +public class ConnectionListenerSupport implements ConnectionListener +{ + + @Override + public void bytesSent(long count) + { + } + + @Override + public void bytesReceived(long count) + { + } + + @Override + public boolean preFailover(boolean redirect) + { + return true; + } + + @Override + public boolean preResubscribe() + { + return false; + } + + @Override + public void failoverComplete() + { + } + +} diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10Test.java b/qpid/java/client/src/test/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10Test.java index 5fff6b6b35..3afeb79ac3 100644 --- a/qpid/java/client/src/test/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10Test.java +++ b/qpid/java/client/src/test/java/org/apache/qpid/client/message/AMQMessageDelegate_0_10Test.java @@ -124,7 +124,6 @@ public class AMQMessageDelegate_0_10Test extends QpidTestCase for (Enumeration props = delegate.getPropertyNames(); props.hasMoreElements();) { String key = (String)props.nextElement(); - System.out.println("PropName : " + key); if (key.equals("JMS_" + QpidMessageProperties.QPID_SUBJECT)) { propFound = true; diff --git a/qpid/java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java b/qpid/java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java index ce9e681eaf..2914244103 100644 --- a/qpid/java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java +++ b/qpid/java/client/src/test/java/org/apache/qpid/jndi/PropertiesFileInitialContextFactoryTest.java @@ -115,7 +115,7 @@ public class PropertiesFileInitialContextFactoryTest extends QpidTestCase setTestSystemProperty(ClientProperties.DEST_SYNTAX, "ADDR"); setTestSystemProperty(InitialContext.INITIAL_CONTEXT_FACTORY, "org.apache.qpid.jndi.PropertiesFileInitialContextFactory"); - setTestSystemProperty(InitialContext.PROVIDER_URL, "file://" + f.getCanonicalPath()); + setTestSystemProperty(InitialContext.PROVIDER_URL, f.toURI().toURL().toString()); InitialContext context = new InitialContext(); Destination dest = (Destination) context.lookup("topicExchange"); diff --git a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java index e13180424b..9c9664931a 100644 --- a/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java +++ b/qpid/java/client/src/test/java/org/apache/qpid/test/unit/client/destinationurl/DestinationURLTest.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.RejectBehaviour; import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.url.AMQBindingURL; import org.apache.qpid.url.BindingURL; @@ -138,7 +139,7 @@ public class DestinationURLTest extends TestCase AMQBindingURL dest = new AMQBindingURL(url); - assertTrue(dest.getExchangeClass().equals(ExchangeDefaults.DIRECT_EXCHANGE_CLASS)); + assertTrue(dest.getExchangeClass().equals(AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS))); assertTrue(dest.getExchangeName().equalsCharSequence("")); assertTrue(dest.getDestinationName().equalsCharSequence("")); assertTrue(dest.getQueueName().equalsCharSequence("IBMPerfQueue1")); @@ -180,18 +181,6 @@ public class DestinationURLTest extends TestCase assertTrue("Failed to throw an URISyntaxException when both the bindingkey and routingkey is specified",exceptionThrown); } - - public void testDestinationWithDurableTopic() throws URISyntaxException - { - - String url = "topic://amq.topic//testTopicD?durable='true'&autodelete='true'&clientid='test'&subscription='testQueueD'"; - - AMQBindingURL dest = new AMQBindingURL(url); - - assertTrue(dest.getExchangeClass().equalsCharSequence("topic")); - assertTrue(dest.getExchangeName().equalsCharSequence("amq.topic")); - assertTrue(dest.getQueueName().equalsCharSequence("test:testQueueD")); - } public void testExchangeOptionsNotPresent() throws URISyntaxException { @@ -374,6 +363,46 @@ public class DestinationURLTest extends TestCase assertNull("Reject behaviour is unexpected", dest.getRejectBehaviour()); } + public void testBindingUrlWithoutDestinationAndQueueName() throws Exception + { + AMQBindingURL bindingURL = new AMQBindingURL("topic://amq.topic//?routingkey='testTopic'"); + assertEquals("Unexpected queue name", AMQShortString.EMPTY_STRING, bindingURL.getQueueName()); + assertEquals("Unexpected destination", AMQShortString.EMPTY_STRING, bindingURL.getDestinationName()); + assertEquals("Unexpected routing key", AMQShortString.valueOf("testTopic"), bindingURL.getRoutingKey()); + } + + public void testBindingUrlWithoutDestinationAndMissedQueueName() throws Exception + { + AMQBindingURL bindingURL = new AMQBindingURL("topic://amq.topic/?routingkey='testTopic'"); + assertEquals("Unexpected queue name", AMQShortString.EMPTY_STRING, bindingURL.getQueueName()); + assertEquals("Unexpected destination", AMQShortString.EMPTY_STRING, bindingURL.getDestinationName()); + assertEquals("Unexpected routing key", AMQShortString.valueOf("testTopic"), bindingURL.getRoutingKey()); + } + + public void testBindingUrlWithoutQueueName() throws Exception + { + AMQBindingURL bindingURL = new AMQBindingURL("topic://amq.topic/destination/?routingkey='testTopic'"); + assertEquals("Unexpected queue name", AMQShortString.EMPTY_STRING, bindingURL.getQueueName()); + assertEquals("Unexpected destination", AMQShortString.valueOf("destination"), bindingURL.getDestinationName()); + assertEquals("Unexpected routing key", AMQShortString.valueOf("testTopic"), bindingURL.getRoutingKey()); + } + + public void testBindingUrlWithQueueNameWithoutDestination() throws Exception + { + AMQBindingURL bindingURL = new AMQBindingURL("topic://amq.topic//queueName?routingkey='testTopic'"); + assertEquals("Unexpected queue name", AMQShortString.valueOf("queueName"), bindingURL.getQueueName()); + assertEquals("Unexpected destination", AMQShortString.EMPTY_STRING, bindingURL.getDestinationName()); + assertEquals("Unexpected routing key", AMQShortString.valueOf("testTopic"), bindingURL.getRoutingKey()); + } + + public void testBindingUrlWithQueueNameAndDestination() throws Exception + { + AMQBindingURL bindingURL = new AMQBindingURL("topic://amq.topic/destination/queueName?routingkey='testTopic'"); + assertEquals("Unexpected queue name", AMQShortString.valueOf("queueName"), bindingURL.getQueueName()); + assertEquals("Unexpected destination", AMQShortString.valueOf("destination"), bindingURL.getDestinationName()); + assertEquals("Unexpected routing key", AMQShortString.valueOf("testTopic"), bindingURL.getRoutingKey()); + } + public static junit.framework.Test suite() { return new junit.framework.TestSuite(DestinationURLTest.class); diff --git a/qpid/java/common.xml b/qpid/java/common.xml index 85cc7fc30b..c47cab2ac7 100644 --- a/qpid/java/common.xml +++ b/qpid/java/common.xml @@ -24,9 +24,9 @@ <property name="project.name" value="qpid"/> <!-- Version used for standard build output --> - <property name="project.version" value="0.23"/> + <property name="project.version" value="0.25"/> <!-- The release version used for maven output. SNAPSHOT added via maven.version.suffix --> - <property name="project.version.maven" value="0.24"/> + <property name="project.version.maven" value="0.26"/> <property name="project.url" value="http://qpid.apache.org"/> <property name="project.groupid" value="org.apache.qpid"/> <property name="project.namever" value="${project.name}-${project.version}"/> diff --git a/qpid/java/common/src/main/java/common.bnd b/qpid/java/common/src/main/java/common.bnd index 5635012faa..4d6cd3d844 100755 --- a/qpid/java/common/src/main/java/common.bnd +++ b/qpid/java/common/src/main/java/common.bnd @@ -17,7 +17,7 @@ # under the License.
#
-ver: 0.23.0
+ver: 0.25.0
Bundle-SymbolicName: qpid-common
Bundle-Version: ${ver}
diff --git a/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java b/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java index 44cd603a8d..df71ece787 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/AMQChannelException.java @@ -7,9 +7,9 @@ * 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 @@ -21,6 +21,7 @@ package org.apache.qpid; import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.protocol.AMQConstant; @@ -56,7 +57,8 @@ public class AMQChannelException extends AMQException public AMQFrame getCloseFrame(int channel) { MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor)); - return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), getMessageAsShortString(),_classId,_methodId)); + return new AMQFrame(channel, reg.createChannelCloseBody(getErrorCode() == null ? AMQConstant.INTERNAL_ERROR.getCode() : getErrorCode().getCode(), + AMQShortString.validValueOf(getMessage()),_classId,_methodId)); } } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java b/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java index c7a0816f91..ef108eeb67 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/AMQConnectionException.java @@ -22,6 +22,7 @@ package org.apache.qpid; import org.apache.qpid.framing.AMQFrame; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.MethodRegistry; import org.apache.qpid.framing.ProtocolVersion; import org.apache.qpid.protocol.AMQConstant; @@ -64,7 +65,7 @@ public class AMQConnectionException extends AMQException MethodRegistry reg = MethodRegistry.getMethodRegistry(new ProtocolVersion(major,minor)); return new AMQFrame(0, reg.createConnectionCloseBody(getErrorCode().getCode(), - getMessageAsShortString(), + AMQShortString.validValueOf(getMessage()), _classId, _methodId)); diff --git a/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java b/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java index 40ecc3a946..591202d934 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/AMQException.java @@ -39,7 +39,7 @@ public class AMQException extends Exception { /** Holds the AMQ error code constant associated with this exception. */ private AMQConstant _errorCode; - + private boolean _isHardError; /** @@ -75,13 +75,13 @@ public class AMQException extends Exception * Deprecated constructors brought from M2.1 */ @Deprecated - public AMQException(String msg) + public AMQException(String msg) { this(null, (msg == null) ? "" : msg); } - - @Deprecated - public AMQException(AMQConstant errorCode, String msg) + + @Deprecated + public AMQException(AMQConstant errorCode, String msg) { this(errorCode, (msg == null) ? "" : msg, null); } @@ -97,7 +97,7 @@ public class AMQException extends Exception { return getClass().getName() + ": " + getMessage() + (_errorCode == null ? "" : " [error code " + _errorCode + "]"); } - + /** * Gets the AMQ protocol exception code associated with this exception. * @@ -141,14 +141,4 @@ public class AMQException extends Exception return newAMQE; } - /** - * Truncates the exception message to 255 characters if its length exceeds 255. - * - * @return exception message - */ - public AMQShortString getMessageAsShortString() - { - String message = getMessage(); - return AMQShortString.valueOf(message, true, true); - } } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/exchange/ExchangeDefaults.java b/qpid/java/common/src/main/java/org/apache/qpid/exchange/ExchangeDefaults.java index c9bf67c11d..5e59628fb6 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/exchange/ExchangeDefaults.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/exchange/ExchangeDefaults.java @@ -41,31 +41,30 @@ public class ExchangeDefaults } /** The default direct exchange, which is a special internal exchange that cannot be explicitly bound to. */ - public static final AMQShortString DEFAULT_EXCHANGE_NAME = AMQShortString.EMPTY_STRING; + public static final String DEFAULT_EXCHANGE_NAME = ""; /** The pre-defined topic exchange, the broker SHOULD provide this. */ - public static final AMQShortString TOPIC_EXCHANGE_NAME = new AMQShortString("amq.topic"); + public static final String TOPIC_EXCHANGE_NAME = "amq.topic"; /** Defines the identifying type name of topic exchanges. */ - public static final AMQShortString TOPIC_EXCHANGE_CLASS = new AMQShortString("topic"); + public static final String TOPIC_EXCHANGE_CLASS = "topic"; /** The pre-defined direct exchange, the broker MUST provide this. */ - public static final AMQShortString DIRECT_EXCHANGE_NAME = new AMQShortString("amq.direct"); + public static final String DIRECT_EXCHANGE_NAME = "amq.direct"; /** Defines the identifying type name of direct exchanges. */ - public static final AMQShortString DIRECT_EXCHANGE_CLASS = new AMQShortString("direct"); + public static final String DIRECT_EXCHANGE_CLASS = "direct"; /** The pre-defined headers exchange, the specification does not say this needs to be provided. */ - public static final AMQShortString HEADERS_EXCHANGE_NAME = new AMQShortString("amq.match"); + public static final String HEADERS_EXCHANGE_NAME = "amq.match"; /** Defines the identifying type name of headers exchanges. */ - public static final AMQShortString HEADERS_EXCHANGE_CLASS = new AMQShortString("headers"); + public static final String HEADERS_EXCHANGE_CLASS = "headers"; /** The pre-defined fanout exchange, the boker MUST provide this. */ - public static final AMQShortString FANOUT_EXCHANGE_NAME = new AMQShortString("amq.fanout"); + public static final String FANOUT_EXCHANGE_NAME = "amq.fanout"; /** Defines the identifying type name of fanout exchanges. */ - public static final AMQShortString FANOUT_EXCHANGE_CLASS = new AMQShortString("fanout"); - - public static final AMQShortString WILDCARD_ANY = new AMQShortString("*"); + public static final String FANOUT_EXCHANGE_CLASS = "fanout"; + } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java index 4adc59b158..a06fa2d15b 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/AMQShortString.java @@ -21,18 +21,15 @@ package org.apache.qpid.framing; +import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; -import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.Collection; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.WeakHashMap; /** * A short string is a representation of an AMQ Short String @@ -64,7 +61,7 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt { if(_count == -1) { - _count = 1 + AMQShortString.this.occurences(_delim); + _count = 1 + AMQShortString.this.occurrences(_delim); } return _count; } @@ -100,40 +97,8 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt return new AMQShortString(_data, from+_offset, to-from); } - - private static final int LOCAL_INTERN_CACHE_SIZE = 2048; - - private static final ThreadLocal<Map<AMQShortString, AMQShortString>> _localInternMap = - new ThreadLocal<Map<AMQShortString, AMQShortString>>() - { - protected Map<AMQShortString, AMQShortString> initialValue() - { - return new LinkedHashMap<AMQShortString, AMQShortString>() - { - @Override - protected boolean removeEldestEntry(Map.Entry<AMQShortString, AMQShortString> eldest) - { - return size() > LOCAL_INTERN_CACHE_SIZE; - } - }; - }; - }; - - private static final Map<AMQShortString, WeakReference<AMQShortString>> _globalInternMap = - new WeakHashMap<AMQShortString, WeakReference<AMQShortString>>(); - - - private static final ThreadLocal<Map<String, WeakReference<AMQShortString>>> _localStringMap = - new ThreadLocal<Map<String, WeakReference<AMQShortString>>>() - { - protected Map<String, WeakReference<AMQShortString>> initialValue() - { - return new WeakHashMap<String, WeakReference<AMQShortString>>(); - }; - }; - - private static final Map<String, WeakReference<AMQShortString>> _globalStringMap = - new WeakHashMap<String, WeakReference<AMQShortString>>(); + private static final ConcurrentHashMap<AMQShortString, AMQShortString> _globalInternMap = + new ConcurrentHashMap<AMQShortString, AMQShortString>(); private static final Logger _logger = LoggerFactory.getLogger(AMQShortString.class); @@ -443,7 +408,7 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt { if (_asString == null) { - AMQShortString intern = intern(); + AMQShortString intern = intern(false); if(intern == this) { @@ -641,35 +606,9 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt public AMQShortString intern(boolean keep) { - hashCode(); - - Map<AMQShortString, AMQShortString> localMap = - _localInternMap.get(); - - AMQShortString internString = localMap.get(this); - + AMQShortString internString = keep ? _globalInternMap.putIfAbsent(this,this) : _globalInternMap.get(this); - if(internString != null) - { - return internString; - } - - - WeakReference<AMQShortString> ref; - synchronized(_globalInternMap) - { - - ref = _globalInternMap.get(this); - if((ref == null) || ((internString = ref.get()) == null)) - { - internString = keep ? shrink() : copy(); - ref = new WeakReference(internString); - _globalInternMap.put(internString, ref); - } - - } - localMap.put(internString, internString); - return internString; + return internString == null ? this : internString; } @@ -680,7 +619,7 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt return new AMQShortString(dataBytes,0,_length); } - private int occurences(final byte delim) + private int occurrences(final byte delim) { int count = 0; final int end = _offset + _length; @@ -794,7 +733,12 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt return false; //To change body of created methods use File | Settings | File Templates. } - public static AMQShortString valueOf(Object obj, boolean truncate, boolean nullAsEmptyString) + public static AMQShortString validValueOf(Object obj) + { + return valueOf(obj,true,true); + } + + static AMQShortString valueOf(Object obj, boolean truncate, boolean nullAsEmptyString) { if (obj == null) { @@ -826,37 +770,11 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt { return null; } - - Map<String, WeakReference<AMQShortString>> localMap = - _localStringMap.get(); - - WeakReference<AMQShortString> ref = localMap.get(obj); - AMQShortString internString; - - if(ref != null) + else { - internString = ref.get(); - if(internString != null) - { - return internString; - } + return new AMQShortString(obj); } - - synchronized(_globalStringMap) - { - - ref = _globalStringMap.get(obj); - if((ref == null) || ((internString = ref.get()) == null)) - { - internString = (new AMQShortString(obj)).intern(); - ref = new WeakReference<AMQShortString>(internString); - _globalStringMap.put(obj, ref); - } - - } - localMap.put(obj, ref); - return internString; } public static String toString(AMQShortString amqShortString) @@ -864,10 +782,4 @@ public final class AMQShortString implements CharSequence, Comparable<AMQShortSt return amqShortString == null ? null : amqShortString.asString(); } - public static void clearLocalCache() - { - _localInternMap.remove(); - _localStringMap.remove(); - } - } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java index 4c7772a3a9..575816db4f 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/framing/amqp_8_0/MethodConverter_8_0.java @@ -79,9 +79,9 @@ public class MethodConverter_8_0 extends AbstractMethodConverter implements Prot _basicPublishClassId = BasicPublishBodyImpl.CLASS_ID; _basicPublishMethodId = BasicPublishBodyImpl.METHOD_ID; - + } - + public AMQBody convertToBody(byte[] data) { return new ContentBody(data); @@ -97,7 +97,7 @@ public class MethodConverter_8_0 extends AbstractMethodConverter implements Prot return new MessagePublishInfoImpl(exchange == null ? null : exchange.intern(), publishBody.getImmediate(), publishBody.getMandatory(), - routingKey == null ? null : routingKey.intern()); + routingKey == null ? null : routingKey.intern(false)); } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java index 158006f072..e9dec362a6 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/ssl/SSLContextFactory.java @@ -7,9 +7,9 @@ * 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 @@ -22,7 +22,6 @@ package org.apache.qpid.ssl; import org.apache.qpid.transport.network.security.ssl.QpidClientX509KeyManager; import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; -import org.apache.qpid.transport.network.security.ssl.QpidPeersOnlyTrustManager; import org.apache.qpid.transport.network.security.ssl.SSLUtil; import javax.net.ssl.KeyManager; @@ -42,55 +41,17 @@ import java.util.Collections; /** * Factory used to create SSLContexts. SSL needs to be configured * before this will work. - * + * */ public class SSLContextFactory { public static final String TRANSPORT_LAYER_SECURITY_CODE = "TLS"; - - public static class TrustStoreWrapper - { - private final String trustStorePath; - private final String trustStorePassword; - private final String trustStoreType; - private final Boolean trustStorePeersOnly; - private String trustManagerFactoryAlgorithm; - - public TrustStoreWrapper(final String trustStorePath, final String trustStorePassword, - final String trustStoreType, final Boolean trustStorePeersOnly, - final String trustManagerFactoryAlgorithm) - { - this.trustStorePath = trustStorePath; - this.trustStorePassword = trustStorePassword; - this.trustStoreType = trustStoreType; - this.trustStorePeersOnly = trustStorePeersOnly; - this.trustManagerFactoryAlgorithm = trustManagerFactoryAlgorithm; - } - } private SSLContextFactory() { //no instances } - public static SSLContext buildServerContext(final String keyStorePath, - final String keyStorePassword, final String keyStoreType, - final String keyManagerFactoryAlgorithm) - throws GeneralSecurityException, IOException - { - return buildContext(Collections.<TrustStoreWrapper>emptyList(), keyStorePath, - keyStorePassword, keyStoreType, keyManagerFactoryAlgorithm, null); - } - - public static SSLContext buildClientContext(Collection<TrustStoreWrapper> trustStores, - final String keyStorePath, final String keyStorePassword, - final String keyStoreType, final String keyManagerFactoryAlgorithm, - final String certAlias) throws GeneralSecurityException, IOException - { - return buildContext(trustStores, keyStorePath, keyStorePassword, keyStoreType, - keyManagerFactoryAlgorithm, certAlias); - } - public static SSLContext buildClientContext(final String trustStorePath, final String trustStorePassword, final String trustStoreType, final String trustManagerFactoryAlgorithm, final String keyStorePath, @@ -98,17 +59,25 @@ public class SSLContextFactory final String keyManagerFactoryAlgorithm, final String certAlias) throws GeneralSecurityException, IOException { - TrustStoreWrapper trstWrapper = new TrustStoreWrapper(trustStorePath, trustStorePassword, - trustStoreType, Boolean.FALSE, - trustManagerFactoryAlgorithm); - return buildContext(Collections.singletonList(trstWrapper), keyStorePath, - keyStorePassword, keyStoreType, keyManagerFactoryAlgorithm, certAlias); + return buildContext(trustStorePath, + trustStorePassword, + trustStoreType, + trustManagerFactoryAlgorithm, + keyStorePath, + keyStorePassword, + keyStoreType, + keyManagerFactoryAlgorithm, + certAlias); } - - private static SSLContext buildContext(final Collection<TrustStoreWrapper> trstWrappers, - final String keyStorePath, final String keyStorePassword, - final String keyStoreType, final String keyManagerFactoryAlgorithm, - final String certAlias) + + private static SSLContext buildContext(String trustStorePath, + String trustStorePassword, + String trustStoreType, + String trustManagerFactoryAlgorithm, + String keyStorePath, + String keyStorePassword, + String keyStoreType, + String keyManagerFactoryAlgorithm, String certAlias) throws GeneralSecurityException, IOException { // Initialize the SSLContext to work with our key managers. @@ -117,53 +86,20 @@ public class SSLContextFactory final TrustManager[] trustManagers; final KeyManager[] keyManagers; - - final Collection<TrustManager> trustManagersCol = new ArrayList<TrustManager>(); - final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager(); - for (TrustStoreWrapper tsw : trstWrappers) - { - if (tsw.trustStorePath != null) - { - final KeyStore ts = SSLUtil.getInitializedKeyStore(tsw.trustStorePath, - tsw.trustStorePassword, tsw.trustStoreType); - final TrustManagerFactory tmf = TrustManagerFactory - .getInstance(tsw.trustManagerFactoryAlgorithm); - tmf.init(ts); - TrustManager[] delegateManagers = tmf.getTrustManagers(); - for (TrustManager tm : delegateManagers) - { - if (tm instanceof X509TrustManager) - { - if (Boolean.TRUE.equals(tsw.trustStorePeersOnly)) - { - // truststore is supposed to trust only clients which peers certificates - // are directly in the store. CA signing will not be considered. - mulTrustManager.addTrustManager(new QpidPeersOnlyTrustManager(ts, (X509TrustManager) tm)); - } - else - { - mulTrustManager.addTrustManager((X509TrustManager) tm); - } - } - else - { - trustManagersCol.add(tm); - } - } - } - } - if (! mulTrustManager.isEmpty()) - { - trustManagersCol.add(mulTrustManager); - } - - if (trustManagersCol.isEmpty()) + + if (trustStorePath != null) { - trustManagers = null; + final KeyStore ts = SSLUtil.getInitializedKeyStore(trustStorePath, + trustStorePassword, trustStoreType); + final TrustManagerFactory tmf = TrustManagerFactory + .getInstance(trustManagerFactoryAlgorithm); + tmf.init(ts); + + trustManagers = tmf.getTrustManagers(); } else { - trustManagers = trustManagersCol.toArray(new TrustManager[trustManagersCol.size()]); + trustManagers = null; } if (keyStorePath != null) diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java index 478355edc1..bfd1ae8181 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/SecurityLayerFactory.java @@ -124,7 +124,7 @@ public class SecurityLayerFactory public String getUserID() { - return SSLUtil.retriveIdentity(_engine); + return SSLUtil.retrieveIdentity(_engine); } } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java index a527c436f8..7553e3dad8 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java @@ -1,5 +1,5 @@ /* - * + * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -7,19 +7,22 @@ * 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.transport.network.security.ssl; +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.naming.ldap.Rdn; import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.util.Logger; @@ -50,21 +53,21 @@ public class SSLUtil Certificate cert = engine.getSession().getPeerCertificates()[0]; Principal p = ((X509Certificate)cert).getSubjectDN(); String dn = p.getName(); - String hostname = null; - + String hostname = null; + if (dn.contains("CN=")) { hostname = dn.substring(3, dn.indexOf(",") == -1? dn.length(): dn.indexOf(",")); - } - + } + if (log.isDebugEnabled()) { log.debug("Hostname expected : " + hostnameExpected); log.debug("Distinguished Name for server certificate : " + dn); log.debug("Host Name obtained from DN : " + hostname); } - + if (hostname != null && !(hostname.equalsIgnoreCase(hostnameExpected) || hostname.equalsIgnoreCase(hostnameExpected + ".localdomain"))) { @@ -72,60 +75,78 @@ public class SSLUtil " Expected : " + hostnameExpected + " Found in cert : " + hostname); } - + } catch(SSLPeerUnverifiedException e) { log.warn("Exception received while trying to verify hostname",e); // For some reason the SSL engine sets the handshake status to FINISH twice - // in succession. The first time the peer certificate + // in succession. The first time the peer certificate // info is not available. The second time it works ! // Therefore have no choice but to ignore the exception here. } } - - public static String retriveIdentity(SSLEngine engine) + + public static String getIdFromSubjectDN(String dn) { - StringBuffer id = new StringBuffer(); + String cnStr = null; + String dcStr = null; + if(dn == null) + { + return ""; + } + else + { + try + { + LdapName ln = new LdapName(dn); + for(Rdn rdn : ln.getRdns()) + { + if("CN".equalsIgnoreCase(rdn.getType())) + { + cnStr = rdn.getValue().toString(); + } + else if("DC".equalsIgnoreCase(rdn.getType())) + { + if(dcStr == null) + { + dcStr = rdn.getValue().toString(); + } + else + { + dcStr = rdn.getValue().toString() + '.' + dcStr; + } + } + } + return cnStr == null || cnStr.length()==0 ? "" : dcStr == null ? cnStr : cnStr + '@' + dcStr; + } + catch (InvalidNameException e) + { + log.warn("Invalid name: '"+dn+"'. "); + return ""; + } + } + } + + + public static String retrieveIdentity(SSLEngine engine) + { + String id = ""; + Certificate cert = engine.getSession().getLocalCertificates()[0]; + Principal p = ((X509Certificate)cert).getSubjectDN(); + String dn = p.getName(); try { - Certificate cert = engine.getSession().getLocalCertificates()[0]; - Principal p = ((X509Certificate)cert).getSubjectDN(); - String dn = p.getName(); - - if (dn.contains("CN=")) - { - String str = dn.substring(dn.indexOf("CN=")+3, dn.length()); - id.append(str.substring(0, - str.indexOf(",") == -1? str.length(): str.indexOf(","))); - } - - if (dn.contains("DC=")) - { - id.append("@"); - int c = 0; - for (String toks : dn.split(",")) - { - if (toks.contains("DC")) - { - if (c > 0) {id.append(".");} - id.append(toks.substring( - toks.indexOf("=")+1, - toks.indexOf(",") == -1? toks.length(): toks.indexOf(","))); - c++; - } - } - } + id = SSLUtil.getIdFromSubjectDN(dn); } - catch(Exception e) + catch (Exception e) { - log.info("Exception received while trying to retrive client identity from SSL cert",e); + log.info("Exception received while trying to retrive client identity from SSL cert", e); } - log.debug("Extracted Identity from client certificate : " + id); - return id.toString(); + return id; } - + public static KeyStore getInitializedKeyStore(String storePath, String storePassword, String keyStoreType) throws GeneralSecurityException, IOException { KeyStore ks = KeyStore.getInstance(keyStoreType); @@ -137,7 +158,7 @@ public class SSLUtil { in = new FileInputStream(f); } - else + else { in = Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath); } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java b/qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java index 3b9a0baab2..77902c3531 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/url/AMQBindingURL.java @@ -34,9 +34,9 @@ public class AMQBindingURL implements BindingURL private static final Logger _logger = LoggerFactory.getLogger(AMQBindingURL.class); private String _url; - private AMQShortString _exchangeClass = ExchangeDefaults.DIRECT_EXCHANGE_CLASS; + private AMQShortString _exchangeClass = AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS); private AMQShortString _exchangeName = new AMQShortString(""); - private AMQShortString _destinationName = new AMQShortString("");; + private AMQShortString _destinationName = new AMQShortString(""); private AMQShortString _queueName = new AMQShortString(""); private AMQShortString[] _bindingKeys = new AMQShortString[0]; private HashMap<String, String> _options; @@ -56,7 +56,6 @@ public class AMQBindingURL implements BindingURL { BindingURLParser parser = new BindingURLParser(); parser.parse(_url,this); - processOptions(); _logger.debug("URL Parsed: " + this); } @@ -80,10 +79,6 @@ public class AMQBindingURL implements BindingURL setExchangeName(new AMQShortString(exchangeName)); } - private void processOptions() throws URISyntaxException - { - } - public String getURL() { return _url; @@ -98,7 +93,7 @@ public class AMQBindingURL implements BindingURL { _exchangeClass = exchangeClass; - if (exchangeClass.equals(ExchangeDefaults.TOPIC_EXCHANGE_CLASS)) + if (exchangeClass.equals(AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS))) { setOption(BindingURL.OPTION_EXCLUSIVE, "true"); } @@ -152,11 +147,11 @@ public class AMQBindingURL implements BindingURL public AMQShortString getRoutingKey() { - if (_exchangeClass.equals(ExchangeDefaults.DIRECT_EXCHANGE_CLASS)) + if (_exchangeClass.equals(AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS))) { if (containsOption(BindingURL.OPTION_ROUTING_KEY)) { - return new AMQShortString((String)getOption(OPTION_ROUTING_KEY)); + return new AMQShortString(getOption(OPTION_ROUTING_KEY)); } else { @@ -166,7 +161,7 @@ public class AMQBindingURL implements BindingURL if (containsOption(BindingURL.OPTION_ROUTING_KEY)) { - return new AMQShortString((String)getOption(OPTION_ROUTING_KEY)); + return new AMQShortString(getOption(OPTION_ROUTING_KEY)); } return getDestinationName(); @@ -196,7 +191,7 @@ public class AMQBindingURL implements BindingURL public String toString() { - StringBuffer sb = new StringBuffer(); + StringBuilder sb = new StringBuilder(); sb.append(_exchangeClass); sb.append("://"); @@ -212,7 +207,7 @@ public class AMQBindingURL implements BindingURL if (getRoutingKey() == null || getRoutingKey().toString().equals("")) { - if (sb.toString().indexOf("?") == -1) + if (!sb.toString().contains("?")) { sb.append("?"); } diff --git a/qpid/java/common/src/main/java/org/apache/qpid/url/BindingURL.java b/qpid/java/common/src/main/java/org/apache/qpid/url/BindingURL.java index 61585443b1..80a1ae540b 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/url/BindingURL.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/url/BindingURL.java @@ -32,8 +32,6 @@ public interface BindingURL public static final String OPTION_AUTODELETE = "autodelete"; public static final String OPTION_DURABLE = "durable"; public static final String OPTION_BROWSE = "browse"; - public static final String OPTION_CLIENTID = "clientid"; - public static final String OPTION_SUBSCRIPTION = "subscription"; public static final String OPTION_ROUTING_KEY = "routingkey"; public static final String OPTION_BINDING_KEY = "bindingkey"; public static final String OPTION_EXCHANGE_AUTODELETE = "exchangeautodelete"; diff --git a/qpid/java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java b/qpid/java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java index 939080e252..ee823978b4 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/url/BindingURLParser.java @@ -1,5 +1,5 @@ /* - * + * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -7,16 +7,16 @@ * 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.url; @@ -61,7 +61,8 @@ public class BindingURLParser } //<exch_class>://<exch_name>/[<destination>]/[<queue>]?<option>='<value>'[,<option>='<value>']* - public synchronized void parse(String url,AMQBindingURL bindingURL) throws URISyntaxException + public synchronized void + parse(String url,AMQBindingURL bindingURL) throws URISyntaxException { _url = (url + END_OF_URL_MARKER_CHAR).toCharArray(); _bindingURL = bindingURL; @@ -203,14 +204,14 @@ public class BindingURLParser // "myQueue?durable='true'" use case else if (nextChar == QUESTION_MARK_CHAR) { - _bindingURL.setExchangeClass(ExchangeDefaults.DIRECT_EXCHANGE_CLASS.asString()); + _bindingURL.setExchangeClass(ExchangeDefaults.DIRECT_EXCHANGE_CLASS); _bindingURL.setExchangeName(""); _bindingURL.setQueueName(builder.toString()); return BindingURLParserState.QUESTION_MARK_CHAR; } else { - _bindingURL.setExchangeClass(ExchangeDefaults.DIRECT_EXCHANGE_CLASS.asString()); + _bindingURL.setExchangeClass(ExchangeDefaults.DIRECT_EXCHANGE_CLASS); _bindingURL.setExchangeName(""); _bindingURL.setQueueName(builder.toString()); return BindingURLParserState.BINDING_URL_END; @@ -418,31 +419,11 @@ public class BindingURLParser { throw new URISyntaxException(String.valueOf(_url),"It is illegal to specify both a routingKey and a bindingKey in the same URL",-1); } - - // check for durable subscriptions - if (_bindingURL.getExchangeClass().equals(ExchangeDefaults.TOPIC_EXCHANGE_CLASS)) - { - String queueName = null; - if (Boolean.parseBoolean(_bindingURL.getOption(BindingURL.OPTION_DURABLE))) - { - if (_bindingURL.containsOption(BindingURL.OPTION_CLIENTID) && _bindingURL.containsOption(BindingURL.OPTION_SUBSCRIPTION)) - { - queueName = _bindingURL.getOption(BindingURL.OPTION_CLIENTID) + ":" + _bindingURL.getOption(BindingURL.OPTION_SUBSCRIPTION); - } - else - { - throw new URISyntaxException(String.valueOf(_url),"Durable subscription must have values for " + BindingURL.OPTION_CLIENTID - + " and " + BindingURL.OPTION_SUBSCRIPTION , -1); - - } - } - _bindingURL.setQueueName(queueName); - } } public static void main(String[] args) { - + String[] urls = new String[] { "topic://amq.topic//myTopic?routingkey='stocks.#'", diff --git a/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java b/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java index 575058b7f8..9fceef337c 100644 --- a/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java +++ b/qpid/java/common/src/test/java/org/apache/qpid/AMQExceptionTest.java @@ -101,7 +101,7 @@ public class AMQExceptionTest extends TestCase sb.append("message [" + i + "]"); } AMQException e = new AMQException(AMQConstant.INTERNAL_ERROR, sb.toString(), null); - AMQShortString message = e.getMessageAsShortString(); + AMQShortString message = AMQShortString.validValueOf(e.getMessage()); assertEquals(sb.substring(0, AMQShortString.MAX_LENGTH - 3) + "...", message.toString()); } diff --git a/qpid/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java b/qpid/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java index 21b8871d9a..c5fa852f95 100644 --- a/qpid/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java +++ b/qpid/java/common/src/test/java/org/apache/qpid/ssl/SSLContextFactoryTest.java @@ -36,25 +36,7 @@ public class SSLContextFactoryTest extends QpidTestCase private static final String DEFAULT_TRUST_MANAGER_ALGORITHM = TrustManagerFactory.getDefaultAlgorithm(); private static final String CERT_ALIAS_APP1 = "app1"; - public void testBuildServerContext() throws Exception - { - SSLContext context = SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM); - assertNotNull("SSLContext should not be null", context); - } - public void testBuildServerContextWithIncorrectPassword() throws Exception - { - try - { - SSLContextFactory.buildServerContext(BROKER_KEYSTORE_PATH, "sajdklsad", STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM); - fail("Exception was not thrown due to incorrect password"); - } - catch (IOException e) - { - //expected - } - } - public void testTrustStoreDoesNotExist() throws Exception { try @@ -79,7 +61,7 @@ public class SSLContextFactoryTest extends QpidTestCase SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_TRUST_MANAGER_ALGORITHM, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM, null); assertNotNull("SSLContext should not be null", context); } - + public void testBuildClientContextWithForClientAuthWithCertAlias() throws Exception { SSLContext context = SSLContextFactory.buildClientContext(CLIENT_TRUSTSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_TRUST_MANAGER_ALGORITHM, CLIENT_KEYSTORE_PATH, STORE_PASSWORD, STORE_TYPE, DEFAULT_KEY_MANAGER_ALGORITHM, CERT_ALIAS_APP1); diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/security/ssl/SSLUtilTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/security/ssl/SSLUtilTest.java new file mode 100644 index 0000000000..2d17f7a3c7 --- /dev/null +++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/security/ssl/SSLUtilTest.java @@ -0,0 +1,52 @@ +/* + * + * 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.transport.network.security.ssl; + +import org.apache.qpid.test.utils.QpidTestCase; + +public class SSLUtilTest extends QpidTestCase +{ + public void testGetIdFromSubjectDN() + { + // "normal" dn + assertEquals("user@somewhere.example.org",SSLUtil.getIdFromSubjectDN("cn=user,dc=somewhere,dc=example,dc=org")); + // quoting of values, case of types, spacing all ignored + assertEquals("user2@somewhere.example.org",SSLUtil.getIdFromSubjectDN("DC=somewhere, dc=example,cn=\"user2\",dc=org")); + // only first cn is used + assertEquals("user@somewhere.example.org",SSLUtil.getIdFromSubjectDN("DC=somewhere, dc=example,cn=\"user\",dc=org, cn=user2")); + // no cn, no Id + assertEquals("",SSLUtil.getIdFromSubjectDN("DC=somewhere, dc=example,dc=org")); + // cn in value is ignored + assertEquals("",SSLUtil.getIdFromSubjectDN("C=CZ,O=Scholz,OU=\"JAKUB CN=USER1\"")); + // cn with no dc gives just user + assertEquals("someone",SSLUtil.getIdFromSubjectDN("ou=someou, CN=\"someone\"")); + // null results in empty string + assertEquals("",SSLUtil.getIdFromSubjectDN(null)); + // invalid name results in empty string + assertEquals("",SSLUtil.getIdFromSubjectDN("ou=someou, =")); + // component containing whitespace + assertEquals("me@example.com",SSLUtil.getIdFromSubjectDN("CN=me,DC=example, DC=com, O=My Company Ltd, L=Newbury, ST=Berkshire, C=GB")); + // empty CN + assertEquals("",SSLUtil.getIdFromSubjectDN("CN=,DC=somewhere, dc=example,dc=org")); + + + } +} diff --git a/qpid/java/ivy.nexus.xml b/qpid/java/ivy.nexus.xml index f47aab7454..d492169ff3 100644 --- a/qpid/java/ivy.nexus.xml +++ b/qpid/java/ivy.nexus.xml @@ -57,6 +57,66 @@ <artifact name="qpid-broker-plugins-management-jmx" type="jar.asc" ext="jar.asc"/> <artifact name="qpid-broker-plugins-management-jmx" type="source" ext="jar" e:classifier="sources"/> <artifact name="qpid-broker-plugins-management-jmx" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-0-10-protocol" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-amqp-0-10-protocol" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-amqp-0-10-protocol" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-amqp-0-10-protocol" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-amqp-0-10-protocol" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-0-10-protocol" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-0-8-protocol" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-amqp-0-8-protocol" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-amqp-0-8-protocol" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-amqp-0-8-protocol" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-amqp-0-8-protocol" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-0-8-protocol" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-1-0-protocol" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-amqp-1-0-protocol" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-amqp-1-0-protocol" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-amqp-1-0-protocol" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-amqp-1-0-protocol" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-1-0-protocol" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-10-to-1-0" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-0-10" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-amqp-msg-conv-0-8-to-1-0" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-derby-store" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-derby-store" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-derby-store" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-derby-store" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-derby-store" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-derby-store" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-jdbc-store" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-jdbc-store" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-jdbc-store" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-jdbc-store" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-jdbc-store" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-jdbc-store" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-memory-store" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-memory-store" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-memory-store" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-memory-store" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-memory-store" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-memory-store" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-jdbc-provider-bone" type="pom" ext="pom"/> + <artifact name="qpid-broker-plugins-jdbc-provider-bone" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-broker-plugins-jdbc-provider-bone" type="jar" ext="jar"/> + <artifact name="qpid-broker-plugins-jdbc-provider-bone" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-broker-plugins-jdbc-provider-bone" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-broker-plugins-jdbc-provider-bone" type="source.asc" ext="jar.asc" e:classifier="sources"/> <artifact name="qpid-amqp-1-0-common" type="pom" ext="pom"/> <artifact name="qpid-amqp-1-0-common" type="pom.asc" ext="pom.asc"/> <artifact name="qpid-amqp-1-0-common" type="jar" ext="jar"/> diff --git a/qpid/java/ivy.retrieve.xml b/qpid/java/ivy.retrieve.xml index fff99e7aca..faecfb2dbf 100644 --- a/qpid/java/ivy.retrieve.xml +++ b/qpid/java/ivy.retrieve.xml @@ -76,7 +76,7 @@ <!-- The following are optional dependencies, for modules providing optional functionlity or for use in optional build/test steps. Their optional status is usually indicative of licences which are not compatible with the Apache Licence --> - <dependency org="com.sleepycat" name="je" rev="5.0.73" transitive="false" conf="bdbje"/> + <dependency org="com.sleepycat" name="je" rev="5.0.84" transitive="false" conf="bdbje"/> <dependency org="jfree" name="jfreechart" rev="1.0.13" transitive="false" conf="jfree"/> <dependency org="jfree" name="jcommon" rev="1.0.16" transitive="false" conf="jfree"/> <dependency org="com.jolbox" name="bonecp" rev="0.7.1.RELEASE" transitive="false" conf="bonecp"/> diff --git a/qpid/java/jca/README-JBOSS.txt b/qpid/java/jca/README-JBOSS.txt index e88643e0f2..717565b938 100644 --- a/qpid/java/jca/README-JBOSS.txt +++ b/qpid/java/jca/README-JBOSS.txt @@ -101,7 +101,7 @@ provides two such objects name="qpid.jca:name=HelloQueue"> <attribute name="JNDIName">Hello</attribute> <depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name='qpid-ra-<ra-version>.rar'</depends> - <attribute name="Type">javax.jms.Destination</attribute> + <attribute name="Type">org.apache.qpid.ra.admin.QpidQueue/attribute> <attribute name="Properties"> DestinationAddress=amq.direct </attribute> @@ -118,7 +118,7 @@ can be customized for your environment. Please see the Qpid Java Client document name="qpid.jca:name=HelloTopic"> <attribute name="JNDIName">HelloTopic</attribute> <depends optional-attribute-name="RARName">jboss.jca:service=RARDeployment,name='qpid-ra-<ra-version>.rar'</depends> - <attribute name="Type">javax.jms.Destination</attribute> + <attribute name="Type">org.apache.qpid.ra.admin.QpidTopic</attribute> <attribute name="Properties"> DestinationAddress=amq.topic </attribute> diff --git a/qpid/java/jca/README.txt b/qpid/java/jca/README.txt index a4d426310d..d4c14112a4 100644 --- a/qpid/java/jca/README.txt +++ b/qpid/java/jca/README.txt @@ -97,7 +97,7 @@ UseConnectionPerHandler The Apache C++ Broker multiplexes on the physical connection rather than the session. As a result, performance improvements can be gained by allocating and assigning a connection per inbound listener. The alternative is to share a connection across each handler for a given endpoint (MDB). -Default:true +Default:false The ManagedConnectionFactory JavaBean ===================================== diff --git a/qpid/java/jca/example/README-JBOSS7.txt b/qpid/java/jca/example/README-JBOSS7.txt index 7a3e0db01a..5234a0b293 100644 --- a/qpid/java/jca/example/README-JBOSS7.txt +++ b/qpid/java/jca/example/README-JBOSS7.txt @@ -64,8 +64,6 @@ deploy this file copy the file to: JBOSS_HOME/standalone/configuration -directory. - Prior to deploying any application component, the JBoss application server should be started and available for requests. In order to use the qpid-standalone.xml file generated in the previous step, when starting JBoss AS 7 invoke the following: @@ -100,7 +98,22 @@ will attempt to deploy the Qpid JCA example EAR into the JBoss AS 7 environment. Once the above command executes successfully, the Qpid JCA example application is deployed, configured and ready for use. -Note, currently there is an issue with 'hot-deployment' in the JBoss AS 7 environment. +If you choose to use the standalone 'thin' EJB3 client example, you will need to configure +the security realm for your application. Please see + +http://www.mastertheboss.com/jboss-as-7/jboss-as-7-remote-ejb-client-tutorial + +on instructions for how to do this in the JBoss7 environment. Once this is done you +will need to change the conf/jboss-ejb-client.properties file to use your recently +configured username/password for your application: + +remote.connection.default.username=CHANGEME +remote.connection.default.password=CHANGEME + +Modify these properties to use the username/password you configured in the +above step. + +Currently there is an issue with 'hot-deployment' in the JBoss AS 7 environment. If you need to re-deploy the EAR file, restarting JBoss AS 7 is required. The build-jboss7-properties.xml file contains JBoss AS 7 specific configuration options diff --git a/qpid/java/jca/example/conf/jboss-ejb-client.properties b/qpid/java/jca/example/conf/jboss-ejb-client.properties index 8bf1075c14..9b62e6794c 100644 --- a/qpid/java/jca/example/conf/jboss-ejb-client.properties +++ b/qpid/java/jca/example/conf/jboss-ejb-client.properties @@ -7,6 +7,6 @@ remote.connection.default.host=localhost remote.connection.default.port = 4447 remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false -remote.connection.default.username=wmprice -remote.connection.default.password=72whtu78 +remote.connection.default.username=CHANGEME +remote.connection.default.password=CHANGEME diff --git a/qpid/java/jca/rar/src/main/resources/META-INF/ra.xml b/qpid/java/jca/rar/src/main/resources/META-INF/ra.xml index a9374f52d7..4819bc8ad5 100755 --- a/qpid/java/jca/rar/src/main/resources/META-INF/ra.xml +++ b/qpid/java/jca/rar/src/main/resources/META-INF/ra.xml @@ -109,12 +109,12 @@ <config-property-type>java.lang.String</config-property-type> <config-property-value>amqp://anonymous:passwd@client/test?brokerlist='tcp://localhost?sasl_mechs='PLAIN''</config-property-value> </config-property> - + <config-property> <description>Use a JMS Connection per MessageHandler</description> <config-property-name>UseConnectionPerHandler</config-property-name> <config-property-type>java.lang.Boolean</config-property-type> - <config-property-value>true</config-property-value> + <config-property-value>false</config-property-value> </config-property> <outbound-resourceadapter> diff --git a/qpid/java/lib/poms/bonecp-0.7.1.RELEASE.xml b/qpid/java/lib/poms/bonecp-0.7.1.RELEASE.xml index a9b7581e3e..6a9ff3d214 100644 --- a/qpid/java/lib/poms/bonecp-0.7.1.RELEASE.xml +++ b/qpid/java/lib/poms/bonecp-0.7.1.RELEASE.xml @@ -19,4 +19,10 @@ <groupId>com.jolbox</groupId> <artifactId>bonecp</artifactId> <version>0.7.1.RELEASE</version> + <exclusions> + <exclusion> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + </exclusion> + </exclusions> </dep> diff --git a/qpid/java/lib/poms/guava-14.0.1.xml b/qpid/java/lib/poms/guava-14.0.1.xml index 9ff023bef0..79e42308c2 100644 --- a/qpid/java/lib/poms/guava-14.0.1.xml +++ b/qpid/java/lib/poms/guava-14.0.1.xml @@ -16,7 +16,7 @@ limitations under the License. --> <dep> - <groupId>com.google</groupId> + <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>14.0.1</version> </dep> diff --git a/qpid/java/lib/poms/je-5.0.73.xml b/qpid/java/lib/poms/je-5.0.84.xml index d55c4ec14f..7a556bbe1c 100644 --- a/qpid/java/lib/poms/je-5.0.73.xml +++ b/qpid/java/lib/poms/je-5.0.84.xml @@ -18,5 +18,5 @@ <dep> <groupId>com.sleepycat</groupId> <artifactId>je</artifactId> - <version>5.0.73</version> + <version>5.0.84</version> </dep> diff --git a/qpid/java/management/common/src/main/java/management-common.bnd b/qpid/java/management/common/src/main/java/management-common.bnd index dad6055a13..b31617a2e1 100644 --- a/qpid/java/management/common/src/main/java/management-common.bnd +++ b/qpid/java/management/common/src/main/java/management-common.bnd @@ -17,7 +17,7 @@ # under the License. # -ver: 0.23.0 +ver: 0.25.0 Bundle-SymbolicName: qpid-management-common Bundle-Version: ${ver} diff --git a/qpid/java/module.xml b/qpid/java/module.xml index ce54e108c5..b3029645e0 100644 --- a/qpid/java/module.xml +++ b/qpid/java/module.xml @@ -74,6 +74,7 @@ <property name="module.genpom.args" value=""/> <property name="module.maven.depends" value=""/> <property name="maven.remote.repo" value="file://${module.release.base}/maven"/> + <property name="eclipse.project.suffix" value=""/> <property name="broker.log.prefix" value="BROKER: "/> <property name="broker.log.interleave" value="true"/> @@ -521,10 +522,15 @@ </jar> </target> - <target name="copy-broker-plugin-jars" if="broker.plugin" description="copy broker plugins for use in release packaging"> + <target name="copy-broker-plugin-jars" depends="copy-broker-plugin-jars-deps" if="broker.plugin" description="copy broker plugins for use in release packaging"> <copy file="${module.jar}" todir="${build.scratch.broker.plugins.lib}" failonerror="true"/> </target> + <!-- Overridden in broker-plugins/amqp-1-0-protocol, bdbstore, and bdbstore/jmx modules --> + <target name="copy-broker-plugin-jars-deps" if="broker.plugin" description="copy broker plugins dependencies for use in release packaging"> + <copylist todir="${build.scratch.broker.plugins.lib}" dir="${project.root}" files="${module.libs}"/> + </target> + <target name="copy-files-to-module-metainf" depends="copy-project-resources-metainf, copy-module-resources-metainf, copy-module-src-resources-metainf"/> <target name="copy-project-resources-metainf"> @@ -909,7 +915,7 @@ qpid.name=${project.name} <map from="${project.root}${file.separator}" to=''/> </pathconvert> <map property="eclipse.required.slashedprojectnames" value="${eclipse.required.projectnames}" join="${path.separator}"> - <globmapper from="*" to="/*"/> + <globmapper from="*" to="/*${eclipse.project.suffix}"/> </map> <echo message="Ant module dependencies : ${module.depends} ${module.test.depends} converted to Eclipse required project(s): ${eclipse.required.slashedprojectnames}"/> @@ -921,7 +927,7 @@ qpid.name=${project.name} <!-- Create the Eclipse .project --> <target name="eclipse-project"> <eclipse updatealways="${eclipse.updatealways}"> - <project name="${module.name}"/> + <project name="${module.name}${eclipse.project.suffix}"/> <!-- If the Eclipse task were to ever support the generation of linked resources, we would configure it to generate diff --git a/qpid/java/perftests/README-java-perftests.txt b/qpid/java/perftests/README-java-perftests.txt deleted file mode 100644 index 9af77ebb21..0000000000 --- a/qpid/java/perftests/README-java-perftests.txt +++ /dev/null @@ -1,105 +0,0 @@ -The qpid-perftests distributed JMS test framework -================================================= - -This folder contains the distributed test (aka Perf Test) framework written for -testing the performance of a JMS provider. Although it was written for the -purpose of testing Qpid, it can be used to test the performance of any JMS -provider with minimal configuration changes. - -This document explains how to use the framework. - - -How it works ------------- - -First, you need to run a message broker. This can be Qpid, ActiveMQ etc. All -messages are sent using the JMS API. - -Then run a Perf Test Controller, providing the details of the test in either or -a JSON or Javascript file. This specifies details about the messages to send, -how many connections and sessions to use etc. There are a lot of options -available - see the .js and .json files under this folder for examples. - -Now run one or more Perf Test Client processes. These will be responsible for -sending/receiving the messages once the test starts. For convenience, you can -instead configure the Controller to start clients in-process. The clients and -the controller communicate using queues on the message broker. - -The test results are written to CSV files. - -You can use the qpid-perftests-visualisation tool to create charts from the CSV files. - -Example usage -------------- - -The etc/ folder contains shell scripts that can be used to run the performance -tests and visualise the results. It also contains sub-folders for test config -and chart definitions. - -Instructions ------------- - -1. Extract the archive - -2. cd into the etc/ folder - -3. Start your JMS broker - -4. To run the Controller and clients in a single process, run the following -command: - -java -cp ".:../lib/*:/path/to/your-jms-client-jars/*" \ - -Dqpid.dest_syntax=BURL \ - org.apache.qpid.disttest.ControllerRunner \ - jndi-config=perftests-jndi.properties \ - test-config=/path/to/test-config.json \ - distributed=false - -Note that the test-config parameter can point at either a JSON or Javascript -file, or at a directory (in which case all the .json and .js files in the -directory are used. - -When the test is complete, the CSV files containing the results are written to -the current directory. - - -Running the clients in a separate process ------------------------------------------ - -When using a large number of clients, you may get more representative -performance results if the clients are distributed among multiple processes, -potentially on multiple machines. To do this: - -1. Run the Controller, providing distributed=true. - -2. Run your clients (assuming you want to launch 10 logical clients in this -process): - -java -cp ".:../lib/*:/path/to/your-jms-client-jars/*" \ - -Dqpid.dest_syntax=BURL \ - org.apache.qpid.disttest.ClientRunner \ - jndi-config=perftests-jndi.properties \ - number-of-clients=10 - - -Caveats for non-Qpid JMS providers ----------------------------------- - -If you are not using the Qpid broker, you must create one or more queues before -running the test. This is necessary because you can't use Qpid's API to create -queues on the broker. The queues are: - -– The controller queue. You can specify the physical name of this in -etc/perftests-jndi.properties. This queue is used by the clients to register -with the Controller and to send results to it. -– the queue(s) used by your JSON test configuration (unless you have configured -a vendor-specific queue creator). - -You must also override the Controller's default queue creator using the system -property qpid.disttest.queue.creator.class. Provide the class name of an -implementation of org.apache.qpid.disttest.jms.QueueCreator, or -org.apache.qpid.disttest.jms.NoOpQueueCreator if you are going to create and -delete the queues manually. - -You can also omit the qpid.dest_syntax system property if your JMS provider is -not Qpid. diff --git a/qpid/java/perftests/build.xml b/qpid/java/perftests/build.xml index d29649ad68..3b19c7645a 100644 --- a/qpid/java/perftests/build.xml +++ b/qpid/java/perftests/build.xml @@ -33,7 +33,7 @@ </condition> <property name="module.depends" value="client common"/> - <property name="module.test.depends" value="systests broker common/tests management/common ${perftests.optional.test.depends}"/> + <property name="module.test.depends" value="systests broker broker-plugins/memory-store broker-plugins/derby-store common/tests management/common broker-plugins/amqp-0-8-protocol broker-plugins/amqp-0-10-protocol broker-plugins/amqp-1-0-protocol ${perftests.optional.test.depends}"/> <import file="../module.xml"/> diff --git a/qpid/java/resources/README.txt b/qpid/java/resources/README.txt index 1d52d487fb..eec46a52f0 100644 --- a/qpid/java/resources/README.txt +++ b/qpid/java/resources/README.txt @@ -1,40 +1,3 @@ +Documentation for the Qpid components can be accessed on our website at: -Documentation --------------- -All of our user documentation for the Qpid Java components can be accessed on our wiki at: - -http://cwiki.apache.org/confluence/display/qpid/Qpid+Java+Documentation - -This includes a Getting Started Guide and FAQ as well as detailed developer documentation. -However, here's a VERY quick guide to running the installed Qpid broker, once you have installed it somewhere ! - - -Running the Broker ------------------- - -To run the broker, set the QPID_HOME environment variable to -distribution directory and add $QPID_HOME/bin to your PATH. Then run -the qpid-server shell script or qpid-server.bat batch file to start -the broker. By default, the broker will use $QPID_HOME/etc to find -the configuration files. You can supply a custom configuration using -the -c argument. - -For example: - -qpid-server -c ~/etc/config.xml - -You can get a list of all command line arguments by using the -h argument. - - -Developing ----------- - -In order to build Qpid you need Ant 1.6.5. Use ant -p to list the -available targets. The default ant target, build, creates a working -development-mode distribution in the build directory. To run the -scripts in build/bin set QPID_HOME to the build directory and put -${QPID_HOME}/bin on your PATH. The scripts in that directory include -the standard ones in the distribution and a number of testing scripts. - - - +http://qpid.apache.org/documentation.html diff --git a/qpid/java/systests/build.xml b/qpid/java/systests/build.xml index dee73b2e1e..59fcb8bbd2 100644 --- a/qpid/java/systests/build.xml +++ b/qpid/java/systests/build.xml @@ -34,7 +34,7 @@ nn - or more contributor license agreements. See the NOTICE file <!-- The jca module is unusual in that it produces a jar with the name ra rather than jca. Unfortunately this means we need to add both jca (finds jca's jar dependencies) and ra (to find the qpid-ra jar file itself). --> - <property name="module.depends" value="client management/common broker broker/tests common amqp-1-0-common common/tests jca ra broker-plugins/access-control broker-plugins/management-http broker-plugins/management-jmx ${systests.optional.depends}"/> + <property name="module.depends" value="client management/common broker broker/tests common amqp-1-0-common common/tests jca ra broker-plugins/access-control broker-plugins/management-http broker-plugins/management-jmx broker-plugins/memory-store broker-plugins/derby-store broker-plugins/amqp-0-8-protocol broker-plugins/amqp-0-10-protocol broker-plugins/amqp-1-0-protocol broker-plugins/amqp-msg-conv-0-8-to-0-10 broker-plugins/amqp-msg-conv-0-8-to-1-0 broker-plugins/amqp-msg-conv-0-10-to-1-0 ${systests.optional.depends}"/> <property name="module.test.src" location="src/main/java"/> <property name="module.test.excludes" value="**/DropInTest.java,**/TestClientControlledTest.java"/> diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java index 4f8a6ee54a..8822fc5373 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/failover/FailoverBehaviourTest.java @@ -466,7 +466,7 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio try { - // an implicit recover performed when acknowledge throws an exception due to failover + // an implicit recover performed when acknowledge throws an exception due to failover lastMessage.acknowledge(); fail("JMSException should be thrown"); } @@ -529,7 +529,7 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio Message lastMessage = consumeMessages(); try { - // an implicit recover performed when acknowledge throws an exception due to failover + // an implicit recover performed when acknowledge throws an exception due to failover lastMessage.acknowledge(); fail("JMSException should be thrown"); } @@ -923,9 +923,9 @@ public class FailoverBehaviourTest extends FailoverBaseCase implements Connectio final Map<String, Object> arguments = new HashMap<String, Object>(); arguments.put("x-qpid-capacity", capacity); arguments.put("x-qpid-flow-resume-capacity", resumeCapacity); - ((AMQSession<?, ?>) session).createQueue(new AMQShortString(queueName), true, true, false, arguments); + ((AMQSession<?, ?>) session).createQueue(new AMQShortString(queueName), false, true, false, arguments); Queue queue = session.createQueue("direct://amq.direct/" + queueName + "/" + queueName + "?durable='" + true - + "'&autodelete='" + true + "'"); + + "'&autodelete='" + false + "'"); ((AMQSession<?, ?>) session).declareAndBind((AMQDestination) queue); return queue; } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/client/session/QueueDeclareTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/client/session/QueueDeclareTest.java new file mode 100644 index 0000000000..fefed5b4ab --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/client/session/QueueDeclareTest.java @@ -0,0 +1,68 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.client.session; + +import java.util.Collections; + +import javax.jms.Connection; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Session; + +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.url.AMQBindingURL; + +public class QueueDeclareTest extends QpidBrokerTestCase +{ + private Connection _connection; + private AMQSession<?, ?> _session; + + protected void setUp() throws Exception + { + super.setUp(); + + _connection = getConnection(); + _session = (AMQSession<?, ?>) _connection.createSession(true, Session.SESSION_TRANSACTED); + } + + public void testDeclareAndBindWhenQueueIsNotSpecifiedInDestinationUrl() throws Exception + { + AMQQueue destination = new AMQQueue(new AMQBindingURL("topic://amq.topic//?routingkey='testTopic'")); + + assertEquals("Queue name is generated in parser", AMQShortString.EMPTY_STRING, destination.getAMQQueueName()); + + _session.declareAndBind(destination, FieldTable.convertToFieldTable(Collections.<String, Object> emptyMap())); + + assertFalse("Unexpected queue name: [" + destination.getAMQQueueName() + "]", AMQShortString.EMPTY_STRING.equals(destination.getAMQQueueName())); + + sendMessage(_session, destination, 1); + + MessageConsumer consumer = _session.createConsumer(destination); + _connection.start(); + Message message = consumer.receive(1000l); + assertNotNull("Message not received", message); + _session.commit(); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java index 91f56f369b..69b529cf40 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/exchange/ReturnUnroutableMandatoryMessageTest.java @@ -30,6 +30,7 @@ import org.apache.qpid.client.AMQSession; import org.apache.qpid.client.AMQTopic; import org.apache.qpid.configuration.ClientProperties; import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.url.AMQBindingURL; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java index 95a378f1f6..6bd2b7569b 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/BrokerLoggingTest.java @@ -1000,7 +1000,7 @@ public class BrokerLoggingTest extends AbstractTestLogging } catch (IOException e) { - if (!e.getMessage().equals("Connection refused")) + if (!e.getMessage().startsWith("Connection refused")) { fail("Socket not closed on port:" + port + ":" + e.getMessage()); // Keep stack trace for diagnosis. diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java index 602bdb66b5..c9f3aca91f 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/logging/DurableQueueLoggingTest.java @@ -97,7 +97,7 @@ public class DurableQueueLoggingTest extends AbstractTestLogging String clientID = _connection.getClientID(); assertNotNull("clientID should not be null", clientID); - + validateQueueProperties(results, false, false, clientID); } @@ -256,7 +256,7 @@ public class DurableQueueLoggingTest extends AbstractTestLogging validateQueueProperties(results, true, true, null); } - + private List<String> waitForMesssage() throws IOException { // Validation @@ -267,14 +267,14 @@ public class DurableQueueLoggingTest extends AbstractTestLogging // Only 1 Queue message should hav been logged assertEquals("Result set size not as expected", 1, results.size()); - + return results; } public void validateQueueProperties(List<String> results, boolean hasPriority, boolean hasAutodelete, String clientID) { String log = getLogMessage(results, 0); - + // Message Should be a QUE-1001 validateMessageID("QUE-1001", log); @@ -290,7 +290,7 @@ public class DurableQueueLoggingTest extends AbstractTestLogging fromMessage(log).contains("Priority: " + PRIORITIES)); // Queue is AutoDelete - assertEquals("Unexpected AutoDelete status:" + fromMessage(log), hasAutodelete, + assertEquals("Unexpected AutoDelete status:" + fromMessage(log), hasAutodelete, fromMessage(log).contains("AutoDelete")); if(clientID != null) diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java index 0d4b4ba9f8..0d4b4ba9f8 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/QueueBindTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/QueueBindTest.java new file mode 100644 index 0000000000..64ba0156e6 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/QueueBindTest.java @@ -0,0 +1,130 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.queue; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import javax.jms.Connection; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.Session; + +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQQueue; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.common.AMQPFilterTypes; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.url.AMQBindingURL; + +public class QueueBindTest extends QpidBrokerTestCase +{ + private Connection _connection; + private AMQSession<?, ?> _session; + + protected void setUp() throws Exception + { + super.setUp(); + + _connection = getConnection(); + _session = (AMQSession<?, ?>) _connection.createSession(true, Session.SESSION_TRANSACTED); + } + + public void testQueueCannotBeReboundOnNonTopicExchange() throws Exception + { + runTestForNonTopicExhange(new AMQQueue(new AMQBindingURL("direct://amq.direct//" + getTestQueueName()))); + runTestForNonTopicExhange(new AMQQueue(new AMQBindingURL("fanout://amq.fanout//" + getTestQueueName()) + "?routingkey='" + + getTestQueueName() + "'")); + } + + public void testQueueCanBeReboundOnTopicExchange() throws Exception + { + AMQQueue destination = new AMQQueue(new AMQBindingURL("topic://amq.topic//" + getTestQueueName() + "?routingkey='" + + getTestQueueName() + "'")); + setTestClientSystemProperty("qpid.default_mandatory", "false"); + runTestForTopicExchange(destination); + + } + + private void runTestForTopicExchange(AMQDestination destination) throws AMQException, JMSException, Exception + { + // binding queue with empty arguments + _session.declareAndBind(destination, FieldTable.convertToFieldTable(Collections.<String, Object> emptyMap())); + + // try to re-bind queue with a selector + Map<String, Object> bindArguments = new HashMap<String, Object>(); + bindArguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue().toString(), INDEX + "=0"); + _session.bindQueue(destination.getAMQQueueName(), destination.getRoutingKey(), + FieldTable.convertToFieldTable(bindArguments), destination.getExchangeName(), destination); + + _connection.start(); + + // repeat send/receive twice to make sure that selector is working + for (int i = 0; i < 2; i++) + { + int numberOfMesssages = 2; + sendMessage(_session, destination, numberOfMesssages); + + MessageConsumer consumer = _session.createConsumer(destination); + Message m = consumer.receive(1000); + assertNotNull("Message not received", m); + assertEquals("Unexpected index", 0, m.getIntProperty(INDEX)); + _session.commit(); + + m = consumer.receive(1000); + assertNull("Message received", m); + + consumer.close(); + } + } + + private void runTestForNonTopicExhange(AMQQueue destination) throws AMQException, Exception, JMSException + { + // binding queue with empty arguments + _session.declareAndBind(destination, FieldTable.convertToFieldTable(Collections.<String, Object> emptyMap())); + + // try to re-bind queue with a selector + Map<String, Object> bindArguments = new HashMap<String, Object>(); + bindArguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue().toString(), INDEX + "=0"); + _session.bindQueue(destination.getAMQQueueName(), destination.getRoutingKey(), + FieldTable.convertToFieldTable(bindArguments), destination.getExchangeName(), destination); + + // send and receive to prove that selector is not used + int numberOfMesssages = 2; + sendMessage(_session, destination, numberOfMesssages); + + MessageConsumer consumer = _session.createConsumer(destination); + _connection.start(); + + for (int i = 0; i < numberOfMesssages; i++) + { + Message m = consumer.receive(1000l); + assertNotNull("Message [" + i + "] not received with exchange " + destination.getExchangeName(), m); + assertEquals("Unexpected index", i, m.getIntProperty(INDEX)); + _session.commit(); + } + consumer.close(); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SortedQueueTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SortedQueueTest.java index 14dee60124..844e3ecc11 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SortedQueueTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/SortedQueueTest.java @@ -336,7 +336,7 @@ public class SortedQueueTest extends QpidBrokerTestCase private Queue createQueue() throws AMQException, JMSException { final Map<String, Object> arguments = new HashMap<String, Object>(); - arguments.put(AMQQueueFactory.QPID_QUEUE_SORT_KEY, TEST_SORT_KEY); + arguments.put(QueueArgumentsConverter.QPID_QUEUE_SORT_KEY, TEST_SORT_KEY); ((AMQSession<?,?>) _producerSession).createQueue(new AMQShortString(getTestQueueName()), false, true, false, arguments); final Queue queue = new AMQQueue("amq.direct", getTestQueueName()); ((AMQSession<?,?>) _producerSession).declareAndBind((AMQDestination) queue); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java index 8b678c4eb4..f89e33ccc4 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/MessageStoreTest.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.store; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.qpid.AMQException; @@ -37,20 +38,19 @@ import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.exchange.DirectExchange; import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.exchange.TopicExchange; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.protocol.v0_8.AMQMessage; +import org.apache.qpid.server.protocol.v0_8.MessageMetaData; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQPriorityQueue; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.ConflationQueue; -import org.apache.qpid.server.queue.IncomingMessage; -import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.protocol.v0_8.IncomingMessage; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; @@ -84,22 +84,22 @@ public class MessageStoreTest extends QpidTestCase private String directExchangeName = "MST-DirectExchange"; private String topicExchangeName = "MST-TopicExchange"; - private AMQShortString durablePriorityTopicQueueName = new AMQShortString("MST-PriorityTopicQueue-Durable"); - private AMQShortString durableTopicQueueName = new AMQShortString("MST-TopicQueue-Durable"); - private AMQShortString priorityTopicQueueName = new AMQShortString("MST-PriorityTopicQueue"); - private AMQShortString topicQueueName = new AMQShortString("MST-TopicQueue"); + private String durablePriorityTopicQueueName = "MST-PriorityTopicQueue-Durable"; + private String durableTopicQueueName = "MST-TopicQueue-Durable"; + private String priorityTopicQueueName = "MST-PriorityTopicQueue"; + private String topicQueueName = "MST-TopicQueue"; - private AMQShortString durableExclusiveQueueName = new AMQShortString("MST-Queue-Durable-Exclusive"); - private AMQShortString durablePriorityQueueName = new AMQShortString("MST-PriorityQueue-Durable"); - private AMQShortString durableLastValueQueueName = new AMQShortString("MST-LastValueQueue-Durable"); - private AMQShortString durableQueueName = new AMQShortString("MST-Queue-Durable"); - private AMQShortString priorityQueueName = new AMQShortString("MST-PriorityQueue"); - private AMQShortString queueName = new AMQShortString("MST-Queue"); + private String durableExclusiveQueueName = "MST-Queue-Durable-Exclusive"; + private String durablePriorityQueueName = "MST-PriorityQueue-Durable"; + private String durableLastValueQueueName = "MST-LastValueQueue-Durable"; + private String durableQueueName = "MST-Queue-Durable"; + private String priorityQueueName = "MST-PriorityQueue"; + private String queueName = "MST-Queue"; - private AMQShortString directRouting = new AMQShortString("MST-direct"); - private AMQShortString topicRouting = new AMQShortString("MST-topic"); + private String directRouting = "MST-direct"; + private String topicRouting = "MST-topic"; - private AMQShortString queueOwner = new AMQShortString("MST"); + private String queueOwner = "MST"; private PropertiesConfiguration _config; @@ -203,7 +203,7 @@ public class MessageStoreTest extends QpidTestCase */ public void testQueueExchangeAndBindingCreation() throws Exception { - assertEquals("Should not be any existing queues", 0, getVirtualHost().getQueueRegistry().getQueues().size()); + assertEquals("Should not be any existing queues", 0, getVirtualHost().getQueues().size()); createAllQueues(); createAllTopicQueues(); @@ -241,7 +241,7 @@ public class MessageStoreTest extends QpidTestCase validateMessageOnTopics(2, true); assertEquals("Not all queues correctly registered", - 10, getVirtualHost().getQueueRegistry().getQueues().size()); + 10, getVirtualHost().getQueues().size()); } /** @@ -270,13 +270,11 @@ public class MessageStoreTest extends QpidTestCase { testMessagePersistence(); - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - assertEquals("Incorrect number of queues registered after recovery", - 6, queueRegistry.getQueues().size()); + 6, getVirtualHost().getQueues().size()); //clear the queue - queueRegistry.getQueue(durableQueueName).clearQueue(); + _virtualHost.getQueue(durableQueueName).clearQueue(); //check the messages are gone validateMessageOnQueue(durableQueueName, 0); @@ -295,7 +293,7 @@ public class MessageStoreTest extends QpidTestCase public void testQueuePersistence() throws Exception { assertEquals("Should not be any existing queues", - 0, getVirtualHost().getQueueRegistry().getQueues().size()); + 0, getVirtualHost().getQueues().size()); //create durable and non durable queues/topics createAllQueues(); @@ -304,20 +302,18 @@ public class MessageStoreTest extends QpidTestCase //reload the virtual host, prompting recovery of the queues/topics reloadVirtualHost(); - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - assertEquals("Incorrect number of queues registered after recovery", - 6, queueRegistry.getQueues().size()); + 6, getVirtualHost().getQueues().size()); //Validate the non-Durable Queues were not recovered. assertNull("Non-Durable queue still registered:" + priorityQueueName, - queueRegistry.getQueue(priorityQueueName)); + getVirtualHost().getQueue(priorityQueueName)); assertNull("Non-Durable queue still registered:" + queueName, - queueRegistry.getQueue(queueName)); + getVirtualHost().getQueue(queueName)); assertNull("Non-Durable queue still registered:" + priorityTopicQueueName, - queueRegistry.getQueue(priorityTopicQueueName)); + getVirtualHost().getQueue(priorityTopicQueueName)); assertNull("Non-Durable queue still registered:" + topicQueueName, - queueRegistry.getQueue(topicQueueName)); + getVirtualHost().getQueue(topicQueueName)); //Validate normally expected properties of Queues/Topics validateDurableQueueProperties(); @@ -337,27 +333,24 @@ public class MessageStoreTest extends QpidTestCase //Register Durable Queue createQueue(durableQueueName, false, true, false, false); - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); assertEquals("Incorrect number of queues registered before recovery", - 1, queueRegistry.getQueues().size()); + 1, getVirtualHost().getQueues().size()); reloadVirtualHost(); - queueRegistry = getVirtualHost().getQueueRegistry(); assertEquals("Incorrect number of queues registered after first recovery", - 1, queueRegistry.getQueues().size()); + 1, getVirtualHost().getQueues().size()); //test that removing the queue means it is not recovered next time - final AMQQueue queue = queueRegistry.getQueue(durableQueueName); + final AMQQueue queue = getVirtualHost().getQueue(durableQueueName); DurableConfigurationStoreHelper.removeQueue(getVirtualHost().getDurableConfigurationStore(),queue); reloadVirtualHost(); - queueRegistry = getVirtualHost().getQueueRegistry(); assertEquals("Incorrect number of queues registered after second recovery", - 0, queueRegistry.getQueues().size()); + 0, getVirtualHost().getQueues().size()); assertNull("Durable queue was not removed:" + durableQueueName, - queueRegistry.getQueue(durableQueueName)); + getVirtualHost().getQueue(durableQueueName)); } /** @@ -451,34 +444,30 @@ public class MessageStoreTest extends QpidTestCase */ public void testDurableBindingRemoval() throws Exception { - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - //create durable queue and exchange, bind them Exchange exch = createExchange(DirectExchange.TYPE, directExchangeName, true); createQueue(durableQueueName, false, true, false, false); - bindQueueToExchange(exch, directRouting, queueRegistry.getQueue(durableQueueName), false, null); + bindQueueToExchange(exch, directRouting, getVirtualHost().getQueue(durableQueueName), false); assertEquals("Incorrect number of bindings registered before recovery", - 1, queueRegistry.getQueue(durableQueueName).getBindings().size()); + 1, getVirtualHost().getQueue(durableQueueName).getBindings().size()); //verify binding is actually normally recovered reloadVirtualHost(); - queueRegistry = getVirtualHost().getQueueRegistry(); assertEquals("Incorrect number of bindings registered after first recovery", - 1, queueRegistry.getQueue(durableQueueName).getBindings().size()); + 1, getVirtualHost().getQueue(durableQueueName).getBindings().size()); exch = getVirtualHost().getExchange(directExchangeName); assertNotNull("Exchange was not recovered", exch); //remove the binding and verify result after recovery - unbindQueueFromExchange(exch, directRouting, queueRegistry.getQueue(durableQueueName), false, null); + unbindQueueFromExchange(exch, directRouting, getVirtualHost().getQueue(durableQueueName), false); reloadVirtualHost(); - queueRegistry = getVirtualHost().getQueueRegistry(); assertEquals("Incorrect number of bindings registered after second recovery", - 0, queueRegistry.getQueue(durableQueueName).getBindings().size()); + 0, getVirtualHost().getQueue(durableQueueName).getBindings().size()); } /** @@ -515,15 +504,14 @@ public class MessageStoreTest extends QpidTestCase /** Validates the Durable queues and their properties are as expected following recovery */ private void validateBindingProperties() { - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - assertEquals("Incorrect number of (durable) queues following recovery", 6, queueRegistry.getQueues().size()); + assertEquals("Incorrect number of (durable) queues following recovery", 6, getVirtualHost().getQueues().size()); - validateBindingProperties(queueRegistry.getQueue(durablePriorityQueueName).getBindings(), false); - validateBindingProperties(queueRegistry.getQueue(durablePriorityTopicQueueName).getBindings(), true); - validateBindingProperties(queueRegistry.getQueue(durableQueueName).getBindings(), false); - validateBindingProperties(queueRegistry.getQueue(durableTopicQueueName).getBindings(), true); - validateBindingProperties(queueRegistry.getQueue(durableExclusiveQueueName).getBindings(), false); + 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); } /** @@ -551,18 +539,14 @@ public class MessageStoreTest extends QpidTestCase private void setQueueExclusivity(boolean exclusive) throws AMQException { - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - - AMQQueue queue = queueRegistry.getQueue(durableExclusiveQueueName); + AMQQueue queue = getVirtualHost().getQueue(durableExclusiveQueueName); queue.setExclusive(exclusive); } private void validateQueueExclusivityProperty(boolean expected) { - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - - AMQQueue queue = queueRegistry.getQueue(durableExclusiveQueueName); + AMQQueue queue = getVirtualHost().getQueue(durableExclusiveQueueName); assertEquals("Queue exclusivity was incorrect", queue.isExclusive(), expected); } @@ -570,14 +554,12 @@ public class MessageStoreTest extends QpidTestCase private void validateDurableQueueProperties() { - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - - validateQueueProperties(queueRegistry.getQueue(durablePriorityQueueName), true, true, false, false); - validateQueueProperties(queueRegistry.getQueue(durablePriorityTopicQueueName), true, true, false, false); - validateQueueProperties(queueRegistry.getQueue(durableQueueName), false, true, false, false); - validateQueueProperties(queueRegistry.getQueue(durableTopicQueueName), false, true, false, false); - validateQueueProperties(queueRegistry.getQueue(durableExclusiveQueueName), false, true, true, false); - validateQueueProperties(queueRegistry.getQueue(durableLastValueQueueName), false, true, true, true); + 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); } private void validateQueueProperties(AMQQueue queue, boolean usePriority, boolean durable, boolean exclusive, boolean lastValueQueue) @@ -621,7 +603,7 @@ public class MessageStoreTest extends QpidTestCase } } - private void sendMessageOnExchange(Exchange exchange, AMQShortString routingKey, boolean deliveryMode) + private void sendMessageOnExchange(Exchange exchange, String routingKey, boolean deliveryMode) { //Set MessagePersistence BasicContentHeaderProperties properties = new BasicContentHeaderProperties(); @@ -725,10 +707,10 @@ public class MessageStoreTest extends QpidTestCase createQueue(topicQueueName, false, false, false, false); } - private void createQueue(AMQShortString queueName, boolean usePriority, boolean durable, boolean exclusive, boolean lastValueQueue) + private void createQueue(String queueName, boolean usePriority, boolean durable, boolean exclusive, boolean lastValueQueue) { - FieldTable queueArguments = null; + Map<String,Object> queueArguments = null; if(usePriority || lastValueQueue) { @@ -737,14 +719,12 @@ public class MessageStoreTest extends QpidTestCase if (usePriority) { - queueArguments = new FieldTable(); - queueArguments.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), DEFAULT_PRIORTY_LEVEL); + queueArguments = Collections.singletonMap(Queue.PRIORITIES, (Object) DEFAULT_PRIORTY_LEVEL); } if (lastValueQueue) { - queueArguments = new FieldTable(); - queueArguments.put(new AMQShortString(AMQQueueFactory.QPID_LAST_VALUE_QUEUE_KEY), LVQ_KEY); + queueArguments = Collections.singletonMap(Queue.LVQ_KEY, (Object) LVQ_KEY); } AMQQueue queue = null; @@ -752,25 +732,17 @@ public class MessageStoreTest extends QpidTestCase //Ideally we would be able to use the QueueDeclareHandler here. try { - queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName.asString(), durable, queueOwner.asString(), false, exclusive, - getVirtualHost(), FieldTable.convertToMap(queueArguments)); + queue = getVirtualHost().createQueue(UUIDGenerator.generateRandomUUID(), queueName, durable, queueOwner, false, exclusive, + false, queueArguments); validateQueueProperties(queue, usePriority, durable, exclusive, lastValueQueue); - if (queue.isDurable() && !queue.isAutoDelete()) - { - DurableConfigurationStoreHelper.createQueue(getVirtualHost().getDurableConfigurationStore(), - queue, - queueArguments); - } } catch (AMQException e) { fail(e.getMessage()); } - getVirtualHost().getQueueRegistry().registerQueue(queue); - } private Map<String, Exchange> createExchanges() @@ -793,7 +765,7 @@ public class MessageStoreTest extends QpidTestCase try { - exchange = getVirtualHost().createExchange(null, name, type.getName().toString(), durable, false, null); + exchange = getVirtualHost().createExchange(null, name, type.getType(), durable, false, null); } catch (AMQException e) { @@ -803,47 +775,40 @@ public class MessageStoreTest extends QpidTestCase return exchange; } - private void bindAllQueuesToExchange(Exchange exchange, AMQShortString routingKey) + private void bindAllQueuesToExchange(Exchange exchange, String routingKey) { - FieldTable queueArguments = new FieldTable(); - queueArguments.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), DEFAULT_PRIORTY_LEVEL); - - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durablePriorityQueueName), false, queueArguments); - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durableQueueName), false, null); - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(priorityQueueName), false, queueArguments); - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(queueName), false, null); - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durableExclusiveQueueName), false, null); + 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); } - private void bindAllTopicQueuesToExchange(Exchange exchange, AMQShortString routingKey) + private void bindAllTopicQueuesToExchange(Exchange exchange, String routingKey) { - FieldTable queueArguments = new FieldTable(); - queueArguments.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), DEFAULT_PRIORTY_LEVEL); - - QueueRegistry queueRegistry = getVirtualHost().getQueueRegistry(); - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durablePriorityTopicQueueName), true, queueArguments); - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(durableTopicQueueName), true, null); - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(priorityTopicQueueName), true, queueArguments); - bindQueueToExchange(exchange, routingKey, queueRegistry.getQueue(topicQueueName), true, null); + 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); } - protected void bindQueueToExchange(Exchange exchange, AMQShortString routingKey, AMQQueue queue, boolean useSelector, FieldTable queueArguments) + protected void bindQueueToExchange(Exchange exchange, + String routingKey, + AMQQueue queue, + boolean useSelector) { - FieldTable bindArguments = null; + Map<String,Object> bindArguments = new HashMap<String, Object>(); if (useSelector) { - bindArguments = new FieldTable(); - bindArguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue(), SELECTOR_VALUE ); + bindArguments.put(AMQPFilterTypes.JMS_SELECTOR.toString(), SELECTOR_VALUE ); } try { - exchange.addBinding(String.valueOf(routingKey), queue, FieldTable.convertToMap(bindArguments)); + exchange.addBinding(routingKey, queue, bindArguments); } catch (Exception e) { @@ -851,19 +816,21 @@ public class MessageStoreTest extends QpidTestCase } } - protected void unbindQueueFromExchange(Exchange exchange, AMQShortString routingKey, AMQQueue queue, boolean useSelector, FieldTable queueArguments) + protected void unbindQueueFromExchange(Exchange exchange, + String routingKey, + AMQQueue queue, + boolean useSelector) { - FieldTable bindArguments = null; + Map<String,Object> bindArguments = new HashMap<String, Object>(); if (useSelector) { - bindArguments = new FieldTable(); - bindArguments.put(AMQPFilterTypes.JMS_SELECTOR.getValue(), SELECTOR_VALUE ); + bindArguments.put(AMQPFilterTypes.JMS_SELECTOR.toString(), SELECTOR_VALUE ); } try { - exchange.removeBinding(String.valueOf(routingKey), queue, FieldTable.convertToMap(bindArguments)); + exchange.removeBinding(routingKey, queue, bindArguments); } catch (Exception e) { @@ -895,9 +862,9 @@ public class MessageStoreTest extends QpidTestCase } } - private void validateMessageOnQueue(AMQShortString queueName, long messageCount) + private void validateMessageOnQueue(String queueName, long messageCount) { - AMQQueue queue = getVirtualHost().getQueueRegistry().getQueue(queueName); + AMQQueue queue = getVirtualHost().getQueue(queueName); assertNotNull("Queue(" + queueName + ") not correctly registered:", queue); @@ -910,9 +877,9 @@ public class MessageStoreTest extends QpidTestCase Exchange _exchange; boolean _immediate; boolean _mandatory; - AMQShortString _routingKey; + String _routingKey; - TestMessagePublishInfo(Exchange exchange, boolean immediate, boolean mandatory, AMQShortString routingKey) + TestMessagePublishInfo(Exchange exchange, boolean immediate, boolean mandatory, String routingKey) { _exchange = exchange; _immediate = immediate; @@ -922,7 +889,7 @@ public class MessageStoreTest extends QpidTestCase public AMQShortString getExchange() { - return _exchange.getNameShortString(); + return new AMQShortString(_exchange.getName()); } public void setExchange(AMQShortString exchange) @@ -942,7 +909,7 @@ public class MessageStoreTest extends QpidTestCase public AMQShortString getRoutingKey() { - return _routingKey; + return new AMQShortString(_routingKey); } } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java index a1d3d1542e..e19aeb38e7 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/QuotaMessageStore.java @@ -48,9 +48,7 @@ public class } @Override - public void configureConfigStore(String name, - ConfigurationRecoveryHandler recoveryHandler, - VirtualHost virtualHost) + public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) throws Exception { Object overfullAttr = virtualHost.getAttribute(MessageStoreConstants.OVERFULL_SIZE_ATTRIBUTE); @@ -77,7 +75,7 @@ public class } @Override - public void configureMessageStore(String name, MessageStoreRecoveryHandler recoveryHandler, + public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler recoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) throws Exception { _stateManager.attainState(State.INITIALISED); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java index 50f2ed655f..e08061deea 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/store/SlowMessageStore.java @@ -40,19 +40,17 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore private HashMap<String, Long> _preDelays = new HashMap<String, Long>(); private HashMap<String, Long> _postDelays = new HashMap<String, Long>(); private long _defaultDelay = 0L; - private MessageStore _realStore = new MemoryMessageStore(); - private DurableConfigurationStore _durableConfigurationStore = (MemoryMessageStore) _realStore; + private MessageStore _realStore = new MessageStoreCreator().createMessageStore("Memory"); + private DurableConfigurationStore _durableConfigurationStore = (DurableConfigurationStore) _realStore; private static final String PRE = "pre"; private static final String POST = "post"; private String DEFAULT_DELAY = "default"; // ***** MessageStore Interface. - public void configureConfigStore(String name, - ConfigurationRecoveryHandler recoveryHandler, - VirtualHost virtualHost) throws Exception + public void configureConfigStore(VirtualHost virtualHost, ConfigurationRecoveryHandler recoveryHandler) throws Exception { - _logger.info("Starting SlowMessageStore on Virtualhost:" + name); + _logger.info("Starting SlowMessageStore on Virtualhost:" + virtualHost.getName()); Object delaysAttr = virtualHost.getAttribute("slowMessageStoreDelays"); @@ -84,7 +82,7 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore _durableConfigurationStore = (DurableConfigurationStore)o; } } - _durableConfigurationStore.configureConfigStore(name, recoveryHandler, virtualHost); + _durableConfigurationStore.configureConfigStore(virtualHost, recoveryHandler); } @@ -153,11 +151,10 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore } - public void configureMessageStore(String name, - MessageStoreRecoveryHandler messageRecoveryHandler, + public void configureMessageStore(VirtualHost virtualHost, MessageStoreRecoveryHandler messageRecoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler) throws Exception { - _realStore.configureMessageStore(name, messageRecoveryHandler, tlogRecoveryHandler); + _realStore.configureMessageStore(virtualHost, messageRecoveryHandler, tlogRecoveryHandler); } public void close() throws Exception @@ -190,6 +187,15 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore } @Override + public UUID[] removeConfiguredObjects(final UUID... objects) throws AMQStoreException + { + doPreDelay("remove"); + UUID[] removed = _durableConfigurationStore.removeConfiguredObjects(objects); + doPostDelay("remove"); + return removed; + } + + @Override public void update(UUID id, String type, Map<String, Object> attributes) throws AMQStoreException { doPreDelay("update"); @@ -197,6 +203,22 @@ public class SlowMessageStore implements MessageStore, DurableConfigurationStore doPostDelay("update"); } + @Override + public void update(ConfiguredObjectRecord... records) throws AMQStoreException + { + doPreDelay("update"); + _durableConfigurationStore.update(records); + doPostDelay("update"); + } + + @Override + public void update(boolean createIfNecessary, ConfiguredObjectRecord... records) throws AMQStoreException + { + doPreDelay("update"); + _durableConfigurationStore.update(createIfNecessary, records); + doPostDelay("update"); + } + public Transaction newTransaction() { doPreDelay("beginTran"); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ExchangeManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ExchangeManagementTest.java index cc662bddca..594239b2ee 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ExchangeManagementTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ExchangeManagementTest.java @@ -53,10 +53,10 @@ public class ExchangeManagementTest extends QpidBrokerTestCase _managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); _testQueueName = getTestName(); _managedBroker.createNewQueue(_testQueueName, null, true); - _directExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME.asString()); - _topicExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.TOPIC_EXCHANGE_NAME.asString()); - _fanoutExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.FANOUT_EXCHANGE_NAME.asString()); - _headersExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.HEADERS_EXCHANGE_NAME.asString()); + _directExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME); + _topicExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.TOPIC_EXCHANGE_NAME); + _fanoutExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.FANOUT_EXCHANGE_NAME); + _headersExchange = _jmxUtils.getManagedExchange(ExchangeDefaults.HEADERS_EXCHANGE_NAME); _connection = getConnection(); _connection.start(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java index 7a66fe6a7c..f396c79351 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ManagementLoggingTest.java @@ -249,7 +249,7 @@ public class ManagementLoggingTest extends AbstractTestLogging // Validate the keystore path is as expected assertTrue("SSL Keystore entry expected.:" + getMessageString(log), - getMessageString(log).endsWith(TestSSLConstants.BROKER_KEYSTORE)); + getMessageString(log).endsWith("systestsKeyStore")); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java index cf066e3c01..2d6943f643 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/QueueManagementTest.java @@ -28,6 +28,7 @@ import org.apache.qpid.management.common.mbeans.ManagedBroker; import org.apache.qpid.management.common.mbeans.ManagedQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.NotificationCheckTest; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.queue.SimpleAMQQueue; import org.apache.qpid.server.queue.SimpleAMQQueueTest; import org.apache.qpid.test.client.destination.AddressBasedDestinationTest; @@ -168,7 +169,7 @@ public class QueueManagementTest extends QpidBrokerTestCase public void testNewQueueWithDescription() throws Exception { String queueName = getTestQueueName(); - Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); + Map<String, Object> arguments = Collections.singletonMap(QueueArgumentsConverter.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); ((AMQSession<?, ?>)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); @@ -181,7 +182,7 @@ public class QueueManagementTest extends QpidBrokerTestCase public void testQueueDescriptionSurvivesRestart() throws Exception { String queueName = getTestQueueName(); - Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); + Map<String, Object> arguments = Collections.singletonMap(QueueArgumentsConverter.X_QPID_DESCRIPTION, (Object)TEST_QUEUE_DESCRIPTION); ((AMQSession<?, ?>)_session).createQueue(AMQShortString.valueOf(queueName), false, true, false, arguments); @@ -195,7 +196,7 @@ public class QueueManagementTest extends QpidBrokerTestCase } /** - * Tests queue creation with {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests + * Tests queue creation with {@link QueueArgumentsConverter#X_QPID_MAXIMUM_DELIVERY_COUNT} argument. Also tests * that the attribute is exposed correctly through {@link ManagedQueue#getMaximumDeliveryCount()}. */ public void testCreateQueueWithMaximumDeliveryCountSet() throws Exception @@ -204,7 +205,7 @@ public class QueueManagementTest extends QpidBrokerTestCase final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); final Integer deliveryCount = 1; - final Map<String, Object> arguments = Collections.singletonMap(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount); + final Map<String, Object> arguments = Collections.singletonMap(QueueArgumentsConverter.X_QPID_MAXIMUM_DELIVERY_COUNT, (Object)deliveryCount); managedBroker.createNewQueue(queueName, null, true, arguments); // Ensure the queue exists @@ -225,10 +226,10 @@ public class QueueManagementTest extends QpidBrokerTestCase final Long maximumQueueDepth = 300l; final Long maximumMessageAge = 400l; final Map<String, Object> arguments = new HashMap<String, Object>(); - arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_COUNT, maximumMessageCount); - arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_SIZE, maximumMessageSize); - arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_QUEUE_DEPTH, maximumQueueDepth); - arguments.put(AMQQueueFactory.X_QPID_MAXIMUM_MESSAGE_AGE, maximumMessageAge); + arguments.put(QueueArgumentsConverter.X_QPID_MAXIMUM_MESSAGE_COUNT, maximumMessageCount); + arguments.put(QueueArgumentsConverter.X_QPID_MAXIMUM_MESSAGE_SIZE, maximumMessageSize); + arguments.put(QueueArgumentsConverter.X_QPID_MAXIMUM_QUEUE_DEPTH, maximumQueueDepth); + arguments.put(QueueArgumentsConverter.X_QPID_MAXIMUM_MESSAGE_AGE, maximumMessageAge); managedBroker.createNewQueue(queueName, null, true, arguments); @@ -642,7 +643,7 @@ public class QueueManagementTest extends QpidBrokerTestCase final ManagedBroker managedBroker = _jmxUtils.getManagedBroker(VIRTUAL_HOST); final Object messageGroupKey = "test"; - final Map<String, Object> arguments = Collections.singletonMap(SimpleAMQQueue.QPID_GROUP_HEADER_KEY, messageGroupKey); + final Map<String, Object> arguments = Collections.singletonMap(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY, messageGroupKey); managedBroker.createNewQueue(queueName, null, true, arguments); final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); @@ -659,8 +660,8 @@ public class QueueManagementTest extends QpidBrokerTestCase final Object messageGroupKey = "test"; final Map<String, Object> arguments = new HashMap<String, Object>(2); - arguments.put(SimpleAMQQueue.QPID_GROUP_HEADER_KEY, messageGroupKey); - arguments.put(SimpleAMQQueue.QPID_SHARED_MSG_GROUP, SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE); + arguments.put(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY, messageGroupKey); + arguments.put(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP, SimpleAMQQueue.SHARED_MSG_GROUP_ARG_VALUE); managedBroker.createNewQueue(queueName, null, true, arguments); final ManagedQueue managedQueue = _jmxUtils.getManagedQueue(queueName); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java index 1d1c474be0..ad328eaede 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java @@ -51,7 +51,7 @@ public class Asserts assertNotNull("Virtualhost " + virtualHostName + " data are not found", virtualHost); assertAttributesPresent(virtualHost, VirtualHost.AVAILABLE_ATTRIBUTES, VirtualHost.TIME_TO_LIVE, VirtualHost.CREATED, VirtualHost.UPDATED, VirtualHost.SUPPORTED_QUEUE_TYPES, VirtualHost.STORE_PATH, - VirtualHost.CONFIG_PATH, VirtualHost.TYPE); + VirtualHost.CONFIG_PATH, VirtualHost.TYPE, VirtualHost.CONFIG_STORE_PATH, VirtualHost.CONFIG_STORE_TYPE); assertEquals("Unexpected value of attribute " + VirtualHost.NAME, virtualHostName, virtualHost.get(VirtualHost.NAME)); assertNotNull("Unexpected value of attribute " + VirtualHost.ID, virtualHost.get(VirtualHost.ID)); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java index a2f9d3189c..8f2c138869 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/LogRecordsRestTest.java @@ -39,4 +39,25 @@ public class LogRecordsRestTest extends QpidRestTestCase assertEquals("Unexpected thread", "main", record.get("thread")); assertEquals("Unexpected logger", "qpid.message.broker.ready", record.get("logger")); } + + public void testGetLogsFromGivenId() throws Exception + { + List<Map<String, Object>> logs = getRestTestHelper().getJsonAsList("/rest/logrecords"); + assertNotNull("Logs data cannot be null", logs); + assertTrue("Logs are not found", logs.size() > 0); + + Map<String, Object> lastLog = logs.get(logs.size() -1); + Object lastId = lastLog.get("id"); + + //make sure that new logs are created + getConnection(); + + List<Map<String, Object>> newLogs = getRestTestHelper().getJsonAsList("/rest/logrecords?lastLogId=" + lastId); + assertNotNull("Logs data cannot be null", newLogs); + assertTrue("Logs are not found", newLogs.size() > 0); + + Object nextId = newLogs.get(0).get("id"); + + assertEquals("Unexpected next log id", ((Number)lastId).longValue() + 1, ((Number)nextId).longValue()); + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/LogViewerTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/LogViewerTest.java new file mode 100644 index 0000000000..6166e8afc1 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/LogViewerTest.java @@ -0,0 +1,105 @@ +/* + * + * 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.systest.rest; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.apache.qpid.server.BrokerOptions; + +public class LogViewerTest extends QpidRestTestCase +{ + public static final String DEFAULT_FILE_APPENDER_NAME = "FileAppender"; + private String _expectedLogFileName; + + public void setUp() throws Exception + { + setSystemProperty("logsuffix", "-" + getTestQueueName()); + _expectedLogFileName = System.getProperty("logprefix", "") + "qpid" + System.getProperty("logsuffix", "") + ".log"; + + // use real broker log file + File brokerLogFile = new File(System.getProperty(QPID_HOME), BrokerOptions.DEFAULT_LOG_CONFIG_FILE); + setBrokerCommandLog4JFile(brokerLogFile); + + super.setUp(); + } + + public void testGetLogFiles() throws Exception + { + List<Map<String, Object>> logFiles = getRestTestHelper().getJsonAsList("/rest/logfiles"); + assertNotNull("Log files data cannot be null", logFiles); + + // 1 file appender is configured in QPID default log4j xml: + assertEquals("Unexpected number of log files", 1, logFiles.size()); + + Map<String, Object> logFileDetails = logFiles.get(0); + assertEquals("Unexpected log file name", _expectedLogFileName, logFileDetails.get("name")); + assertEquals("Unexpected log file mime type", "text/plain", logFileDetails.get("mimeType")); + assertEquals("Unexpected log file appender",DEFAULT_FILE_APPENDER_NAME, logFileDetails.get("appenderName")); + assertTrue("Unexpected log file size", ((Number)logFileDetails.get("size")).longValue()>0); + assertTrue("Unexpected log file modification time", ((Number)logFileDetails.get("lastModified")).longValue()>0); + } + + public void testDownloadExistingLogFiles() throws Exception + { + byte[] bytes = getRestTestHelper().getBytes("/rest/logfile?l=" + DEFAULT_FILE_APPENDER_NAME + "%2F" + _expectedLogFileName); + + ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(bytes)); + try + { + ZipEntry entry = zis.getNextEntry(); + assertEquals("Unexpected broker log file name", DEFAULT_FILE_APPENDER_NAME + "/" + _expectedLogFileName, entry.getName()); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] buffer = new byte[1024]; + int len; + while ((len = zis.read(buffer)) > 0) + { + baos.write(buffer, 0, len); + } + baos.close(); + assertTrue("Unexpected broker log file content", new String(baos.toByteArray()).contains("BRK-1004")); + assertNull("Unexpepected log file entry", zis.getNextEntry()); + } + finally + { + zis.close(); + } + } + + public void testDownloadNonExistingLogFiles() throws Exception + { + int responseCode = getRestTestHelper().submitRequest("/rest/logfile?l=" + DEFAULT_FILE_APPENDER_NAME + "%2F" + + _expectedLogFileName + "_" + System.currentTimeMillis(), "GET", null); + + assertEquals("Unexpected response code", 404, responseCode); + } + + public void testDownloadNonLogFiles() throws Exception + { + int responseCode = getRestTestHelper().submitRequest("/rest/logfile?l=config.json", "GET", null); + assertEquals("Unexpected response code", 400, responseCode); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java index fb6bfca1d8..d8dc7f35c0 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/MessagesRestTest.java @@ -62,7 +62,7 @@ public class MessagesRestTest extends QpidRestTestCase _session = _connection.createSession(true, Session.SESSION_TRANSACTED); String queueName = getTestQueueName(); Destination queue = _session.createQueue(queueName); - _session.createConsumer(queue); + _session.createConsumer(queue).close(); _producer = _session.createProducer(queue); _ttl = TimeUnit.DAYS.toMillis(1); @@ -318,7 +318,7 @@ public class MessagesRestTest extends QpidRestTestCase { if (even) { - assertEquals("Unexpected message attribute expirationTime", 0, message.get("expirationTime")); + assertNull("Unexpected message attribute expirationTime", message.get("expirationTime")); assertEquals("Unexpected message attribute priority", 4, message.get("priority")); assertEquals("Unexpected message attribute persistent", Boolean.TRUE, message.get("persistent")); } @@ -348,7 +348,6 @@ public class MessagesRestTest extends QpidRestTestCase assertNotNull("Unexpected message attribute mimeType", message.get("mimeType")); assertNotNull("Unexpected message attribute userId", message.get("userId")); assertNotNull("Message priority cannot be null", message.get("priority")); - assertNotNull("Message expirationTime cannot be null", message.get("expirationTime")); assertNotNull("Message persistent cannot be null", message.get("persistent")); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java new file mode 100644 index 0000000000..7f604bada7 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesProviderRestTest.java @@ -0,0 +1,190 @@ +/* + * + * 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.systest.rest; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.server.plugin.AuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.manager.PlainPasswordFileAuthenticationManagerFactory; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; + +public class PreferencesProviderRestTest extends QpidRestTestCase +{ + private Map<String, File> _preferencesProviderFiles; + private File _authenticationProviderFile; + + public void setUp() throws Exception + { + _authenticationProviderFile = TestFileUtils.createTempFile(this, ".test.prefs.txt", "test:test"); + _preferencesProviderFiles = new HashMap<String, File>(); + super.setUp(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_authenticationProviderFile != null) + { + _authenticationProviderFile.delete(); + } + for (File file : _preferencesProviderFiles.values()) + { + file.delete(); + } + } + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + Map<String, Object> anonymousAuthProviderAttributes = new HashMap<String, Object>(); + anonymousAuthProviderAttributes.put(AuthenticationManagerFactory.ATTRIBUTE_TYPE, PlainPasswordFileAuthenticationManagerFactory.PROVIDER_TYPE); + anonymousAuthProviderAttributes.put(AuthenticationProvider.NAME, TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "-2"); + anonymousAuthProviderAttributes.put(PlainPasswordFileAuthenticationManagerFactory.ATTRIBUTE_PATH, _authenticationProviderFile.getAbsolutePath()); + getBrokerConfiguration().addAuthenticationProviderConfiguration(anonymousAuthProviderAttributes); + } + + public void testCreateAndGetProvider() throws Exception + { + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList("/rest/preferencesprovider"); + assertEquals("Unexpected number of providers", 0, providerDetails.size()); + + createPreferencesProvider(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, "test1"); + createPreferencesProvider(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "-2", "test2"); + + providerDetails = getRestTestHelper().getJsonAsList("/rest/preferencesprovider"); + assertEquals("Unexpected number of providers", 2, providerDetails.size()); + + for (Map<String, Object> provider : providerDetails) + { + assertProvider(provider); + } + + Map<String, Object> provider = getRestTestHelper().getJsonAsSingletonList( + "/rest/preferencesprovider/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/test1"); + assertProvider(provider); + assertEquals("Unexpected provider name ", "test1", provider.get(PreferencesProvider.NAME)); + + Map<String, Object> provider2 = getRestTestHelper().getJsonAsSingletonList( + "/rest/preferencesprovider/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "-2/test2"); + assertProvider(provider); + assertEquals("Unexpected provider name ", "test2", provider2.get(PreferencesProvider.NAME)); + } + + public void testDeleteProvider() throws Exception + { + createPreferencesProvider(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, "test1"); + String providerUrl = "/rest/preferencesprovider/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/test1"; + Map<String, Object> provider = getRestTestHelper().getJsonAsSingletonList(providerUrl); + assertProvider(provider); + assertEquals("Unexpected provider name ", "test1", provider.get(PreferencesProvider.NAME)); + + int responseCode = getRestTestHelper().submitRequest(providerUrl, "DELETE", null); + assertEquals("Failed to delete preferences provider", 200, responseCode); + + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList(providerUrl); + assertEquals("Unexpected number of providers", 0, providerDetails.size()); + } + + public void testUpdateProvider() throws Exception + { + createPreferencesProvider(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, "test1"); + String providerUrl = "/rest/preferencesprovider/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/test1"; + Map<String, Object> provider = getRestTestHelper().getJsonAsSingletonList(providerUrl); + assertProvider(provider); + assertEquals("Unexpected provider name ", "test1", provider.get(PreferencesProvider.NAME)); + + File file = TestFileUtils.createTempFile(this, ".prefs.json", "{\"admin\":{\"something\": \"somethingValue\"}}"); + _preferencesProviderFiles.put("new-test1", file); + Map<String, Object> newAttributes = new HashMap<String, Object>(); + newAttributes.put(FileSystemPreferencesProvider.PATH, file.getAbsolutePath()); + + int responseCode = getRestTestHelper().submitRequest(providerUrl, "PUT", newAttributes); + assertEquals("Failed to update preferences provider", 200, responseCode); + + List<Map<String, Object>> providerDetails = getRestTestHelper().getJsonAsList(providerUrl); + assertEquals("Unexpected number of providers", 1, providerDetails.size()); + + provider = providerDetails.get(0); + assertProviderCommonAttributes(provider); + String name = (String) provider.get(PreferencesProvider.NAME); + assertEquals("Unexpected name", "test1", name); + assertEquals("Unexpected path for provider " + name, (String) provider.get(FileSystemPreferencesProvider.PATH), + file.getAbsolutePath()); + } + + private void assertProvider(Map<String, Object> provider) + { + assertProviderCommonAttributes(provider); + + String name = (String) provider.get(PreferencesProvider.NAME); + assertNotNull("Name cannot be null", name); + assertEquals("Unexpected path for provider " + name, (String) provider.get(FileSystemPreferencesProvider.PATH), + _preferencesProviderFiles.get(name).getAbsolutePath()); + } + + public void assertProviderCommonAttributes(Map<String, Object> provider) + { + Asserts.assertAttributesPresent(provider, PreferencesProvider.AVAILABLE_ATTRIBUTES, PreferencesProvider.CREATED, + PreferencesProvider.UPDATED, PreferencesProvider.TIME_TO_LIVE); + assertEquals("Unexpected value of provider attribute " + PreferencesProvider.STATE, State.ACTIVE.name(), + provider.get(PreferencesProvider.STATE)); + assertEquals("Unexpected value of provider attribute " + PreferencesProvider.LIFETIME_POLICY, + LifetimePolicy.PERMANENT.name(), provider.get(PreferencesProvider.LIFETIME_POLICY)); + assertEquals("Unexpected value of provider attribute " + PreferencesProvider.DURABLE, Boolean.TRUE, + provider.get(PreferencesProvider.DURABLE)); + assertEquals("Unexpected value of provider attribute " + PreferencesProvider.TYPE, + FileSystemPreferencesProvider.PROVIDER_TYPE, provider.get(PreferencesProvider.TYPE)); + } + + private void createPreferencesProvider(String authenticationProvider, String providerName) throws Exception + { + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PreferencesProvider.NAME, providerName); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.PROVIDER_TYPE); + File file = TestFileUtils.createTempFile(this, ".prefs.json", "{\"admin\":{\"language\": \"en\"}}"); + _preferencesProviderFiles.put(providerName, file); + attributes.put(FileSystemPreferencesProvider.PATH, file.getAbsolutePath()); + + int responseCode = getRestTestHelper().submitRequest( + "/rest/preferencesprovider/" + authenticationProvider + "/" + providerName, "PUT", attributes); + assertEquals("Unexpected response code", 201, responseCode); + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java new file mode 100644 index 0000000000..bf2044aa74 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java @@ -0,0 +1,95 @@ +package org.apache.qpid.systest.rest; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; + +public class PreferencesRestTest extends QpidRestTestCase +{ + private File _preferencesProviderFile; + + public void setUp() throws Exception + { + _preferencesProviderFile = TestFileUtils.createTempFile(this, ".prefs.json", + "{\"webadmin\":{\"language\": \"en\", \"saveTabs\":true}}"); + super.setUp(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_preferencesProviderFile != null) + { + _preferencesProviderFile.delete(); + } + } + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PreferencesProvider.NAME, "test"); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.PROVIDER_TYPE); + attributes.put(FileSystemPreferencesProvider.PATH, _preferencesProviderFile.getAbsolutePath()); + brokerConfiguration.addPreferencesProviderConfiguration(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, + attributes); + + } + + public void testGetPreferences() throws Exception + { + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap("/rest/preferences"); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "en", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", true, preferences.get("saveTabs")); + } + + public void testUpdatePreferences() throws Exception + { + Map<String, Object> additionalPreferences = new HashMap<String, Object>(); + additionalPreferences.put("timezone", "Europe/London"); + additionalPreferences.put("test", 1); + + int status = getRestTestHelper().submitRequest("/rest/preferences", "POST", additionalPreferences); + assertEquals("Unexpected response code", 200, status); + + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap("/rest/preferences"); + assertEquals("Unexpected number of preferences", 4, preferences.size()); + assertEquals("Unexpected language preference", "en", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", true, preferences.get("saveTabs")); + assertEquals("Unexpected timezone preference", "Europe/London", preferences.get("timezone")); + assertEquals("Unexpected test preference", 1, preferences.get("test")); + } + + public void testReplacePreferences() throws Exception + { + Map<String, Object> additionalPreferences = new HashMap<String, Object>(); + additionalPreferences.put("timezone", "Europe/London"); + additionalPreferences.put("test", 1); + + int status = getRestTestHelper().submitRequest("/rest/preferences", "PUT", additionalPreferences); + assertEquals("Unexpected response code", 200, status); + + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap("/rest/preferences"); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected timezone preference", "Europe/London", preferences.get("timezone")); + assertEquals("Unexpected test preference", 1, preferences.get("test")); + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java index c15e5d7285..7d99b30049 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java @@ -468,4 +468,11 @@ public class RestTestHelper connection.disconnect(); return responseCode; } + + public byte[] getBytes(String path) throws IOException + { + HttpURLConnection connection = openManagementConnection(path, "GET"); + connection.connect(); + return readConnectionInputStream(connection); + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java index 664b8fffa4..da72dd6f05 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/StructureRestTest.java @@ -80,8 +80,8 @@ public class StructureRestTest extends QpidRestTestCase Map<String, Object> exchange = getRestTestHelper().find("name", exchangeName, exchanges); assertNotNull("Exchange " + exchangeName + " is not found ", exchange); assertNode(exchange, exchangeName); - if (ExchangeDefaults.DIRECT_EXCHANGE_NAME.asString().equalsIgnoreCase(exchangeName) || - ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equalsIgnoreCase(exchangeName)) + if (ExchangeDefaults.DIRECT_EXCHANGE_NAME.equalsIgnoreCase(exchangeName) || + ExchangeDefaults.DEFAULT_EXCHANGE_NAME.equalsIgnoreCase(exchangeName)) { @SuppressWarnings("unchecked") List<Map<String, Object>> bindings = (List<Map<String, Object>>) exchange.get("bindings"); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java new file mode 100644 index 0000000000..7c0883ec84 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/UserPreferencesRestTest.java @@ -0,0 +1,140 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.systest.rest; + +import java.io.File; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.User; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; + +public class UserPreferencesRestTest extends QpidRestTestCase +{ + private File _preferencesProviderFile; + + public void setUp() throws Exception + { + _preferencesProviderFile = TestFileUtils.createTempFile(this, ".prefs.json", + "{\"webadmin\":{\"language\": \"en\", \"saveTabs\":true}," + + " \"admin\":{\"language\": \"fr\", \"saveTabs\":false}" + "}"); + super.setUp(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_preferencesProviderFile != null) + { + _preferencesProviderFile.delete(); + } + } + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PreferencesProvider.NAME, "test"); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.PROVIDER_TYPE); + attributes.put(FileSystemPreferencesProvider.PATH, _preferencesProviderFile.getAbsolutePath()); + brokerConfiguration.addPreferencesProviderConfiguration(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, + attributes); + + } + + public void testGetUserPreferences() throws Exception + { + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap( + "/rest/userpreferences/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/webadmin"); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "en", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", true, preferences.get("saveTabs")); + } + + public void testGetUserListForAuthenticationProvider() throws Exception + { + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList( + "/rest/userpreferences/" + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER); + assertEquals("Unexpected number of users", 2, users.size()); + String[] expectedUsers = { "webadmin", "admin" }; + for (int i = 0; i < expectedUsers.length; i++) + { + Map<String, Object> user = findUser(expectedUsers[i], users); + assertNotNull(String.format("User %s is not found", expectedUsers[i]), user); + } + } + + public void testGetUserList() throws Exception + { + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/userpreferences"); + assertEquals("Unexpected number of users", 2, users.size()); + String[] expectedUsers = { "webadmin", "admin" }; + for (int i = 0; i < expectedUsers.length; i++) + { + Map<String, Object> user = findUser(expectedUsers[i], users); + assertNotNull(String.format("User %s is not found", expectedUsers[i]), user); + } + } + + public void testDeleteUser() throws Exception + { + int status = getRestTestHelper().submitRequest( + "/rest/userpreferences?user=" + + URLEncoder.encode(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/webadmin", + "UTF-8"), "DELETE", null); + assertEquals("Unexpected status ", 200, status); + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList("/rest/userpreferences"); + assertEquals("Unexpected number of users", 1, users.size()); + Map<String, Object> user = findUser("admin", users); + assertNotNull("User admin is not found", user); + assertNull("User webadmin is found", findUser("webadmin", users)); + } + + private Map<String, Object> findUser(String userName, List<Map<String, Object>> users) + { + for (Map<String, Object> map : users) + { + if (userName.equals(map.get(User.NAME))) + { + return map; + } + } + return null; + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java index 940d6a3298..969f222316 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/VirtualHostRestTest.java @@ -37,6 +37,7 @@ import org.apache.qpid.server.model.Exchange; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueArgumentsConverter; import org.apache.qpid.server.virtualhost.StandardVirtualHostFactory; import org.apache.qpid.test.utils.TestFileUtils; import org.apache.qpid.util.FileUtils; @@ -291,7 +292,7 @@ public class VirtualHostRestTest extends QpidRestTestCase Asserts.assertQueue(queueName , "lvq", lvqQueue); assertEquals("Unexpected value of queue attribute " + Queue.DURABLE, Boolean.TRUE, lvqQueue.get(Queue.DURABLE)); - assertEquals("Unexpected lvq key attribute", AMQQueueFactory.QPID_LVQ_KEY, lvqQueue.get(Queue.LVQ_KEY)); + assertEquals("Unexpected lvq key attribute", AMQQueueFactory.QPID_DEFAULT_LVQ_KEY, lvqQueue.get(Queue.LVQ_KEY)); } public void testPutCreateSortedQueueWithoutKey() throws Exception @@ -460,7 +461,7 @@ public class VirtualHostRestTest extends QpidRestTestCase String queueName = getTestQueueName(); Map<String, Object> attributes = new HashMap<String, Object>(); - attributes.put(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); + attributes.put(Queue.CREATE_DLQ_ON_CREATION, true); //verify the starting state Map<String, Object> hostDetails = getRestTestHelper().getJsonAsSingletonList("/rest/virtualhost/test"); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java new file mode 100644 index 0000000000..5a2ebe3e8e --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/LogViewerACLTest.java @@ -0,0 +1,100 @@ +/* + * + * 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.systest.rest.acl; + +import java.io.IOException; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.management.plugin.HttpManagement; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; +import org.apache.qpid.systest.rest.QpidRestTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +public class LogViewerACLTest extends QpidRestTestCase +{ + private static final String ALLOWED_USER = "user1"; + private static final String DENIED_USER = "user2"; + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER); + + AbstractACLTestCase.writeACLFileUtil(this, null, + "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", + "ACL ALLOW-LOG " + ALLOWED_USER + " ACCESS_LOGS BROKER", + "ACL DENY-LOG " + DENIED_USER + " ACCESS_LOGS BROKER", + "ACL DENY-LOG ALL ALL"); + + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, + HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, true); + } + + public void testGetLogRecordsAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + int responseCode = getRestTestHelper().submitRequest("/rest/logrecords", "GET", null); + assertEquals("Access to log records should be allowed", 200, responseCode); + } + + public void testGetLogRecordsDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + int responseCode = getRestTestHelper().submitRequest("/rest/logrecords", "GET", null); + assertEquals("Access to log records should be denied", 403, responseCode); + } + + public void testGetLogFilesAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + int responseCode = getRestTestHelper().submitRequest("/rest/logfiles", "GET", null); + assertEquals("Access to log files should be allowed", 200, responseCode); + } + + public void testGetLogFilesDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + int responseCode = getRestTestHelper().submitRequest("/rest/logfiles", "GET", null); + assertEquals("Access to log files should be denied", 403, responseCode); + } + + public void testDownloadLogFileAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + int responseCode = getRestTestHelper().submitRequest("/rest/logfile?l=appender%2fqpid.log", "GET", null); + assertEquals("Access to log files should be allowed", 404, responseCode); + } + + public void testDownloadLogFileDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + int responseCode = getRestTestHelper().submitRequest("/rest/logfile?l=appender%2fqpid.log", "GET", null); + assertEquals("Access to log files should be denied", 403, responseCode); + } + +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java new file mode 100644 index 0000000000..6ed84ac95a --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/acl/UserPreferencesRestACLTest.java @@ -0,0 +1,197 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.apache.qpid.systest.rest.acl; + +import java.io.File; +import java.io.IOException; +import java.net.URLEncoder; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.management.plugin.HttpManagement; +import org.apache.qpid.server.model.PreferencesProvider; +import org.apache.qpid.server.model.adapter.FileSystemPreferencesProvider; +import org.apache.qpid.server.security.acl.AbstractACLTestCase; +import org.apache.qpid.systest.rest.QpidRestTestCase; +import org.apache.qpid.test.utils.TestBrokerConfiguration; +import org.apache.qpid.test.utils.TestFileUtils; + +public class UserPreferencesRestACLTest extends QpidRestTestCase +{ + + private static final String REST_USER_PREFERENCES_BASE_URL = "/rest/userpreferences"; + private static final String ALLOWED_USER = "webadmin"; + private static final String DENIED_USER = "admin"; + private static final String TEST_USER_PREFERENCES_GET_URL = REST_USER_PREFERENCES_BASE_URL + "/" + + TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/%s"; + + private File _preferencesProviderFile; + + public void setUp() throws Exception + { + _preferencesProviderFile = TestFileUtils.createTempFile(this, ".prefs.json", + "{\"webadmin\":{\"language\": \"en\", \"saveTabs\":true}," + " \"admin\":{\"language\": \"fr\", \"saveTabs\":false}" + + "}"); + super.setUp(); + } + + public void tearDown() throws Exception + { + try + { + super.tearDown(); + } + finally + { + if (_preferencesProviderFile != null) + { + _preferencesProviderFile.delete(); + } + } + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + getRestTestHelper().configureTemporaryPasswordFile(this, ALLOWED_USER, DENIED_USER); + + AbstractACLTestCase.writeACLFileUtil(this, null, "ACL ALLOW-LOG ALL ACCESS MANAGEMENT", "ACL ALLOW-LOG " + ALLOWED_USER + + " UPDATE USER", "ACL DENY-LOG " + DENIED_USER + " UPDATE USER", "ACL DENY-LOG ALL ALL"); + + TestBrokerConfiguration brokerConfiguration = getBrokerConfiguration(); + brokerConfiguration.setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_MANAGEMENT, + HttpManagement.HTTP_BASIC_AUTHENTICATION_ENABLED, true); + + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(PreferencesProvider.NAME, "test"); + attributes.put(PreferencesProvider.TYPE, FileSystemPreferencesProvider.PROVIDER_TYPE); + attributes.put(FileSystemPreferencesProvider.PATH, _preferencesProviderFile.getAbsolutePath()); + brokerConfiguration + .addPreferencesProviderConfiguration(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, attributes); + } + + public void testListUsersWithPreferencesAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + List<Map<String, Object>> users = getRestTestHelper().getJsonAsList(REST_USER_PREFERENCES_BASE_URL); + assertUsers(users); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + users = getRestTestHelper().getJsonAsList(REST_USER_PREFERENCES_BASE_URL); + assertUsers(users); + } + + public void testViewOtherUserPreferencesAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String userPreferencesUrl = String.format(TEST_USER_PREFERENCES_GET_URL, DENIED_USER); + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "fr", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", false, preferences.get("saveTabs")); + } + + public void testViewOtherUserPreferencesDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + int responseCode = getRestTestHelper().submitRequest( + "/rest/userpreferences?user=" + + URLEncoder.encode(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + ALLOWED_USER, "UTF-8"), + "DELETE", null); + assertEquals("Preferences deletion should be denied", 403, responseCode); + } + + public void testDeleteOtherUserPreferencesAllowed() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String userPreferencesUrl = String.format(TEST_USER_PREFERENCES_GET_URL, DENIED_USER); + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "fr", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", false, preferences.get("saveTabs")); + + int responseCode = getRestTestHelper().submitRequest( + "/rest/userpreferences?user=" + + URLEncoder.encode(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + DENIED_USER, "UTF-8"), + "DELETE", null); + assertEquals("Preferences deletion should be allowed", 200, responseCode); + + preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences after deletion", 0, preferences.size()); + } + + public void testDeleteOtherUserPreferencesDenied() throws Exception + { + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + String userPreferencesUrl = String.format(TEST_USER_PREFERENCES_GET_URL, ALLOWED_USER); + Map<String, Object> preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences", 2, preferences.size()); + assertEquals("Unexpected language preference", "en", preferences.get("language")); + assertEquals("Unexpected saveTabs preference", true, preferences.get("saveTabs")); + + getRestTestHelper().setUsernameAndPassword(DENIED_USER, DENIED_USER); + + int responseCode = getRestTestHelper().submitRequest( + "/rest/userpreferences?user=" + + URLEncoder.encode(TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER + "/" + ALLOWED_USER, "UTF-8"), + "DELETE", null); + assertEquals("Preferences deletion should be denied", 403, responseCode); + + getRestTestHelper().setUsernameAndPassword(ALLOWED_USER, ALLOWED_USER); + + preferences = getRestTestHelper().getJsonAsMap(userPreferencesUrl); + assertEquals("Unexpected number of preferences after deletion", 2, preferences.size()); + } + + + private void assertUsers(List<Map<String, Object>> users) + { + assertEquals("Unexpected number of users", 2, users.size()); + Map<String, Object> webadmin = findUser("webadmin", users); + assertEquals("Unexpected name", "webadmin", webadmin.get("name")); + assertEquals("Unexpected authentication provider", TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, webadmin.get("authenticationProvider")); + Map<String, Object> admin = findUser("admin", users); + assertEquals("Unexpected name", "admin", admin.get("name")); + assertEquals("Unexpected authentication provider", TestBrokerConfiguration.ENTRY_NAME_AUTHENTICATION_PROVIDER, admin.get("authenticationProvider")); + } + + private Map<String, Object> findUser(String name, List<Map<String, Object>> users) + { + for (Map<String, Object> user : users) + { + if (name.equals(user.get("name"))) + { + return user; + } + } + return null; + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java index 67a2988ad1..bd826259bc 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/destination/AddressBasedDestinationTest.java @@ -200,8 +200,8 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "{" + "exclusive: true," + "arguments: {" + - "'qpid.max_size': 1000," + - "'qpid.max_count': 100" + + "'qpid.alert_size': 1000," + + "'qpid.alert_count': 100" + "}" + "}, " + "x-bindings: [{exchange : 'amq.direct', key : test}, " + @@ -401,7 +401,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase "x-declare: " + "{ " + "auto-delete: true," + - "arguments: {'qpid.max_count': 100}" + + "arguments: {'qpid.alert_count': 100}" + "}, " + "x-bindings: [{exchange : 'amq.direct', key : test}, " + "{exchange : 'amq.topic', key : 'a.#'}," + @@ -485,7 +485,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase { Hashtable<String,String> map = new Hashtable<String,String>(); map.put("destination.myQueue1", "ADDR:my-queue/hello; {create: always, node: " + - "{x-declare: {auto-delete: true, arguments : {'qpid.max_size': 1000}}}}"); + "{x-declare: {auto-delete: true, arguments : {'qpid.alert_size': 1000}}}}"); map.put("destination.myQueue2", "ADDR:my-queue2; { create: receiver }"); @@ -603,7 +603,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase String addr = "ADDR:amq.direct/x512; {" + "link : {name : 'MY.RESP.QUEUE', " + "x-declare : { auto-delete: true, exclusive: true, " + - "arguments : {'qpid.max_size': 1000, 'qpid.policy_type': ring} } } }"; + "arguments : {'qpid.alert_size': 1000, 'qpid.policy_type': ring} } } }"; queue = ssn.createQueue(addr); cons = ssn.createConsumer(queue); @@ -1403,7 +1403,7 @@ public class AddressBasedDestinationTest extends QpidBrokerTestCase Session ssn = _connection.createSession(false,Session.AUTO_ACKNOWLEDGE); String xDeclareArgs = "x-declare: { exclusive: false, auto-delete: false," + "alternate-exchange: 'amq.fanout'," + - "arguments: {'qpid.max_size': 1000,'qpid.max_count': 100}" + + "arguments: {'qpid.alert_size': 1000,'qpid.alert_count': 100}" + "}"; String addr = "ADDR:amq.topic/test; {link: {name:my-queue, durable:true," + xDeclareArgs + "}}"; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java index 3c26cbb3c9..2d8847ea33 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java @@ -19,6 +19,7 @@ */ package org.apache.qpid.test.unit.basic; +import org.apache.qpid.framing.AMQShortString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -190,7 +191,7 @@ public class MultipleConnectionTest extends QpidBrokerTestCase String broker = _connectionString; int messages = 10; - AMQTopic topic = new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, "amq.topic"); + AMQTopic topic = new AMQTopic(AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_NAME), "amq.topic"); Receiver[] receivers = new Receiver[] { new Receiver(broker, topic, 2), new Receiver(broker, topic, 14) }; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java index 67b2e099bf..963a23b0ba 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ConnectionTest.java @@ -88,16 +88,16 @@ public class ConnectionTest extends QpidBrokerTestCase AMQSession sess = (AMQSession) conn.createSession(false, Session.AUTO_ACKNOWLEDGE); sess.declareExchange(new AMQShortString("test.direct"), - ExchangeDefaults.DIRECT_EXCHANGE_CLASS, false); + AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS), false); sess.declareExchange(new AMQShortString("tmp.direct"), - ExchangeDefaults.DIRECT_EXCHANGE_CLASS, false); + AMQShortString.valueOf(ExchangeDefaults.DIRECT_EXCHANGE_CLASS), false); sess.declareExchange(new AMQShortString("tmp.topic"), - ExchangeDefaults.TOPIC_EXCHANGE_CLASS, false); + AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS), false); sess.declareExchange(new AMQShortString("test.topic"), - ExchangeDefaults.TOPIC_EXCHANGE_CLASS, false); + AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_CLASS), false); QueueSession queueSession = conn.createQueueSession(false, Session.AUTO_ACKNOWLEDGE); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java new file mode 100644 index 0000000000..141de1e5a8 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/connection/ExceptionListenerTest.java @@ -0,0 +1,244 @@ +/* + * 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.test.unit.client.connection; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +import javax.jms.Connection; +import javax.jms.ExceptionListener; +import javax.jms.IllegalStateException; +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.MessageConsumer; +import javax.jms.MessageListener; +import javax.jms.Queue; +import javax.jms.Session; + +import org.apache.qpid.AMQConnectionClosedException; +import org.apache.qpid.client.AMQNoRouteException; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.test.utils.QpidBrokerTestCase; +import org.apache.qpid.transport.ConnectionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ExceptionListenerTest extends QpidBrokerTestCase +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionListenerTest.class); + + private volatile Throwable _lastExceptionListenerException = null; + + public void testExceptionListenerHearsBrokerShutdown() throws Exception + { + final CountDownLatch exceptionReceivedLatch = new CountDownLatch(1); + final AtomicInteger exceptionCounter = new AtomicInteger(0); + final ExceptionListener listener = new ExceptionListener() + { + public void onException(JMSException exception) + { + exceptionCounter.incrementAndGet(); + _lastExceptionListenerException = exception; + exceptionReceivedLatch.countDown(); + } + }; + + Connection connection = getConnection(); + connection.setExceptionListener(listener); + + stopBroker(); + + exceptionReceivedLatch.await(10, TimeUnit.SECONDS); + + assertEquals("Unexpected number of exceptions received", 1, exceptionCounter.intValue()); + LOGGER.debug("exception was", _lastExceptionListenerException); + assertNotNull("Exception should have cause", _lastExceptionListenerException.getCause()); + Class<? extends Exception> expectedExceptionClass = isBroker010() ? ConnectionException.class : AMQConnectionClosedException.class; + assertEquals(expectedExceptionClass, _lastExceptionListenerException.getCause().getClass()); + } + + /** + * It is reasonable for an application to perform Connection#close within the exception + * listener. This test verifies that close is allowed, and proceeds without generating + * further exceptions. + */ + public void testExceptionListenerClosesConnection_IsAllowed() throws Exception + { + final CountDownLatch exceptionReceivedLatch = new CountDownLatch(1); + final Connection connection = getConnection(); + final ExceptionListener listener = new ExceptionListener() + { + public void onException(JMSException exception) + { + try + { + connection.close(); + // PASS + } + catch (Throwable t) + { + _lastExceptionListenerException = t; + } + finally + { + exceptionReceivedLatch.countDown(); + } + } + }; + connection.setExceptionListener(listener); + + + stopBroker(); + + boolean exceptionReceived = exceptionReceivedLatch.await(10, TimeUnit.SECONDS); + assertTrue("Exception listener did not hear exception within timeout", exceptionReceived); + assertNull("Connection#close() should not have thrown exception", _lastExceptionListenerException); + } + + /** + * Spring's SingleConnectionFactory installs an ExceptionListener that calls stop() + * and ignores any IllegalStateException that result. This test serves to test this + * scenario. + */ + public void testExceptionListenerStopsConnection_ThrowsIllegalStateException() throws Exception + { + final CountDownLatch exceptionReceivedLatch = new CountDownLatch(1); + final Connection connection = getConnection(); + final ExceptionListener listener = new ExceptionListener() + { + public void onException(JMSException exception) + { + try + { + connection.stop(); + fail("Exception not thrown"); + } + catch (IllegalStateException ise) + { + // PASS + } + catch (Throwable t) + { + _lastExceptionListenerException = t; + } + finally + { + exceptionReceivedLatch.countDown(); + } + } + }; + connection.setExceptionListener(listener); + + stopBroker(); + + boolean exceptionReceived = exceptionReceivedLatch.await(10, TimeUnit.SECONDS); + assertTrue("Exception listener did not hear exception within timeout", exceptionReceived); + assertNull("Connection#stop() should not have thrown unexpected exception", _lastExceptionListenerException); + } + + /** + * This test reproduces a deadlock that was the subject of a support call. A Spring based + * application was using SingleConnectionFactory. It installed an ExceptionListener that + * stops and closes the connection in response to any exception. On receipt of a message + * the application would create a new session then send a response message (within onMessage). + * It appears that a misconfiguration in the application meant that some of these messages + * were bounced (no-route). Bounces are treated like connection exceptions and are passed + * back to the application via the ExceptionListener. The deadlock occurred between the + * ExceptionListener's call to stop() and the MessageListener's attempt to create a new + * session. + */ + public void testExceptionListenerConnectionStopDeadlock() throws Exception + { + Queue messageQueue = getTestQueue(); + + Map<String, String> options = new HashMap<String, String>(); + options.put(ConnectionURL.OPTIONS_CLOSE_WHEN_NO_ROUTE, Boolean.toString(false)); + + final Connection connection = getConnectionWithOptions(options); + + Session session = connection.createSession(true, Session.SESSION_TRANSACTED); + session.createConsumer(messageQueue).close(); // Create queue by side-effect + + // Put 10 messages onto messageQueue + sendMessage(session, messageQueue, 10); + + // Install an exception listener that stops/closes the connection on receipt of 2nd AMQNoRouteException. + // (Triggering on the 2nd (rather than 1st) seems to increase the probability that the test ends in deadlock, + // at least on my machine). + final CountDownLatch exceptionReceivedLatch = new CountDownLatch(2); + final ExceptionListener listener = new ExceptionListener() + { + public void onException(JMSException exception) + { + try + { + assertNotNull("JMS Exception must have cause", exception.getCause() ); + assertEquals("JMS Exception is of wrong type", AMQNoRouteException.class, exception.getCause().getClass()); + exceptionReceivedLatch.countDown(); + if (exceptionReceivedLatch.getCount() == 0) + { + connection.stop(); // ** Deadlock + connection.close(); + } + } + catch (Throwable t) + { + _lastExceptionListenerException = t; + } + } + }; + connection.setExceptionListener(listener); + + // Create a message listener that receives from testQueue and tries to forward them to unknown queue (thus + // provoking AMQNoRouteException exceptions to be delivered to the ExceptionListener). + final Queue unknownQueue = session.createQueue(getTestQueueName() + "_unknown");; + MessageListener redirectingMessageListener = new MessageListener() + { + @Override + public void onMessage(Message msg) + { + try + { + Session mlSession = connection.createSession(true, Session.SESSION_TRANSACTED); // ** Deadlock + mlSession.createProducer(unknownQueue).send(msg); + mlSession.commit(); + } + catch (JMSException je) + { + // Connection is closed by the listener, so exceptions here are expected. + LOGGER.debug("Expected exception - message listener got exception", je); + } + } + }; + + MessageConsumer consumer = session.createConsumer(messageQueue); + consumer.setMessageListener(redirectingMessageListener); + connection.start(); + + // Await the 2nd exception + boolean exceptionReceived = exceptionReceivedLatch.await(10, TimeUnit.SECONDS); + assertTrue("Exception listener did not hear exception within timeout", exceptionReceived); + assertNull("Exception listener should not have had experienced exception", _lastExceptionListenerException); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java index cf05cc0304..38a7b90ebd 100755 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/QpidBrokerTestCase.java @@ -57,6 +57,7 @@ import org.apache.qpid.client.AMQConnectionURL; import org.apache.qpid.client.AMQQueue; import org.apache.qpid.client.AMQTopic; import org.apache.qpid.exchange.ExchangeDefaults; +import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.server.Broker; @@ -66,7 +67,6 @@ import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.plugin.MessageStoreFactory; import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.store.MessageStoreConstants; import org.apache.qpid.server.store.MessageStoreCreator; import org.apache.qpid.url.URLSyntaxException; @@ -250,20 +250,12 @@ public class QpidBrokerTestCase extends QpidTestCase private void initialiseLogConfigFile() { - try - { - _logger.info("About to initialise log config file from system property: " + LOG4J_CONFIG_FILE_PATH); + _logger.info("About to initialise log config file from system property: " + LOG4J_CONFIG_FILE_PATH); - URI uri = new URI("file", LOG4J_CONFIG_FILE_PATH, null); - _logConfigFile = new File(uri); - if(!_logConfigFile.exists()) - { - throw new RuntimeException("Log config file " + _logConfigFile.getAbsolutePath() + " does not exist"); - } - } - catch (URISyntaxException e) + _logConfigFile = new File(LOG4J_CONFIG_FILE_PATH); + if(!_logConfigFile.exists()) { - throw new RuntimeException("Couldn't create URI from log4.configuration: " + LOG4J_CONFIG_FILE_PATH, e); + throw new RuntimeException("Log config file " + _logConfigFile.getAbsolutePath() + " does not exist"); } } @@ -634,17 +626,17 @@ public class QpidBrokerTestCase extends QpidTestCase public String getTestConfigFile(int port) { - return _output + "/" + getTestQueueName() + "-" + port + "-config"; + return _output + File.separator + getTestQueueName() + "-" + port + "-config"; } public String getTestVirtualhostsFile(int port) { - return _output + "/" + getTestQueueName() + "-" + port + "-virtualhosts.xml"; + return _output + File.separator + getTestQueueName() + "-" + port + "-virtualhosts.xml"; } private String relativeToQpidHome(String file) { - return file.replace(System.getProperty(QPID_HOME,"QPID_HOME") + "/",""); + return file.replace(System.getProperty(QPID_HOME,"QPID_HOME") + File.separator,""); } protected String getPathRelativeToWorkingDirectory(String file) @@ -1199,7 +1191,7 @@ public class QpidBrokerTestCase extends QpidTestCase */ public Topic getTestTopic() { - return new AMQTopic(ExchangeDefaults.TOPIC_EXCHANGE_NAME, getTestQueueName()); + return new AMQTopic(AMQShortString.valueOf(ExchangeDefaults.TOPIC_EXCHANGE_NAME), getTestQueueName()); } @Override @@ -1433,10 +1425,10 @@ public class QpidBrokerTestCase extends QpidTestCase public String getTestProfileMessageStoreType() { final String storeClass = getTestProfileMessageStoreClassName(); - if (storeClass == null) + /* if (storeClass == null) { - return MemoryMessageStore.TYPE; - } + return "Memory"; + }*/ return supportedStoresClassToTypeMapping.get(storeClass); } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java index 9cb1e6dfcb..9e893bb7bb 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/utils/TestBrokerConfiguration.java @@ -38,6 +38,7 @@ import org.apache.qpid.server.model.GroupProvider; import org.apache.qpid.server.model.KeyStore; import org.apache.qpid.server.model.Plugin; import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.PreferencesProvider; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.model.VirtualHost; @@ -295,4 +296,16 @@ public class TestBrokerConfiguration _saved = saved; } + public void addPreferencesProviderConfiguration(String authenticationProvider, Map<String, Object> attributes) + { + ConfigurationEntry pp = new ConfigurationEntry(UUIDGenerator.generateRandomUUID(), + PreferencesProvider.class.getSimpleName(), attributes, Collections.<UUID> emptySet(), _store); + ConfigurationEntry ap = findObjectByName(authenticationProvider); + Set<UUID> children = new HashSet<UUID>(); + children.addAll(ap.getChildrenIds()); + children.add(pp.getId()); + ConfigurationEntry newAp = new ConfigurationEntry(ap.getId(), ap.getType(), ap.getAttributes(), children, _store); + _store.save(newAp, pp); + } + } diff --git a/qpid/java/test-profiles/CPPExcludes b/qpid/java/test-profiles/CPPExcludes index 72523e2d4b..8ea592daf9 100755 --- a/qpid/java/test-profiles/CPPExcludes +++ b/qpid/java/test-profiles/CPPExcludes @@ -62,6 +62,7 @@ org.apache.qpid.test.client.timeouts.SyncWaitTimeoutDelayTest#* // c++ broker doesn't support message bouncing org.apache.qpid.server.exchange.ReturnUnroutableMandatoryMessageTest#* org.apache.qpid.test.unit.topic.DurableSubscriptionTest#testUnsubscribeWhenUsingSelectorMakesTopicUnreachable +org.apache.qpid.test.unit.client.connection.ExceptionListenerTest#testExceptionListenerConnectionStopDeadlock // c++ broker expires messages on delivery or when the queue cleaner thread runs. org.apache.qpid.server.queue.TimeToLiveTest#testActiveTTL @@ -187,3 +188,5 @@ org.apache.qpid.client.ssl.SSLTest#testCreateSSLandTCPonSamePort // QPID-2796 : Java 0-10 client only sends heartbeats in response to heartbeats from the server, not timeout based org.apache.qpid.client.HeartbeatTest#testReadOnlyConnectionHeartbeats +// Exclude java broker specific behavior allowing queue re-bind to topic exchanges on 0.8/0-10 paths +org.apache.qpid.server.queue.QueueBindTest#testQueueCanBeReboundOnTopicExchange diff --git a/qpid/java/test-profiles/Java010Excludes b/qpid/java/test-profiles/Java010Excludes index b0489fca38..02c2db1134 100755 --- a/qpid/java/test-profiles/Java010Excludes +++ b/qpid/java/test-profiles/Java010Excludes @@ -20,6 +20,7 @@ // Those tests are testing 0.8..-0-9-1 specific semantics org.apache.qpid.test.client.ImmediateAndMandatoryPublishingTest#* org.apache.qpid.test.client.CloseOnNoRouteForMandatoryMessageTest#* +org.apache.qpid.test.unit.client.connection.ExceptionListenerTest#testExceptionListenerConnectionStopDeadlock org.apache.qpid.systest.rest.BrokerRestTest#testSetCloseOnNoRoute //this test checks explicitly for 0-8 flow control semantics @@ -68,3 +69,6 @@ org.apache.qpid.client.AsynchMessageListenerTest#testImmediatePrefetchWithMessag // QPID-2796 : Java 0-10 client only sends heartbeats in response to heartbeats from the server, not timeout based org.apache.qpid.client.HeartbeatTest#testReadOnlyConnectionHeartbeats + +// Java 0-10 client does not support re-binding the queue to the same exchange +org.apache.qpid.server.queue.QueueBindTest#testQueueCanBeReboundOnTopicExchange diff --git a/qpid/java/test-profiles/testprofile.defaults b/qpid/java/test-profiles/testprofile.defaults index 033da12a97..ccd31a5d1e 100644 --- a/qpid/java/test-profiles/testprofile.defaults +++ b/qpid/java/test-profiles/testprofile.defaults @@ -17,7 +17,7 @@ # under the License. # java.naming.factory.initial=org.apache.qpid.jndi.PropertiesFileInitialContextFactory -java.naming.provider.url=${test.profiles}/test-provider.properties +java.naming.provider.url=${test.profiles}${file.separator}test-provider.properties broker.ready=Listening on TCP broker.config=build/etc/config-systests.json @@ -36,7 +36,7 @@ root.logging.level=warn # System property log4j.configuration is used by log4j. # QpidBrokerTestCase uses log4j.configuration.file to construct a java.io.File, eg for log configuration of spawned brokers. -log4j.configuration.file=${test.profiles}/log4j-test.xml +log4j.configuration.file=${test.profiles}${file.separator}log4j-test.xml log4j.configuration=file:///${log4j.configuration.file} log4j.debug=false @@ -63,6 +63,6 @@ exclude.modules=none profile.clustered=false broker.config-store-type=json -broker.virtualhosts-config="${QPID_HOME}/etc/virtualhosts-systests.xml" +broker.virtualhosts-config="${QPID_HOME}${file.separator}etc${file.separator}virtualhosts-systests.xml" |
