summaryrefslogtreecommitdiff
path: root/qpid/java/broker-core/src/main/java/org/apache
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/java/broker-core/src/main/java/org/apache')
-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
26 files changed, 641 insertions, 118 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;
+ }
+
}