summaryrefslogtreecommitdiff
path: root/qpid/java/broker-core
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/java/broker-core')
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java1
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java24
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java7
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java3
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java6
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java30
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java19
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java102
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java3
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java10
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java1
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java9
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java3
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java10
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java2
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java11
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/JmxPort.java12
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueArgumentsConverter.java8
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java120
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java58
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java15
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java9
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java102
-rw-r--r--qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java190
-rw-r--r--qpid/java/broker-core/src/main/resources/initial-config.json5
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java72
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java10
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategoryImpl.java19
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java9
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java2
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverterTest.java142
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java99
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java6
-rw-r--r--qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java14
36 files changed, 981 insertions, 156 deletions
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java
index a6fae97aaa..9b3f290723 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/BrokerOptions.java
@@ -85,7 +85,6 @@ public class BrokerOptions
Map<String,Object> attributes = new HashMap<String, Object>();
attributes.put("storePath", getConfigurationStoreLocation());
- attributes.put("storeTye", getConfigurationStoreType());
attributes.put(ConfiguredObject.CONTEXT, getConfigProperties());
return attributes;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
index 8eb0b4feb0..a910eea657 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/binding/BindingImpl.java
@@ -36,6 +36,7 @@ import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.messages.BindingMessages;
import org.apache.qpid.server.logging.subjects.BindingLogSubject;
import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.Binding;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.Queue;
@@ -66,12 +67,31 @@ public class BindingImpl
public BindingImpl(Map<String, Object> attributes, AMQQueue queue, ExchangeImpl exchange)
{
- super(parentsMap(queue,exchange),enhanceWithDurable(attributes,queue,exchange));
+ super(parentsMap(queue,exchange),stripEmptyArguments(enhanceWithDurable(attributes, queue, exchange)));
_bindingKey = getName();
_queue = queue;
_exchange = exchange;
}
+ private static Map<String, Object> stripEmptyArguments(final Map<String, Object> attributes)
+ {
+ Map<String,Object> returnVal;
+ if(attributes != null
+ && attributes.containsKey(Binding.ARGUMENTS)
+ && (attributes.get(Binding.ARGUMENTS) instanceof Map)
+ && ((Map)(attributes.get(Binding.ARGUMENTS))).isEmpty())
+ {
+ returnVal = new HashMap<>(attributes);
+ returnVal.remove(Binding.ARGUMENTS);
+ }
+ else
+ {
+ returnVal = attributes;
+ }
+
+ return returnVal;
+ }
+
@Override
protected void onOpen()
{
@@ -113,7 +133,7 @@ public class BindingImpl
{
if(!attributes.containsKey(DURABLE))
{
- attributes = new HashMap<String, Object>(attributes);
+ attributes = new HashMap(attributes);
attributes.put(DURABLE, queue.isDurable() && exchange.isDurable());
}
return attributes;
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index 4472669f4a..af1de8b099 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -111,6 +112,12 @@ public abstract class AbstractExchange<T extends AbstractExchange<T>>
public AbstractExchange(Map<String, Object> attributes, VirtualHostImpl vhost)
{
super(parentsMap(vhost), attributes);
+ Set<String> providedAttributeNames = new HashSet<>(attributes.keySet());
+ providedAttributeNames.removeAll(getAttributeNames());
+ if(!providedAttributeNames.isEmpty())
+ {
+ throw new IllegalArgumentException("Unknown attributes provided: " + providedAttributeNames);
+ }
_virtualHost = vhost;
// check ACL
try
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
index 67bbc26f74..a5c74cb286 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
@@ -123,7 +123,6 @@ public class HeadersExchange extends AbstractExchange<HeadersExchange>
{
String bindingKey = binding.getBindingKey();
AMQQueue queue = binding.getAMQQueue();
- Map<String,Object> args = binding.getArguments();
assert queue != null;
assert bindingKey != null;
@@ -143,7 +142,7 @@ public class HeadersExchange extends AbstractExchange<HeadersExchange>
if(_logger.isDebugEnabled())
{
_logger.debug("Exchange " + getName() + ": Binding " + queue.getName() +
- " with binding key '" +bindingKey + "' and args: " + args);
+ " with binding key '" +bindingKey + "' and args: " + binding.getArguments());
}
_bindingHeaderMatchers.add(new HeadersBinding(binding));
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
index 18930d8817..31de8118dd 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
@@ -469,7 +469,6 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
{
if(_dynamicState.compareAndSet(DynamicState.UNINIT, DynamicState.OPENED))
{
- registerWithParents();
final AuthenticatedPrincipal currentUser = SecurityManager.getCurrentUser();
if(currentUser != null)
{
@@ -487,6 +486,9 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
doResolution(true);
doValidation(true);
+
+ registerWithParents();
+
doCreation(true);
doOpening(true);
doAttainState();
@@ -1100,7 +1102,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im
@Override
public Map<String, Object> run()
{
- Map<String,Object> attributes = new HashMap<String, Object>();
+ Map<String,Object> attributes = new LinkedHashMap<String, Object>();
Map<String,Object> actualAttributes = getActualAttributes();
for(ConfiguredObjectAttribute<?,?> attr : _attributeTypes.values())
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java
index b7b56db15c..15e804e6f5 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java
@@ -89,7 +89,15 @@ abstract class AttributeValueConverter<T>
}
else if(value instanceof String)
{
- return Long.valueOf(AbstractConfiguredObject.interpolate(object, (String) value));
+ String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
+ try
+ {
+ return Long.valueOf(interpolated);
+ }
+ catch(NumberFormatException e)
+ {
+ throw new IllegalArgumentException("Cannot convert string '" + interpolated + "'",e);
+ }
}
else if(value == null)
{
@@ -117,7 +125,15 @@ abstract class AttributeValueConverter<T>
}
else if(value instanceof String)
{
- return Integer.valueOf(AbstractConfiguredObject.interpolate(object, (String) value));
+ String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
+ try
+ {
+ return Integer.valueOf(interpolated);
+ }
+ catch(NumberFormatException e)
+ {
+ throw new IllegalArgumentException("Cannot convert string '" + interpolated + "'",e);
+ }
}
else if(value == null)
{
@@ -145,7 +161,15 @@ abstract class AttributeValueConverter<T>
}
else if(value instanceof String)
{
- return Short.valueOf(AbstractConfiguredObject.interpolate(object, (String) value));
+ String interpolated = AbstractConfiguredObject.interpolate(object, (String) value);
+ try
+ {
+ return Short.valueOf(interpolated);
+ }
+ catch(NumberFormatException e)
+ {
+ throw new IllegalArgumentException("Cannot convert string '" + interpolated + "'",e);
+ }
}
else if(value == null)
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
index 011aaeee23..78da1227d5 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
@@ -47,8 +47,6 @@ public interface Broker<X extends Broker<X>> extends ConfiguredObject<X>, EventL
String DEFAULT_VIRTUAL_HOST = "defaultVirtualHost";
String STATISTICS_REPORTING_PERIOD = "statisticsReportingPeriod";
String STATISTICS_REPORTING_RESET_ENABLED = "statisticsReportingResetEnabled";
- String STORE_TYPE = "storeType";
- String STORE_VERSION = "storeVersion";
String STORE_PATH = "storePath";
String MODEL_VERSION = "modelVersion";
String CONFIDENTIAL_CONFIGURATION_ENCRYPTION_PROVIDER = "confidentialConfigurationEncryptionProvider";
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java
index 6f6ef7f6e1..1d1c736cd3 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java
@@ -21,11 +21,10 @@
package org.apache.qpid.server.model;
import java.lang.reflect.Method;
+import java.lang.reflect.Type;
public abstract class ConfiguredObjectAttribute<C extends ConfiguredObject, T> extends ConfiguredObjectAttributeOrStatistic<C,T>
{
-
-
ConfiguredObjectAttribute(Class<C> clazz,
final Method getter)
{
@@ -48,6 +47,20 @@ public abstract class ConfiguredObjectAttribute<C extends ConfiguredObject, T> e
public T convert(final Object value, C object)
{
- return getConverter().convert(value, object);
+ final AttributeValueConverter<T> converter = getConverter();
+ try
+ {
+ return converter.convert(value, object);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ Type returnType = getGetter().getGenericReturnType();
+ String simpleName = returnType instanceof Class ? ((Class) returnType).getSimpleName() : returnType.toString();
+
+ throw new IllegalArgumentException("Cannot convert '" + value
+ + "' into a " + simpleName
+ + " for attribute " + getName()
+ + " (" + iae.getMessage() + ")", iae);
+ }
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
index 3201ff16f1..e377d31baf 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
@@ -24,6 +24,7 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.AbstractCollection;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -33,6 +34,7 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
+import java.util.TreeMap;
import java.util.TreeSet;
import org.apache.log4j.Logger;
@@ -45,16 +47,106 @@ public class ConfiguredObjectTypeRegistry
{
private static final Logger LOGGER = Logger.getLogger(ConfiguredObjectTypeRegistry.class);
- private static final Comparator<ConfiguredObjectAttributeOrStatistic<?,?>> NAME_COMPARATOR = new Comparator<ConfiguredObjectAttributeOrStatistic<?, ?>>()
+ private static Map<String,Integer> STANDARD_FIRST_FIELDS_ORDER = new HashMap<>();
+ static
+ {
+ int i = 0;
+ for(String name : Arrays.asList(ConfiguredObject.ID,
+ ConfiguredObject.NAME,
+ ConfiguredObject.DESCRIPTION,
+ ConfiguredObject.TYPE,
+ ConfiguredObject.DESIRED_STATE,
+ ConfiguredObject.STATE,
+ ConfiguredObject.DURABLE,
+ ConfiguredObject.LIFETIME_POLICY,
+ ConfiguredObject.CONTEXT))
+ {
+ STANDARD_FIRST_FIELDS_ORDER.put(name, i++);
+ }
+
+ }
+
+ private static Map<String,Integer> STANDARD_LAST_FIELDS_ORDER = new HashMap<>();
+ static
+ {
+ int i = 0;
+ for(String name : Arrays.asList(ConfiguredObject.LAST_UPDATED_BY,
+ ConfiguredObject.LAST_UPDATED_TIME,
+ ConfiguredObject.CREATED_BY,
+ ConfiguredObject.CREATED_TIME))
+ {
+ STANDARD_LAST_FIELDS_ORDER.put(name, i++);
+ }
+
+ }
+
+
+ private static final Comparator<ConfiguredObjectAttributeOrStatistic<?,?>> OBJECT_NAME_COMPARATOR = new Comparator<ConfiguredObjectAttributeOrStatistic<?, ?>>()
{
@Override
public int compare(final ConfiguredObjectAttributeOrStatistic<?, ?> left,
final ConfiguredObjectAttributeOrStatistic<?, ?> right)
{
- return left.getName().compareTo(right.getName());
+ String leftName = left.getName();
+ String rightName = right.getName();
+ return compareAttributeNames(leftName, rightName);
}
};
+ private static final Comparator<String> NAME_COMPARATOR = new Comparator<String>()
+ {
+ @Override
+ public int compare(final String left, final String right)
+ {
+ return compareAttributeNames(left, right);
+ }
+ };
+
+ private static int compareAttributeNames(final String leftName, final String rightName)
+ {
+ int result;
+ if(leftName.equals(rightName))
+ {
+ result = 0;
+ }
+ else if(STANDARD_FIRST_FIELDS_ORDER.containsKey(leftName))
+ {
+ if(STANDARD_FIRST_FIELDS_ORDER.containsKey(rightName))
+ {
+ result = STANDARD_FIRST_FIELDS_ORDER.get(leftName) - STANDARD_FIRST_FIELDS_ORDER.get(rightName);
+ }
+ else
+ {
+ result = -1;
+ }
+ }
+ else if(STANDARD_FIRST_FIELDS_ORDER.containsKey(rightName))
+ {
+ result = 1;
+ }
+ else if(STANDARD_LAST_FIELDS_ORDER.containsKey(rightName))
+ {
+ if(STANDARD_LAST_FIELDS_ORDER.containsKey(leftName))
+ {
+ result = STANDARD_LAST_FIELDS_ORDER.get(leftName) - STANDARD_LAST_FIELDS_ORDER.get(rightName);
+ }
+ else
+ {
+ result = -1;
+ }
+ }
+ else if(STANDARD_LAST_FIELDS_ORDER.containsKey(leftName))
+ {
+ result = 1;
+ }
+ else
+ {
+ result = leftName.compareTo(rightName);
+ }
+
+ return result;
+ }
+
private final Map<Class<? extends ConfiguredObject>, Collection<ConfiguredObjectAttribute<?,?>>> _allAttributes =
Collections.synchronizedMap(new HashMap<Class<? extends ConfiguredObject>, Collection<ConfiguredObjectAttribute<?, ?>>>());
@@ -373,8 +465,8 @@ public class ConfiguredObjectTypeRegistry
process((Class<? extends ConfiguredObject>) superclass);
}
- final SortedSet<ConfiguredObjectAttribute<?, ?>> attributeSet = new TreeSet<>(NAME_COMPARATOR);
- final SortedSet<ConfiguredObjectStatistic<?, ?>> statisticSet = new TreeSet<>(NAME_COMPARATOR);
+ final SortedSet<ConfiguredObjectAttribute<?, ?>> attributeSet = new TreeSet<>(OBJECT_NAME_COMPARATOR);
+ final SortedSet<ConfiguredObjectStatistic<?, ?>> statisticSet = new TreeSet<>(OBJECT_NAME_COMPARATOR);
_allAttributes.put(clazz, attributeSet);
_allStatistics.put(clazz, statisticSet);
@@ -480,7 +572,7 @@ public class ConfiguredObjectTypeRegistry
private <X extends ConfiguredObject> void processAttributesTypesAndFields(final Class<X> clazz)
{
- Map<String,ConfiguredObjectAttribute<?,?>> attrMap = new HashMap<String, ConfiguredObjectAttribute<?, ?>>();
+ Map<String,ConfiguredObjectAttribute<?,?>> attrMap = new TreeMap<>(NAME_COMPARATOR);
Map<String,AutomatedField> fieldMap = new HashMap<String, AutomatedField>();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java
index 9f671b47a8..6f5bd2b405 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Model.java
@@ -98,7 +98,7 @@ public abstract class Model
return null;
}
- private Class<? extends ConfiguredObject> getAncestorClassWithGivenDescendant(
+ public Class<? extends ConfiguredObject> getAncestorClassWithGivenDescendant(
final Class<? extends ConfiguredObject> category,
final Class<? extends ConfiguredObject> descendantClass)
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
index eca3b0c7b1..6937d31b3a 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Port.java
@@ -45,9 +45,6 @@ public interface Port<X extends Port<X>> extends ConfiguredObject<X>
// Attributes
- @ManagedAttribute(defaultValue = "*")
- String getBindingAddress();
-
@ManagedAttribute( mandatory = true )
int getPort();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java
index f4d9df6eff..ce1022c2d9 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHostNode.java
@@ -27,6 +27,16 @@ import org.apache.qpid.server.store.DurableConfigurationStore;
@ManagedObject(category=true, managesChildren=false)
public interface VirtualHostNode<X extends VirtualHostNode<X>> extends ConfiguredObject<X>
{
+ String VIRTUALHOST_INITIAL_CONFIGURATION = "virtualHostInitialConfiguration";
+
+ String VIRTUALHOST_BLUEPRINT_CONTEXT_VAR = "virtualhostBlueprint";
+
+ @ManagedContextDefault(name = VIRTUALHOST_BLUEPRINT_CONTEXT_VAR)
+ String DEFAULT_INITIAL_CONFIGURATION = "{}";
+
+ @ManagedAttribute( defaultValue = "${" + VIRTUALHOST_BLUEPRINT_CONTEXT_VAR + "}")
+ String getVirtualHostInitialConfiguration();
+
VirtualHost<?,?,?> getVirtualHost();
DurableConfigurationStore getConfigurationStore();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java
index 50f98c7f03..cc1f557df1 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java
@@ -52,6 +52,7 @@ public class VirtualHostAliasAdapter extends AbstractConfiguredObject<VirtualHos
final Map<String, Object> attributes = new HashMap<String, Object>();
attributes.put(ID, UUID.randomUUID());
attributes.put(NAME, virtualHost.getName());
+ attributes.put(DURABLE, false);
return attributes;
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
index 61790441f9..d1abded988 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AbstractPort.java
@@ -61,9 +61,6 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo
private int _port;
@ManagedAttributeField
- private String _bindingAddress;
-
- @ManagedAttributeField
private KeyStore<?> _keyStore;
@ManagedAttributeField
@@ -172,12 +169,6 @@ abstract public class AbstractPort<X extends AbstractPort<X>> extends AbstractCo
}
@Override
- public String getBindingAddress()
- {
- return _bindingAddress;
- }
-
- @Override
public int getPort()
{
return _port;
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java
index b50a289b22..5c74beb5b7 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPort.java
@@ -48,6 +48,9 @@ public interface AmqpPort<X extends AmqpPort<X>> extends Port<X>
@ManagedContextDefault(name = DEFAULT_AMQP_PROTOCOLS)
String INSTALLED_PROTOCOLS = AmqpPortImpl.getInstalledProtocolsAsString();
+ @ManagedAttribute(defaultValue = "*")
+ String getBindingAddress();
+
@ManagedAttribute( defaultValue = AmqpPort.DEFAULT_AMQP_TCP_NO_DELAY )
boolean isTcpNoDelay();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
index 2c958b00d0..9a0ea3548e 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/AmqpPortImpl.java
@@ -71,6 +71,9 @@ public class AmqpPortImpl extends AbstractPortWithAuthProvider<AmqpPortImpl> imp
@ManagedAttributeField
private int _receiveBufferSize;
+ @ManagedAttributeField
+ private String _bindingAddress;
+
private final Broker<?> _broker;
private AcceptingTransport _transport;
@@ -81,6 +84,13 @@ public class AmqpPortImpl extends AbstractPortWithAuthProvider<AmqpPortImpl> imp
_broker = broker;
}
+
+ @Override
+ public String getBindingAddress()
+ {
+ return _bindingAddress;
+ }
+
@Override
public boolean isTcpNoDelay()
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java
index 51d31cb8ab..d8c87fb123 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPort.java
@@ -36,6 +36,8 @@ public interface HttpPort<X extends HttpPort<X>> extends Port<X>
String DEFAULT_AMQP_NEED_CLIENT_AUTH = "false";
String DEFAULT_AMQP_WANT_CLIENT_AUTH = "false";
+ @ManagedAttribute(defaultValue = "*")
+ String getBindingAddress();
@ManagedAttribute( defaultValue = DEFAULT_AMQP_NEED_CLIENT_AUTH )
boolean getNeedClientAuth();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
index 33abee9bde..80e79a68ca 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/HttpPortImpl.java
@@ -25,6 +25,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.qpid.server.model.Broker;
+import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.ManagedObjectFactoryConstructor;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.model.State;
@@ -33,6 +34,9 @@ public class HttpPortImpl extends AbstractPortWithAuthProvider<HttpPortImpl> imp
{
private PortManager _portManager;
+ @ManagedAttributeField
+ private String _bindingAddress;
+
@ManagedObjectFactoryConstructor
public HttpPortImpl(final Map<String, Object> attributes,
final Broker<?> broker)
@@ -45,6 +49,13 @@ public class HttpPortImpl extends AbstractPortWithAuthProvider<HttpPortImpl> imp
_portManager = manager;
}
+
+ @Override
+ public String getBindingAddress()
+ {
+ return _bindingAddress;
+ }
+
@Override
protected State onActivate()
{
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/JmxPort.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/JmxPort.java
index 981d81a342..fdfe6f1d5d 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/JmxPort.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/port/JmxPort.java
@@ -32,21 +32,9 @@ import org.apache.qpid.server.model.Transport;
@ManagedObject( category = false, type = "JMX")
public interface JmxPort<X extends JmxPort<X>> extends Port<X>
{
-
- String DEFAULT_AMQP_NEED_CLIENT_AUTH = "false";
- String DEFAULT_AMQP_WANT_CLIENT_AUTH = "false";
-
-
- @ManagedAttribute( defaultValue = DEFAULT_AMQP_NEED_CLIENT_AUTH )
- boolean getNeedClientAuth();
-
- @ManagedAttribute( defaultValue = DEFAULT_AMQP_WANT_CLIENT_AUTH )
- boolean getWantClientAuth();
-
@ManagedAttribute( mandatory = true )
AuthenticationProvider getAuthenticationProvider();
-
@ManagedAttribute( defaultValue = "TCP",
validValues = {"[ \"TCP\" ]", "[ \"SSL\" ]"})
Set<Transport> getTransports();
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueArgumentsConverter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueArgumentsConverter.java
index 37e82b0771..49732e8345 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueArgumentsConverter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/QueueArgumentsConverter.java
@@ -23,6 +23,8 @@ package org.apache.qpid.server.queue;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
+
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.virtualhost.AbstractVirtualHost;
@@ -87,6 +89,8 @@ public class QueueArgumentsConverter
ATTRIBUTE_MAPPINGS.put(X_QPID_PRIORITIES, PriorityQueue.PRIORITIES);
ATTRIBUTE_MAPPINGS.put(X_QPID_DESCRIPTION, Queue.DESCRIPTION);
+ ATTRIBUTE_MAPPINGS.put(Queue.ALTERNATE_EXCHANGE, Queue.ALTERNATE_EXCHANGE);
+
ATTRIBUTE_MAPPINGS.put(X_QPID_DLQ_ENABLED, AbstractVirtualHost.CREATE_DLQ_ON_CREATION);
ATTRIBUTE_MAPPINGS.put(QPID_GROUP_HEADER_KEY, Queue.MESSAGE_GROUP_KEY);
@@ -147,6 +151,10 @@ public class QueueArgumentsConverter
{
value = ((Enum) value).name();
}
+ else if(value instanceof ConfiguredObject)
+ {
+ value = ((ConfiguredObject)value).getName();
+ }
wireArguments.put(entry.getKey(), value);
}
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java
index cc284a33f4..5f1c0b4b7f 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverter.java
@@ -22,8 +22,11 @@ package org.apache.qpid.server.store;
import java.io.IOException;
import java.io.Reader;
+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.UUID;
@@ -37,6 +40,11 @@ public class ConfiguredObjectRecordConverter
{
private final Model _model;
+ private static interface NameToIdResolver
+ {
+ public boolean resolve(Map<UUID, ConfiguredObjectRecord> objectsById);
+ }
+
public ConfiguredObjectRecordConverter(final Model model)
{
_model = model;
@@ -52,16 +60,32 @@ public class ConfiguredObjectRecordConverter
Map data = objectMapper.readValue(reader, Map.class);
if(!data.isEmpty())
{
- loadChild(rootClass, data, parent.getCategoryClass(), parent.getId(), objectsById);
+ Collection<NameToIdResolver> unresolved =
+ loadChild(rootClass, data, parent.getCategoryClass(), parent.getId(), objectsById);
+
+ Iterator<NameToIdResolver> iterator = unresolved.iterator();
+ while(iterator.hasNext())
+ {
+ if(iterator.next().resolve(objectsById))
+ {
+ iterator.remove();
+ }
+ }
+
+ if(!unresolved.isEmpty())
+ {
+ throw new IllegalArgumentException("Initial configuration has unresolved references");
+ }
}
return objectsById.values();
}
- private void loadChild(final Class<? extends ConfiguredObject> clazz,
- final Map<String, Object> data,
- final Class<? extends ConfiguredObject> parentClass,
- final UUID parentId, final Map<UUID, ConfiguredObjectRecord> records)
+ private Collection<NameToIdResolver> loadChild(final Class<? extends ConfiguredObject> clazz,
+ final Map<String, Object> data,
+ final Class<? extends ConfiguredObject> parentClass,
+ final UUID parentId,
+ final Map<UUID, ConfiguredObjectRecord> records)
{
String idStr = (String) data.remove("id");
@@ -70,6 +94,7 @@ public class ConfiguredObjectRecordConverter
Map<String,UUID> parentMap = new HashMap<>();
Collection<Class<? extends ConfiguredObject>> childClasses = _model.getChildTypes(clazz);
+ List<NameToIdResolver> requiringResolution = new ArrayList<>();
for(Class<? extends ConfiguredObject> childClass : childClasses)
{
final String childType = childClass.getSimpleName();
@@ -83,13 +108,14 @@ public class ConfiguredObjectRecordConverter
{
if(child instanceof Map)
{
- loadChild(childClass, (Map)child, clazz, id, records);
+ requiringResolution.addAll(loadChild(childClass, (Map) child, clazz, id, records));
}
}
}
}
}
+
if(parentId != null)
{
parentMap.put(parentClass.getSimpleName(),parentId);
@@ -107,7 +133,15 @@ public class ConfiguredObjectRecordConverter
}
catch(IllegalArgumentException e)
{
- // TODO
+ final String ancestorClassName =
+ _model.getAncestorClassWithGivenDescendant(clazz, otherParent).getSimpleName();
+ final String parentName = (String) otherParentId;
+ final String parentType = otherParent.getSimpleName();
+
+ requiringResolution.add(new AncestorFindingResolver(id,
+ parentType,
+ parentName,
+ ancestorClassName));
}
}
}
@@ -117,7 +151,79 @@ public class ConfiguredObjectRecordConverter
records.put(id, new ConfiguredObjectRecordImpl(id, type, data, parentMap));
+ return requiringResolution;
}
+ private static class AncestorFindingResolver implements NameToIdResolver
+ {
+ private final String _parentType;
+ private final String _parentName;
+ private final String _commonAncestorType;
+ private final UUID _id;
+
+ public AncestorFindingResolver(final UUID id,
+ final String parentType,
+ final String parentName,
+ final String commonAncestorType)
+ {
+ _id = id;
+ _parentType = parentType;
+ _parentName = parentName;
+ _commonAncestorType = commonAncestorType;
+ }
+
+ @Override
+ public boolean resolve(final Map<UUID, ConfiguredObjectRecord> objectsById)
+ {
+
+ ConfiguredObjectRecord record = objectsById.get(_id);
+ Collection<ConfiguredObjectRecord> recordsWithMatchingName = new ArrayList<>();
+ for(ConfiguredObjectRecord possibleParentRecord : objectsById.values())
+ {
+ if(possibleParentRecord.getType().equals(_parentType)
+ && _parentName.equals(possibleParentRecord.getAttributes().get(ConfiguredObject.NAME)))
+ {
+ recordsWithMatchingName.add(possibleParentRecord);
+ }
+ }
+ for(ConfiguredObjectRecord candidate : recordsWithMatchingName)
+ {
+ UUID candidateAncestor = findAncestor(candidate, _commonAncestorType, objectsById);
+ UUID recordAncestor = findAncestor(record, _commonAncestorType, objectsById);
+ if(recordAncestor.equals(candidateAncestor))
+ {
+ HashMap<String, UUID> parents = new HashMap<>(record.getParents());
+ parents.put(_parentType, candidate.getId());
+ objectsById.put(_id, new ConfiguredObjectRecordImpl(_id, record.getType(), record.getAttributes(), parents));
+
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private UUID findAncestor(final ConfiguredObjectRecord record,
+ final String commonAncestorType,
+ final Map<UUID, ConfiguredObjectRecord> objectsById)
+ {
+ UUID id = record.getParents().get(commonAncestorType);
+ if(id == null)
+ {
+ for(UUID parentId : record.getParents().values())
+ {
+ ConfiguredObjectRecord parent = objectsById.get(parentId);
+ if(parent != null)
+ {
+ id = findAncestor(parent, commonAncestorType, objectsById);
+ }
+ if(id != null)
+ {
+ break;
+ }
+ }
+ }
+ return id;
+ }
+ }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
index 78d2b6507a..1f5665a0a5 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
@@ -31,6 +31,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
@@ -57,6 +58,28 @@ public class JsonFileConfigStore implements DurableConfigurationStore
{
private static final Logger _logger = Logger.getLogger(JsonFileConfigStore.class);
+ private static final Comparator<Class<? extends ConfiguredObject>> CATEGORY_CLASS_COMPARATOR =
+ new Comparator<Class<? extends ConfiguredObject>>()
+ {
+ @Override
+ public int compare(final Class<? extends ConfiguredObject> left,
+ final Class<? extends ConfiguredObject> right)
+ {
+ return left.getSimpleName().compareTo(right.getSimpleName());
+ }
+ };
+ private static final Comparator<ConfiguredObjectRecord> CONFIGURED_OBJECT_RECORD_COMPARATOR =
+ new Comparator<ConfiguredObjectRecord>()
+ {
+ @Override
+ public int compare(final ConfiguredObjectRecord left, final ConfiguredObjectRecord right)
+ {
+ String leftName = (String) left.getAttributes().get(ConfiguredObject.NAME);
+ String rightName = (String) right.getAttributes().get(ConfiguredObject.NAME);
+ return leftName.compareTo(rightName);
+ }
+ };
+
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();
@@ -313,6 +336,14 @@ public class JsonFileConfigStore implements DurableConfigurationStore
{
throw new StoreException("Cannot create object of unknown type " + record.getType());
}
+ else if(record.getAttributes() == null || !(record.getAttributes().get(ConfiguredObject.NAME) instanceof String))
+ {
+ throw new StoreException("The record " + record.getId()
+ + " of type " + record.getType()
+ + " does not have an attribute '"
+ + ConfiguredObject.NAME
+ + "' of type String");
+ }
else
{
record = new ConfiguredObjectRecordImpl(record);
@@ -385,8 +416,6 @@ public class JsonFileConfigStore implements DurableConfigurationStore
{
ConfiguredObjectRecord record = _objectsById.get(id);
Map<String,Object> map = new LinkedHashMap<String, Object>();
- map.put("id", id);
- map.putAll(record.getAttributes());
Collection<Class<? extends ConfiguredObject>> parentTypes = _parent.getModel().getParentTypes(type);
if(parentTypes.size() > 1)
@@ -403,9 +432,14 @@ public class JsonFileConfigStore implements DurableConfigurationStore
}
}
- Collection<Class<? extends ConfiguredObject>> childClasses =
+ map.put("id", id);
+ map.putAll(record.getAttributes());
+
+ List<Class<? extends ConfiguredObject>> childClasses =
new ArrayList<Class<? extends ConfiguredObject>>(_parent.getModel().getChildTypes(type));
+ Collections.sort(childClasses, CATEGORY_CLASS_COMPARATOR);
+
for(Class<? extends ConfiguredObject> childClass : childClasses)
{
// only add if this is the "first" parent
@@ -416,6 +450,7 @@ public class JsonFileConfigStore implements DurableConfigurationStore
if(childIds != null)
{
List<Map<String,Object>> entities = new ArrayList<Map<String, Object>>();
+ List<ConfiguredObjectRecord> sortedChildren = new ArrayList<>();
for(UUID childId : childIds)
{
ConfiguredObjectRecord childRecord = _objectsById.get(childId);
@@ -424,9 +459,17 @@ public class JsonFileConfigStore implements DurableConfigurationStore
String parentId = parent.toString();
if(id.toString().equals(parentId))
{
- entities.add(build(childClass,childId));
+ sortedChildren.add(childRecord);
}
}
+
+ Collections.sort(sortedChildren, CONFIGURED_OBJECT_RECORD_COMPARATOR);
+
+ for(ConfiguredObjectRecord childRecord : sortedChildren)
+ {
+ entities.add(build(childClass, childRecord.getId()));
+ }
+
if(!entities.isEmpty())
{
map.put(attrName,entities);
@@ -475,6 +518,13 @@ public class JsonFileConfigStore implements DurableConfigurationStore
final UUID id = record.getId();
final String type = record.getType();
+ if(record.getAttributes() == null || !(record.getAttributes().get(ConfiguredObject.NAME) instanceof String))
+ {
+ throw new StoreException("The record " + id + " of type " + type + " does not have an attribute '"
+ + ConfiguredObject.NAME
+ + "' of type String");
+ }
+
if(_objectsById.containsKey(id))
{
final ConfiguredObjectRecord existingRecord = _objectsById.get(id);
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
index 66975e1189..2e6c437e95 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/NullMessageStore.java
@@ -29,6 +29,8 @@ import org.apache.qpid.server.store.handler.MessageInstanceHandler;
public abstract class NullMessageStore implements MessageStore, DurableConfigurationStore, MessageStoreProvider
{
+ private ConfiguredObjectRecord[] _initialRecords;
+
@Override
public MessageStore getMessageStore()
{
@@ -40,6 +42,7 @@ public abstract class NullMessageStore implements MessageStore, DurableConfigura
final boolean overwrite,
final ConfiguredObjectRecord... initialRecords)
{
+ _initialRecords = initialRecords;
}
@Override
@@ -121,6 +124,18 @@ public abstract class NullMessageStore implements MessageStore, DurableConfigura
@Override
public void visitConfiguredObjectRecords(ConfiguredObjectRecordHandler handler) throws StoreException
{
+ handler.begin();
+ if(_initialRecords != null)
+ {
+ for(ConfiguredObjectRecord record : _initialRecords)
+ {
+ if(!handler.handle(record))
+ {
+ break;
+ }
+ }
+ }
+ handler.end();
}
@Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java
index fb0ab4f696..770991bd3d 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java
@@ -136,13 +136,4 @@ public class Handler extends URLStreamHandler
return new ByteArrayInputStream(_content);
}
}
-
- public static void main(String[] args) throws IOException
- {
- register();
- URL url = new URL("data:image/gif;base64,R0lGODdhMAAwAPAAAAAAAP///ywAAAAAMAAwAAAC8IyPqcvt3wCcDkiLc7C0qwyGHhSWpjQu5yqmCYsapyuvUUlvONmOZtfzgFzByTB10QgxOR0TqBQejhRNzOfkVJ+5YiUqrXF5Y5lKh/DeuNcP5yLWGsEbtLiOSpa/TPg7JpJHxyendzWTBfX0cxOnKPjgBzi4diinWGdkF8kjdfnycQZXZeYGejmJlZeGl9i2icVqaNVailT6F5iJ90m6mvuTS4OK05M0vDk0Q4XUtwvKOzrcd3iq9uisF81M1OIcR7lEewwcLp7tuNNkM3uNna3F2JQFo97Vriy/Xl4/f1cf5VWzXyym7PHhhx4dbgYKAAA7");
- InputStream is = url.openStream();
- url = new URL("data:,A%20brief%20note");
- is = url.openStream();
- }
}
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
index b4374af0f0..ce97502124 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNode.java
@@ -20,24 +20,27 @@
*/
package org.apache.qpid.server.virtualhostnode;
+import java.io.IOException;
import java.security.PrivilegedAction;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.Map;
import javax.security.auth.Subject;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
import org.apache.qpid.server.model.Broker;
-import org.apache.qpid.server.model.BrokerModel;
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.RemoteReplicationNode;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.server.security.SecurityManager;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
import org.apache.qpid.server.store.VirtualHostStoreUpgraderAndRecoverer;
public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandardVirtualHostNode<X>> extends AbstractVirtualHostNode<X>
@@ -71,7 +74,20 @@ public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandard
LOGGER.debug("Activating virtualhost node " + this);
}
- getConfigurationStore().openConfigurationStore(this, false);
+ try
+ {
+ ConfiguredObjectRecord[] initialRecords = getInitialRecords();
+ getConfigurationStore().openConfigurationStore(this, false, initialRecords);
+ if(initialRecords != null && initialRecords.length > 0)
+ {
+ setAttribute(VIRTUALHOST_INITIAL_CONFIGURATION, getVirtualHostInitialConfiguration(), "{}");
+ }
+ }
+ catch (IOException e)
+ {
+ throw new IllegalConfigurationException("Could not process initial configuration", e);
+ }
+
getConfigurationStore().upgradeStoreStructure();
getEventLogger().message(getConfigurationStoreLogSubject(), ConfigStoreMessages.CREATED());
@@ -87,47 +103,7 @@ public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandard
VirtualHost<?,?,?> host = getVirtualHost();
- if (host == null)
- {
-
- boolean hasBlueprint = getContextKeys(false).contains(VIRTUALHOST_BLUEPRINT_CONTEXT_VAR);
- boolean blueprintUtilised = getContext().containsKey(VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR)
- && Boolean.parseBoolean(String.valueOf(getContext().get(VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR)));
-
- if (hasBlueprint && !blueprintUtilised)
- {
- Map<String, Object> virtualhostBlueprint = getContextValue(Map.class, VIRTUALHOST_BLUEPRINT_CONTEXT_VAR);
-
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Using virtualhost blueprint " + virtualhostBlueprint);
- }
-
- Map<String, Object> virtualhostAttributes = new HashMap<>();
- virtualhostAttributes.put(VirtualHost.MODEL_VERSION, BrokerModel.MODEL_VERSION);
- virtualhostAttributes.put(VirtualHost.NAME, getName());
- virtualhostAttributes.putAll(virtualhostBlueprint);
-
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Creating new virtualhost named " + virtualhostAttributes.get(VirtualHost.NAME));
- }
-
- host = createChild(VirtualHost.class, virtualhostAttributes);
-
- if (LOGGER.isDebugEnabled())
- {
- LOGGER.debug("Created new virtualhost: " + host);
- }
-
- // Update the context with the utilised flag
- Map<String, String> actualContext = (Map<String, String>) getActualAttributes().get(CONTEXT);
- Map<String, String> context = new HashMap<>(actualContext);
- context.put(VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR, Boolean.TRUE.toString());
- setAttribute(CONTEXT, getContext(), context);
- }
- }
- else
+ if (host != null)
{
final VirtualHost<?,?,?> recoveredHost = host;
Subject.doAs(SecurityManager.getSubjectWithAddedSystemRights(), new PrivilegedAction<Object>()
@@ -142,6 +118,44 @@ public abstract class AbstractStandardVirtualHostNode<X extends AbstractStandard
}
}
+
+ @Override
+ protected ConfiguredObjectRecord enrichInitialVirtualHostRootRecord(final ConfiguredObjectRecord vhostRecord)
+ {
+ ConfiguredObjectRecord replacementRecord;
+ if (vhostRecord.getAttributes().get(ConfiguredObject.NAME) == null)
+ {
+ Map<String, Object> updatedAttributes = new LinkedHashMap<>(vhostRecord.getAttributes());
+ updatedAttributes.put(ConfiguredObject.NAME, getName());
+ if (!updatedAttributes.containsKey(VirtualHost.MODEL_VERSION))
+ {
+ updatedAttributes.put(VirtualHost.MODEL_VERSION, getBroker().getModelVersion());
+ }
+ replacementRecord = new ConfiguredObjectRecordImpl(vhostRecord.getId(),
+ vhostRecord.getType(),
+ updatedAttributes,
+ vhostRecord.getParents());
+ }
+ else if (vhostRecord.getAttributes().get(VirtualHost.MODEL_VERSION) == null)
+ {
+ Map<String, Object> updatedAttributes = new LinkedHashMap<>(vhostRecord.getAttributes());
+
+ updatedAttributes.put(VirtualHost.MODEL_VERSION, getBroker().getModelVersion());
+
+ replacementRecord = new ConfiguredObjectRecordImpl(vhostRecord.getId(),
+ vhostRecord.getType(),
+ updatedAttributes,
+ vhostRecord.getParents());
+ }
+ else
+ {
+ replacementRecord = vhostRecord;
+ }
+
+ return replacementRecord;
+ }
+
+
protected abstract void writeLocationEventLog();
@Override
diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
index ad9df793c8..e866effc54 100644
--- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
+++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
@@ -20,36 +20,61 @@
*/
package org.apache.qpid.server.virtualhostnode;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessControlException;
+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.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicReference;
+
import org.apache.log4j.Logger;
+
+import org.apache.qpid.exchange.ExchangeDefaults;
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
import org.apache.qpid.server.logging.EventLogger;
import org.apache.qpid.server.logging.messages.ConfigStoreMessages;
import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Exchange;
import org.apache.qpid.server.model.LifetimePolicy;
+import org.apache.qpid.server.model.ManagedAttributeField;
import org.apache.qpid.server.model.State;
import org.apache.qpid.server.model.StateTransition;
import org.apache.qpid.server.model.SystemConfig;
import org.apache.qpid.server.model.VirtualHost;
import org.apache.qpid.server.model.VirtualHostNode;
import org.apache.qpid.server.security.access.Operation;
+import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.server.store.ConfiguredObjectRecordConverter;
+import org.apache.qpid.server.store.ConfiguredObjectRecordImpl;
import org.apache.qpid.server.store.DurableConfigurationStore;
-
-import java.security.AccessControlException;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
+import org.apache.qpid.server.util.urlstreamhandler.data.Handler;
public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<X>> extends AbstractConfiguredObject<X> implements VirtualHostNode<X>
{
- public static final String VIRTUALHOST_BLUEPRINT_CONTEXT_VAR = "virtualhostBlueprint";
- public static final String VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR = "virtualhostBlueprintUtilised";
private static final Logger LOGGER = Logger.getLogger(AbstractVirtualHostNode.class);
+
+ static
+ {
+ Handler.register();
+ }
+
private final Broker<?> _broker;
private final AtomicReference<State> _state = new AtomicReference<State>(State.UNINITIALIZED);
private final EventLogger _eventLogger;
@@ -58,6 +83,9 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<
private MessageStoreLogSubject _configurationStoreLogSubject;
+ @ManagedAttributeField
+ private String _virtualHostInitialConfiguration;
+
public AbstractVirtualHostNode(Broker<?> parent, Map<String, Object> attributes)
{
super(Collections.<Class<? extends ConfiguredObject>,ConfiguredObject<?>>singletonMap(Broker.class, parent),
@@ -241,8 +269,152 @@ public abstract class AbstractVirtualHostNode<X extends AbstractVirtualHostNode<
}
}
+ @Override
+ public String getVirtualHostInitialConfiguration()
+ {
+ return _virtualHostInitialConfiguration;
+ }
+
protected abstract DurableConfigurationStore createConfigurationStore();
protected abstract void activate();
+
+
+ protected abstract ConfiguredObjectRecord enrichInitialVirtualHostRootRecord(final ConfiguredObjectRecord vhostRecord);
+
+ protected final ConfiguredObjectRecord[] getInitialRecords() throws IOException
+ {
+ ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(getModel());
+
+ Collection<ConfiguredObjectRecord> records =
+ new ArrayList<>(converter.readFromJson(VirtualHost.class,this,getInitialConfigReader()));
+
+ if(!records.isEmpty())
+ {
+ ConfiguredObjectRecord vhostRecord = null;
+ for(ConfiguredObjectRecord record : records)
+ {
+ if(record.getType().equals(VirtualHost.class.getSimpleName()))
+ {
+ vhostRecord = record;
+ break;
+ }
+ }
+ if(vhostRecord != null)
+ {
+ records.remove(vhostRecord);
+ vhostRecord = enrichInitialVirtualHostRootRecord(vhostRecord);
+ records.add(vhostRecord);
+ }
+ else
+ {
+ // this should be impossible as the converter should always generate a parent record
+ throw new IllegalConfigurationException("Somehow the initial configuration has records but "
+ + "not a VirtualHost. This must be a coding error in Qpid");
+ }
+ addStandardExchangesIfNecessary(records, vhostRecord);
+ enrichWithAuditInformation(records);
+ }
+
+
+ return records.toArray(new ConfiguredObjectRecord[records.size()]);
+ }
+
+ private void enrichWithAuditInformation(final Collection<ConfiguredObjectRecord> records)
+ {
+ List<ConfiguredObjectRecord> replacements = new ArrayList<>(records.size());
+
+ for(ConfiguredObjectRecord record : records)
+ {
+ replacements.add(new ConfiguredObjectRecordImpl(record.getId(), record.getType(),
+ enrichAttributesWithAuditInformation(record.getAttributes()),
+ record.getParents()));
+ }
+ records.clear();
+ records.addAll(replacements);
+ }
+
+ private Map<String, Object> enrichAttributesWithAuditInformation(final Map<String, Object> attributes)
+ {
+ LinkedHashMap<String,Object> enriched = new LinkedHashMap<>(attributes);
+ final AuthenticatedPrincipal currentUser = org.apache.qpid.server.security.SecurityManager.getCurrentUser();
+
+ if(currentUser != null)
+ {
+ enriched.put(ConfiguredObject.LAST_UPDATED_BY, currentUser.getName());
+ enriched.put(ConfiguredObject.CREATED_BY, currentUser.getName());
+ }
+ long currentTime = System.currentTimeMillis();
+ enriched.put(ConfiguredObject.LAST_UPDATED_TIME, currentTime);
+ enriched.put(ConfiguredObject.CREATED_TIME, currentTime);
+
+ return enriched;
+ }
+
+ private void addStandardExchangesIfNecessary(final Collection<ConfiguredObjectRecord> records,
+ final ConfiguredObjectRecord vhostRecord)
+ {
+ addExchangeIfNecessary(ExchangeDefaults.FANOUT_EXCHANGE_CLASS, ExchangeDefaults.FANOUT_EXCHANGE_NAME, records, vhostRecord);
+ addExchangeIfNecessary(ExchangeDefaults.HEADERS_EXCHANGE_CLASS, ExchangeDefaults.HEADERS_EXCHANGE_NAME, records, vhostRecord);
+ addExchangeIfNecessary(ExchangeDefaults.TOPIC_EXCHANGE_CLASS, ExchangeDefaults.TOPIC_EXCHANGE_NAME, records, vhostRecord);
+ addExchangeIfNecessary(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, ExchangeDefaults.DIRECT_EXCHANGE_NAME, records, vhostRecord);
+ }
+
+ private void addExchangeIfNecessary(final String exchangeClass,
+ final String exchangeName,
+ final Collection<ConfiguredObjectRecord> records,
+ final ConfiguredObjectRecord vhostRecord)
+ {
+ boolean found = false;
+
+ for(ConfiguredObjectRecord record : records)
+ {
+ if(Exchange.class.getSimpleName().equals(record.getType())
+ && exchangeName.equals(record.getAttributes().get(ConfiguredObject.NAME)))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ {
+ final Map<String, Object> exchangeAttributes = new HashMap<>();
+ exchangeAttributes.put(ConfiguredObject.NAME, exchangeName);
+ exchangeAttributes.put(ConfiguredObject.TYPE, exchangeClass);
+
+ records.add(new ConfiguredObjectRecordImpl(UUID.randomUUID(), Exchange.class.getSimpleName(),
+ exchangeAttributes, Collections.singletonMap(VirtualHost.class.getSimpleName(), vhostRecord.getId())));
+ }
+ }
+
+ protected final Reader getInitialConfigReader() throws IOException
+ {
+ Reader initialConfigReader;
+ if(getVirtualHostInitialConfiguration() != null)
+ {
+ String initialContextString = getVirtualHostInitialConfiguration();
+
+
+ try
+ {
+ URL url = new URL(initialContextString);
+
+ initialConfigReader =new InputStreamReader(url.openStream());
+ }
+ catch (MalformedURLException e)
+ {
+ initialConfigReader = new StringReader(initialContextString);
+ }
+
+ }
+ else
+ {
+ LOGGER.warn("No initial configuration found for the virtual host");
+ initialConfigReader = new StringReader("{}");
+ }
+ return initialConfigReader;
+ }
+
}
diff --git a/qpid/java/broker-core/src/main/resources/initial-config.json b/qpid/java/broker-core/src/main/resources/initial-config.json
index 9f1f779559..5ee820d9ac 100644
--- a/qpid/java/broker-core/src/main/resources/initial-config.json
+++ b/qpid/java/broker-core/src/main/resources/initial-config.json
@@ -20,7 +20,6 @@
*/
{
"name": "${broker.name}",
- "storeVersion": 1,
"modelVersion": "2.0",
"defaultVirtualHost" : "default",
"authenticationproviders" : [ {
@@ -55,9 +54,7 @@
"virtualhostnodes" : [ {
"name" : "default",
"type" : "JSON",
- "context" : {
- "virtualhostBlueprint" : "{ \"type\" : \"DERBY\" }"
- }
+ "virtualHostInitialConfiguration" : "{ \"type\" : \"DERBY\" }"
} ],
"plugins" : [ {
"type" : "MANAGEMENT-HTTP",
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
index e147abd170..e5c5a89c10 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/AbstractConfiguredObjectTest.java
@@ -26,6 +26,7 @@ import java.util.Map;
import junit.framework.TestCase;
+import org.apache.qpid.server.model.testmodel.TestChildCategory;
import org.apache.qpid.server.model.testmodel.TestModel;
import org.apache.qpid.server.model.testmodel.TestRootCategory;
import org.apache.qpid.server.store.ConfiguredObjectRecord;
@@ -187,4 +188,73 @@ public class AbstractConfiguredObjectTest extends TestCase
assertEquals("myValue", object1.getStringValue());
}
-} \ No newline at end of file
+ public void testCreationOfObjectWithInvalidInterpolatedValues()
+ {
+ final String parentName = "parent";
+ TestRootCategory parent =
+ _model.getObjectFactory().create(TestRootCategory.class,
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
+ parentName)
+ );
+
+ parent.setAttributes(Collections.singletonMap(ConfiguredObject.CONTEXT,
+ Collections.singletonMap("contextVal", "foo")));
+
+ final Map<String, Object> attributes = new HashMap<>();
+ attributes.put("intValue", "${contextVal}");
+ attributes.put("name", "child");
+ attributes.put("integerSet", "[ ]");
+ attributes.put(ConfiguredObject.TYPE, "test");
+
+ try
+ {
+ _model.getObjectFactory().create(TestChildCategory.class, attributes, parent);
+ fail("creation of child object should have failed due to invalid value");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // PASS
+ String message = e.getMessage();
+ assertTrue("Message does not contain the attribute name", message.contains("intValue"));
+ assertTrue("Message does not contain the non-interpolated value", message.contains("contextVal"));
+ assertTrue("Message does not contain the interpolated value", message.contains("foo"));
+
+ }
+
+ assertTrue("Child should not have been registered with parent",
+ parent.getChildren(TestChildCategory.class).isEmpty());
+ }
+
+ public void testCreationOfObjectWithInvalidDefaultValues()
+ {
+ final String parentName = "parent";
+ TestRootCategory parent =
+ _model.getObjectFactory().create(TestRootCategory.class,
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME,
+ parentName)
+ );
+
+ final Map<String, Object> attributes = new HashMap<>();
+ attributes.put("intValue", "1");
+ attributes.put("name", "child");
+ attributes.put(ConfiguredObject.TYPE, "test");
+
+ try
+ {
+ _model.getObjectFactory().create(TestChildCategory.class, attributes, parent);
+ fail("creation of child object should have failed due to invalid value");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // PASS
+ String message = e.getMessage();
+ assertTrue("Message does not contain the attribute name", message.contains("integerSet"));
+ assertTrue("Message does not contain the error value", message.contains("foo"));
+
+ }
+
+ assertTrue("Child should not have been registered with parent",
+ parent.getChildren(TestChildCategory.class).isEmpty());
+ }
+
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java
index 0c8dcc8744..d3fe14b7d8 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategory.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.model.testmodel;
+import java.util.Set;
+
import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ManagedAttribute;
import org.apache.qpid.server.model.ManagedObject;
@@ -30,6 +32,12 @@ public interface TestChildCategory<X extends TestChildCategory<X>> extends Confi
String NON_INTERPOLATED_VALID_VALUE = "${file.separator}";
- @ManagedAttribute(validValues = { NON_INTERPOLATED_VALID_VALUE })
+ @ManagedAttribute(validValues = { NON_INTERPOLATED_VALID_VALUE }, defaultValue = "")
String getValidValueNotInterpolated();
+
+ @ManagedAttribute( defaultValue = "3" )
+ int getIntValue();
+
+ @ManagedAttribute( defaultValue = "[ \"1\", \"2\", \"foo\" ]" )
+ Set<Integer> getIntegerSet();
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategoryImpl.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategoryImpl.java
index b5a4182f79..080a352f11 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategoryImpl.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/model/testmodel/TestChildCategoryImpl.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.model.testmodel;
import java.util.Map;
+import java.util.Set;
import org.apache.qpid.server.model.AbstractConfiguredObject;
import org.apache.qpid.server.model.ManagedAttributeField;
@@ -37,6 +38,12 @@ public class TestChildCategoryImpl
@ManagedAttributeField
private String _validValueNotInterpolated;
+ @ManagedAttributeField
+ private int _intValue;
+
+ @ManagedAttributeField
+ private Set<Integer> _integerSet;
+
@ManagedObjectFactoryConstructor
public TestChildCategoryImpl(final Map<String, Object> attributes, TestRootCategory<?> parent)
@@ -57,4 +64,16 @@ public class TestChildCategoryImpl
{
return _validValueNotInterpolated;
}
+
+ @Override
+ public int getIntValue()
+ {
+ return _intValue;
+ }
+
+ @Override
+ public Set<Integer> getIntegerSet()
+ {
+ return _integerSet;
+ }
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
index 56283b1392..6001ed1750 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManagerFactoryTest.java
@@ -36,7 +36,6 @@ import org.apache.qpid.server.model.Broker;
import org.apache.qpid.server.model.BrokerModel;
import org.apache.qpid.server.model.ConfiguredObjectFactory;
import org.apache.qpid.server.model.TrustStore;
-import org.apache.qpid.server.model.UnknownConfiguredObjectException;
import org.apache.qpid.server.util.BrokerTestHelper;
public class SimpleLDAPAuthenticationManagerFactoryTest extends TestCase
@@ -108,10 +107,12 @@ public class SimpleLDAPAuthenticationManagerFactoryTest extends TestCase
_factory.create(AuthenticationProvider.class, _configuration, _broker);
fail("Exception not thrown");
}
- catch(UnknownConfiguredObjectException e)
+ catch(IllegalArgumentException e)
{
- assertEquals(e.getCategory(), TrustStore.class);
- assertEquals(e.getName(), "notfound");
+ // PASS
+ assertTrue("Message does not include underlying issue", e.getMessage().contains("name 'notfound'"));
+ assertTrue("Message does not include the attribute name", e.getMessage().contains("trustStore"));
+ assertTrue("Message does not include the expected type", e.getMessage().contains("TrustStore"));
}
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
index 6d84c7b602..dd8b4cf4dd 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/AbstractDurableConfigurationStoreTestCase.java
@@ -115,7 +115,7 @@ public abstract class AbstractDurableConfigurationStoreTestCase extends QpidTest
_configStore = createConfigStore();
_configStore.openConfigurationStore(_parent, false);
- _rootRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), VirtualHost.class.getSimpleName(), Collections.<String, Object>emptyMap());
+ _rootRecord = new ConfiguredObjectRecordImpl(UUID.randomUUID(), VirtualHost.class.getSimpleName(), Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "vhost"));
_configStore.create(_rootRecord);
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverterTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverterTest.java
new file mode 100644
index 0000000000..bef3cdcac9
--- /dev/null
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/ConfiguredObjectRecordConverterTest.java
@@ -0,0 +1,142 @@
+/*
+ *
+ * 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 static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.StringReader;
+import java.util.Collection;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Exchange;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class ConfiguredObjectRecordConverterTest extends QpidTestCase
+{
+
+ public void testSecondParentReferencedByName() throws Exception
+ {
+
+ String jsonData = "{\n"
+ + " \"name\" : \"test\",\n"
+ + " \"exchanges\" : [ {\n"
+ + " \"name\" : \"amq.direct\",\n"
+ + " \"type\" : \"direct\"\n"
+ + " } ],\n"
+ + " \"queues\" : [ {\n"
+ + " \"name\" : \"foo\",\n"
+ + " \"bindings\" : [ {\n"
+ + " \"exchange\" : \"amq.direct\",\n"
+ + " \"name\" : \"foo\"\n"
+ + " } ]\n"
+ + " } ]\n"
+ + "} ";
+
+ ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(BrokerModel.getInstance());
+ ConfiguredObject parent = mock(ConfiguredObject.class);
+ when(parent.getId()).thenReturn(UUID.randomUUID());
+ when(parent.getCategoryClass()).thenReturn(VirtualHostNode.class);
+ Collection<ConfiguredObjectRecord> records =
+ converter.readFromJson(VirtualHost.class, parent, new StringReader(jsonData));
+
+ UUID exchangeId = null;
+ for (ConfiguredObjectRecord record : records)
+ {
+ if (record.getType().equals(Exchange.class.getSimpleName()))
+ {
+ assertNull("Only one exchange record expected", exchangeId);
+ exchangeId = record.getId();
+ }
+ }
+ assertNotNull("No exchange record found", exchangeId);
+
+ UUID queueId = null;
+ for (ConfiguredObjectRecord record : records)
+ {
+ if (record.getType().equals(Queue.class.getSimpleName()))
+ {
+ assertNull("Only one queue record expected", queueId);
+ queueId = record.getId();
+ }
+ }
+ assertNotNull("No queueId record found", queueId);
+
+ boolean bindingFound = false;
+ for (ConfiguredObjectRecord record : records)
+ {
+ if (record.getType().equals(Binding.class.getSimpleName()))
+ {
+ assertFalse("Expecting only one binding", bindingFound);
+ bindingFound = true;
+ Map<String,UUID> parents = record.getParents();
+ assertEquals("Two parents expected", 2, parents.size());
+ assertEquals("Queue parent id not as expected", queueId, parents.get(Queue.class.getSimpleName()));
+ assertEquals("Exchange parent id not as expected", exchangeId, parents.get(Exchange.class.getSimpleName()));
+
+ }
+ }
+ assertTrue("No binding found", bindingFound);
+ }
+
+ public void testUnresolvedSecondParentFailsToCovert() throws Exception
+ {
+ {
+
+ String jsonData = "{\n"
+ + " \"name\" : \"test\",\n"
+ + " \"exchanges\" : [ {\n"
+ + " \"name\" : \"amq.direct\",\n"
+ + " \"type\" : \"direct\"\n"
+ + " } ],\n"
+ + " \"queues\" : [ {\n"
+ + " \"name\" : \"foo\",\n"
+ + " \"bindings\" : [ {\n"
+ + " \"exchange\" : \"amq.topic\",\n"
+ + " \"name\" : \"foo\"\n"
+ + " } ]\n"
+ + " } ]\n"
+ + "} ";
+
+ ConfiguredObjectRecordConverter converter = new ConfiguredObjectRecordConverter(BrokerModel.getInstance());
+ ConfiguredObject parent = mock(ConfiguredObject.class);
+ when(parent.getId()).thenReturn(UUID.randomUUID());
+ when(parent.getCategoryClass()).thenReturn(VirtualHostNode.class);
+ try
+ {
+ converter.readFromJson(VirtualHost.class, parent, new StringReader(jsonData));
+ fail("The records should not be converted as there is an unresolved reference");
+ }
+ catch (IllegalArgumentException e)
+ {
+ // pass
+ }
+
+ }
+ }
+}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java
index ee8f6497bc..b652992021 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/JsonFileConfigStoreTest.java
@@ -38,6 +38,7 @@ import org.mockito.ArgumentMatcher;
import org.mockito.InOrder;
import org.apache.qpid.server.model.BrokerModel;
+import org.apache.qpid.server.model.ConfiguredObject;
import org.apache.qpid.server.model.ConfiguredObjectFactory;
import org.apache.qpid.server.model.ConfiguredObjectFactoryImpl;
import org.apache.qpid.server.model.Queue;
@@ -248,10 +249,14 @@ public class JsonFileConfigStoreTest extends QpidTestCase
createRootRecord();
final UUID id = UUID.randomUUID();
- _store.create(new ConfiguredObjectRecordImpl(id, "Queue", Collections.<String, Object>emptyMap(), getRootAsParentMap()));
+ _store.create(new ConfiguredObjectRecordImpl(id, "Queue",
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "queue"),
+ getRootAsParentMap()));
try
{
- _store.create(new ConfiguredObjectRecordImpl(id, "Exchange", Collections.<String, Object>emptyMap(), getRootAsParentMap()));
+ _store.create(new ConfiguredObjectRecordImpl(id, "Exchange",
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "exchange"),
+ getRootAsParentMap()));
fail("Should not be able to create two objects with same id");
}
catch (StoreException e)
@@ -261,19 +266,61 @@ public class JsonFileConfigStoreTest extends QpidTestCase
}
+ public void testObjectWithoutName() throws Exception
+ {
+ _store.openConfigurationStore(_parent, false);
+ createRootRecord();
+
+ final UUID id = UUID.randomUUID();
+ try
+ {
+ _store.create(new ConfiguredObjectRecordImpl(id, "Exchange",
+ Collections.<String, Object>emptyMap(),
+ getRootAsParentMap()));
+ fail("Should not be able to create an object without a name");
+ }
+ catch (StoreException e)
+ {
+ // pass
+ }
+ }
+
+ public void testObjectWithNonStringName() throws Exception
+ {
+ _store.openConfigurationStore(_parent, false);
+ createRootRecord();
+
+ final UUID id = UUID.randomUUID();
+ try
+ {
+ _store.update(true, new ConfiguredObjectRecordImpl(id, "Exchange",
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME, 3),
+ getRootAsParentMap()));
+ fail("Should not be able to create an object without a name");
+ }
+ catch (StoreException e)
+ {
+ // pass
+ }
+ }
+
public void testChangeTypeOfObject() throws Exception
{
_store.openConfigurationStore(_parent, false);
createRootRecord();
final UUID id = UUID.randomUUID();
- _store.create(new ConfiguredObjectRecordImpl(id, "Queue", Collections.<String, Object>emptyMap(), getRootAsParentMap()));
+ _store.create(new ConfiguredObjectRecordImpl(id, "Queue",
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "queue"),
+ getRootAsParentMap()));
_store.closeConfigurationStore();
_store.openConfigurationStore(_parent, false);
try
{
- _store.update(false, new ConfiguredObjectRecordImpl(id, "Exchange", Collections.<String, Object>emptyMap(), getRootAsParentMap()));
+ _store.update(false, new ConfiguredObjectRecordImpl(id, "Exchange",
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "exchange"),
+ getRootAsParentMap()));
fail("Should not be able to update object to different type");
}
catch (StoreException e)
@@ -329,40 +376,57 @@ public class JsonFileConfigStoreTest extends QpidTestCase
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 UUID bindingId = new UUID(0, 3);
final UUID binding2Id = new UUID(1, 3);
Map<String, UUID> parents = getRootAsParentMap();
- final ConfiguredObjectRecordImpl queueRecord = new ConfiguredObjectRecordImpl(queueId, "Queue", EMPTY_ATTR, parents);
+ Map<String, Object> queueAttr = Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "queue");
+ final ConfiguredObjectRecordImpl queueRecord =
+ new ConfiguredObjectRecordImpl(queueId, "Queue",
+ queueAttr,
+ parents);
_store.create(queueRecord);
- final ConfiguredObjectRecordImpl queue2Record = new ConfiguredObjectRecordImpl(queue2Id, "Queue", EMPTY_ATTR, parents);
+ Map<String, Object> queue2Attr = Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "queue2");
+ final ConfiguredObjectRecordImpl queue2Record =
+ new ConfiguredObjectRecordImpl(queue2Id, "Queue",
+ queue2Attr,
+ parents);
_store.create(queue2Record);
- final ConfiguredObjectRecordImpl exchangeRecord = new ConfiguredObjectRecordImpl(exchangeId, "Exchange", EMPTY_ATTR, parents);
+ Map<String, Object> exchangeAttr = Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "exchange");
+ final ConfiguredObjectRecordImpl exchangeRecord =
+ new ConfiguredObjectRecordImpl(exchangeId, "Exchange",
+ exchangeAttr,
+ parents);
_store.create(exchangeRecord);
Map<String,UUID> bindingParents = new HashMap();
bindingParents.put("Exchange", exchangeRecord.getId());
bindingParents.put("Queue", queueRecord.getId());
+ Map<String, Object> bindingAttr = Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "binding");
final ConfiguredObjectRecordImpl bindingRecord =
- new ConfiguredObjectRecordImpl(bindingId, "Binding", EMPTY_ATTR, bindingParents);
+ new ConfiguredObjectRecordImpl(bindingId, "Binding",
+ bindingAttr,
+ bindingParents);
Map<String,UUID> binding2Parents = new HashMap();
binding2Parents.put("Exchange", exchangeRecord.getId());
binding2Parents.put("Queue", queue2Record.getId());
+ Map<String, Object> binding2Attr = Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "binding2");
final ConfiguredObjectRecordImpl binding2Record =
- new ConfiguredObjectRecordImpl(binding2Id, "Binding", EMPTY_ATTR, binding2Parents);
+ new ConfiguredObjectRecordImpl(binding2Id, "Binding",
+ binding2Attr,
+ binding2Parents);
_store.update(true, bindingRecord, binding2Record);
_store.closeConfigurationStore();
_store.openConfigurationStore(_parent, false);
_store.visitConfiguredObjectRecords(_handler);
- verify(_handler).handle(matchesRecord(queueId, "Queue", EMPTY_ATTR));
- verify(_handler).handle(matchesRecord(queue2Id, "Queue", EMPTY_ATTR));
- verify(_handler).handle(matchesRecord(exchangeId, "Exchange", EMPTY_ATTR));
- verify(_handler).handle(matchesRecord(bindingId, "Binding", EMPTY_ATTR));
- verify(_handler).handle(matchesRecord(binding2Id, "Binding", EMPTY_ATTR));
+ verify(_handler).handle(matchesRecord(queueId, "Queue", queueAttr));
+ verify(_handler).handle(matchesRecord(queue2Id, "Queue", queue2Attr));
+ verify(_handler).handle(matchesRecord(exchangeId, "Exchange", exchangeAttr));
+ verify(_handler).handle(matchesRecord(bindingId, "Binding", bindingAttr));
+ verify(_handler).handle(matchesRecord(binding2Id, "Binding", binding2Attr));
_store.closeConfigurationStore();
}
@@ -371,7 +435,10 @@ public class JsonFileConfigStoreTest extends QpidTestCase
private void createRootRecord()
{
UUID rootRecordId = UUID.randomUUID();
- _rootRecord = new ConfiguredObjectRecordImpl(rootRecordId, VIRTUAL_HOST_TYPE, Collections.<String, Object>emptyMap());
+ _rootRecord =
+ new ConfiguredObjectRecordImpl(rootRecordId,
+ VIRTUAL_HOST_TYPE,
+ Collections.<String, Object>singletonMap(ConfiguredObject.NAME, "root"));
_store.create(_rootRecord);
}
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
index 9c8f4ed3ae..8573ae3a42 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/util/BrokerTestHelper.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.util;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -90,6 +91,7 @@ public class BrokerTestHelper
when(broker.getSecurityManager()).thenReturn(new SecurityManager(broker, false));
when(broker.getObjectFactory()).thenReturn(objectFactory);
when(broker.getModel()).thenReturn(objectFactory.getModel());
+ when(broker.getModelVersion()).thenReturn(BrokerModel.MODEL_VERSION);
when(broker.getEventLogger()).thenReturn(eventLogger);
when(broker.getCategoryClass()).thenReturn(Broker.class);
when(broker.getParent(SystemConfig.class)).thenReturn(systemConfig);
@@ -117,9 +119,11 @@ public class BrokerTestHelper
VirtualHostNode virtualHostNode = mock(VirtualHostNode.class);
when(virtualHostNode.getTaskExecutor()).thenReturn(TASK_EXECUTOR);
+ when(virtualHostNode.getParent(eq(Broker.class))).thenReturn(broker);
+
DurableConfigurationStore dcs = mock(DurableConfigurationStore.class);
when(virtualHostNode.getConfigurationStore()).thenReturn(dcs);
- when(virtualHostNode.getParent(Broker.class)).thenReturn(broker);
+ when(virtualHostNode.getParent(eq(VirtualHostNode.class))).thenReturn(virtualHostNode);
when(virtualHostNode.getModel()).thenReturn(objectFactory.getModel());
when(virtualHostNode.getObjectFactory()).thenReturn(objectFactory);
when(virtualHostNode.getCategoryClass()).thenReturn(VirtualHostNode.class);
diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
index 19436627ce..971c96b2ff 100644
--- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
+++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/virtualhostnode/AbstractStandardVirtualHostNodeTest.java
@@ -139,7 +139,7 @@ public class AbstractStandardVirtualHostNodeTest extends QpidTestCase
*/
public void testActivateVHNWithVHBlueprint_StoreHasNoVH() throws Exception
{
- DurableConfigurationStore configStore = configStoreThatProducesNoRecords();
+ DurableConfigurationStore configStore = new NullMessageStore() {};
String vhBlueprint = String.format("{ \"type\" : \"%s\", \"name\" : \"%s\"}",
TestMemoryVirtualHost.VIRTUAL_HOST_TYPE,
@@ -162,18 +162,12 @@ public class AbstractStandardVirtualHostNodeTest extends QpidTestCase
assertEquals("Unexpected virtual host state", State.ACTIVE, virtualHost.getState());
assertNotNull("Unexpected virtual host id", virtualHost.getId());
- Map<String, String> updatedContext = node.getContext();
-
- assertTrue("Context should now have utilised flag", updatedContext.containsKey(
- AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR));
- assertEquals("Utilised flag should be true",
- Boolean.TRUE.toString(),
- updatedContext.get(AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR));
+ assertEquals("Initial configuration should be empty", "{}", node.getVirtualHostInitialConfiguration());
}
/**
* Tests activating a virtualhostnode with blueprint context variable and the
- * marked utilised flag. Config store does not specify a virtualhost.
+ * but the virtualhostInitialConfiguration set to empty. Config store does not specify a virtualhost.
* Checks virtualhost is not recreated from the blueprint.
*/
public void testActivateVHNWithVHBlueprintUsed_StoreHasNoVH() throws Exception
@@ -185,12 +179,12 @@ public class AbstractStandardVirtualHostNodeTest extends QpidTestCase
TEST_VIRTUAL_HOST_NAME);
Map<String, String> context = new HashMap<>();
context.put(AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_CONTEXT_VAR, vhBlueprint);
- context.put(AbstractVirtualHostNode.VIRTUALHOST_BLUEPRINT_UTILISED_CONTEXT_VAR, Boolean.TRUE.toString());
Map<String, Object> nodeAttributes = new HashMap<>();
nodeAttributes.put(VirtualHostNode.NAME, TEST_VIRTUAL_HOST_NODE_NAME);
nodeAttributes.put(VirtualHostNode.ID, _nodeId);
nodeAttributes.put(VirtualHostNode.CONTEXT, context);
+ nodeAttributes.put(VirtualHostNode.VIRTUALHOST_INITIAL_CONFIGURATION, "{}");
VirtualHostNode<?> node = new TestVirtualHostNode(_broker, nodeAttributes, configStore);
node.open();