You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rg...@apache.org on 2016/02/04 16:38:06 UTC

svn commit: r1728497 [1/2] - in /qpid/java/trunk: broker-core/src/main/java/org/apache/qpid/server/model/ broker-core/src/main/java/org/apache/qpid/server/plugin/ broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/ broker-core/...

Author: rgodfrey
Date: Thu Feb  4 15:38:05 2016
New Revision: 1728497

URL: http://svn.apache.org/viewvc?rev=1728497&view=rev
Log:
QPID-7049 : Provide a mechanism for injecting attributes/statistics at run time

Added:
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedInjectedAttribute.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedMethodAttribute.java
      - copied, changed from r1728496, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedAttribute.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttribute.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttributeOrStatistic.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttribute.java
      - copied, changed from r1728382, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttributeOrStatistic.java
      - copied, changed from r1728382, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java
      - copied, changed from r1728382, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableAttribute.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableInjectedAttribute.java
      - copied, changed from r1728382, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/InjectedAttributeOrStatistic.java   (with props)
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectAttributeInjector.java   (with props)
    qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java   (with props)
Removed:
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedAttribute.java
Modified:
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractUnresolvedObject.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java
    qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
    qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestModel.java
    qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java
    qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/lifecycle/TestConfiguredObject.java
    qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/singleton/TestModel.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ApiDocsServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MetaDataServlet.java
    qpid/java/trunk/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java?rev=1728497&r1=1728496&r2=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java Thu Feb  4 15:38:05 2016
@@ -73,7 +73,6 @@ import org.apache.qpid.server.security.e
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 import org.apache.qpid.server.util.Action;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
-import org.apache.qpid.server.virtualhost.AbstractVirtualHost;
 import org.apache.qpid.util.Strings;
 
 public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> implements ConfiguredObject<X>
@@ -284,7 +283,7 @@ public abstract class AbstractConfigured
 
         Object durableObj = attributes.get(DURABLE);
         _durable = AttributeValueConverter.BOOLEAN_CONVERTER.convert(durableObj == null
-                                                                             ? ((ConfiguredAutomatedAttribute) (_attributeTypes
+                                                                             ? ((ConfiguredSettableAttribute) (_attributeTypes
                 .get(DURABLE))).defaultValue()
                                                                              : durableObj, this);
 
@@ -314,9 +313,9 @@ public abstract class AbstractConfigured
         }
         for(ConfiguredObjectAttribute<?,?> attr : _attributeTypes.values())
         {
-            if(attr.isAutomated())
+            if(!attr.isDerived())
             {
-                ConfiguredAutomatedAttribute<?,?> autoAttr = (ConfiguredAutomatedAttribute<?,?>)attr;
+                ConfiguredSettableAttribute<?,?> autoAttr = (ConfiguredSettableAttribute<?,?>)attr;
                 if (autoAttr.isMandatory() && !(_attributes.containsKey(attr.getName())
                                             || !"".equals(autoAttr.defaultValue())))
                 {
@@ -432,7 +431,7 @@ public abstract class AbstractConfigured
         }
     }
 
-    private boolean checkValidValues(final ConfiguredAutomatedAttribute attribute, final Object desiredValue)
+    private boolean checkValidValues(final ConfiguredSettableAttribute attribute, final Object desiredValue)
     {
         for (Object validValue : attribute.validValues())
         {
@@ -1066,9 +1065,9 @@ public abstract class AbstractConfigured
     {
         for(ConfiguredObjectAttribute<?,?> attr : _attributeTypes.values())
         {
-            if (attr.isAutomated())
+            if (!attr.isDerived())
             {
-                ConfiguredAutomatedAttribute autoAttr = (ConfiguredAutomatedAttribute) attr;
+                ConfiguredSettableAttribute autoAttr = (ConfiguredSettableAttribute) attr;
                 if (autoAttr.hasValidValues())
                 {
                     Object desiredValueOrDefault = autoAttr.getValue(this);
@@ -1112,22 +1111,25 @@ public abstract class AbstractConfigured
 
         for (ConfiguredObjectAttribute<?, ?> attr : _attributeTypes.values())
         {
-            if (attr.isAutomated())
+            if(attr.isDerived())
             {
-                unresolved.add(attr);
+                derived.add(attr);
             }
-            else if(attr.isDerived())
+            else
             {
-                derived.add(attr);
+                unresolved.add(attr);
             }
         }
 
         // If there is a context attribute, resolve it first, so that other attribute values
         // may support values containing references to context keys.
         ConfiguredObjectAttribute<?, ?> contextAttribute = _attributeTypes.get("context");
-        if (contextAttribute != null && contextAttribute.isAutomated())
+        if (contextAttribute != null && !contextAttribute.isDerived())
         {
-            resolveAutomatedAttribute((ConfiguredAutomatedAttribute<?, ?>) contextAttribute);
+            if(contextAttribute.isAutomated())
+            {
+                resolveAutomatedAttribute((ConfiguredSettableAttribute<?, ?>) contextAttribute);
+            }
             unresolved.remove(contextAttribute);
         }
 
@@ -1143,7 +1145,10 @@ public abstract class AbstractConfigured
 
                 if(!(dependsOn(attr, unresolved) || (!derived.isEmpty() && dependsOn(attr, derived))))
                 {
-                    resolveAutomatedAttribute((ConfiguredAutomatedAttribute<?, ?>) attr);
+                    if(attr.isAutomated())
+                    {
+                        resolveAutomatedAttribute((ConfiguredSettableAttribute<?, ?>) attr);
+                    }
                     attrIter.remove();
                     changed = true;
                 }
@@ -1162,9 +1167,9 @@ public abstract class AbstractConfigured
                               final Set<ConfiguredObjectAttribute<?, ?>> unresolved)
     {
         Object value = _attributes.get(attr.getName());
-        if(value == null && !"".equals(((ConfiguredAutomatedAttribute)attr).defaultValue()))
+        if(value == null && !"".equals(((ConfiguredSettableAttribute)attr).defaultValue()))
         {
-            value = ((ConfiguredAutomatedAttribute)attr).defaultValue();
+            value = ((ConfiguredSettableAttribute)attr).defaultValue();
         }
         if(value instanceof String)
         {
@@ -1183,7 +1188,7 @@ public abstract class AbstractConfigured
         return false;
     }
 
-    private void resolveAutomatedAttribute(final ConfiguredAutomatedAttribute<?, ?> autoAttr)
+    private void resolveAutomatedAttribute(final ConfiguredSettableAttribute<?, ?> autoAttr)
     {
         String attrName = autoAttr.getName();
         if (_attributes.containsKey(attrName))
@@ -1581,7 +1586,7 @@ public abstract class AbstractConfigured
     public final Object getAttribute(String name)
     {
         ConfiguredObjectAttribute<X,?> attr = (ConfiguredObjectAttribute<X, ?>) _attributeTypes.get(name);
-        if(attr != null && (attr.isAutomated() || attr.isDerived()))
+        if(attr != null)
         {
             Object value = attr.getValue((X)this);
             if(value != null && !SecurityManager.isSystemProcess() && attr.isSecureValue(value))
@@ -1593,11 +1598,6 @@ public abstract class AbstractConfigured
                 return value;
             }
         }
-        else if(attr != null)
-        {
-            Object value = getActualAttribute(name);
-            return value;
-        }
         else
         {
             throw new IllegalArgumentException("Unknown attribute: '" + name + "'");
@@ -2524,9 +2524,9 @@ public abstract class AbstractConfigured
     {
         for(ConfiguredObjectAttribute<?,?> attr : _attributeTypes.values())
         {
-            if (attr.isAutomated() && changedAttributes.contains(attr.getName()))
+            if (!attr.isDerived() && changedAttributes.contains(attr.getName()))
             {
-                ConfiguredAutomatedAttribute autoAttr = (ConfiguredAutomatedAttribute) attr;
+                ConfiguredSettableAttribute autoAttr = (ConfiguredSettableAttribute) attr;
 
                 if (autoAttr.isImmutable() && !Objects.equals(autoAttr.getValue(this), autoAttr.getValue(proxyForValidation)))
                 {
@@ -2868,15 +2868,23 @@ public abstract class AbstractConfigured
                     return null;
                 }
             }
-            throw new UnsupportedOperationException("This class is only intended for value validation, and only getters on managed attributes are permitted.");
+            else if(method.getName().equals("getActualAttributes") && (args == null || args.length == 0))
+            {
+                return Collections.unmodifiableMap(_attributes);
+            }
+            else
+            {
+                throw new UnsupportedOperationException(
+                        "This class is only intended for value validation, and only getters on managed attributes are permitted.");
+            }
         }
 
         protected Object getValue(final ConfiguredObjectAttribute attribute)
         {
             Object value;
-            if(attribute.isAutomated())
+            if(!attribute.isDerived())
             {
-                ConfiguredAutomatedAttribute autoAttr = (ConfiguredAutomatedAttribute) attribute;
+                ConfiguredSettableAttribute autoAttr = (ConfiguredSettableAttribute) attribute;
                 value = _attributes.get(attribute.getName());
                 if (value == null && !"".equals(autoAttr.defaultValue()))
                 {
@@ -2899,7 +2907,7 @@ public abstract class AbstractConfigured
         {
             for(ConfiguredObjectAttribute attribute : _attributeTypes.values())
             {
-                if(attribute.getGetter().getName().equals(method.getName())
+                if((attribute instanceof ConfiguredObjectMethodAttribute) && ((ConfiguredObjectMethodAttribute)attribute).getGetter().getName().equals(method.getName())
                    && !Modifier.isStatic(method.getModifiers()))
                 {
                     return attribute;

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractUnresolvedObject.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractUnresolvedObject.java?rev=1728497&r1=1728496&r2=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractUnresolvedObject.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/AbstractUnresolvedObject.java Thu Feb  4 15:38:05 2016
@@ -60,11 +60,11 @@ public abstract class AbstractUnresolved
                 {
                     addUnresolvedObject((Class<? extends ConfiguredObject>) attributeType,
                                         attribute.getName(),
-                                        attribute.isAutomated() && ((ConfiguredAutomatedAttribute<? super C,?>)attribute).isMandatory());
+                                        attribute.isAutomated() && ((ConfiguredSettableAttribute<? super C,?>)attribute).isMandatory());
                 }
                 else if (Collection.class.isAssignableFrom(attributeType))
                 {
-                    Type returnType = attribute.getGetter().getGenericReturnType();
+                    Type returnType = attribute.getGenericType();
                     Class<? extends ConfiguredObject> attrClass = getMemberType(returnType);
                     if (attrClass != null)
                     {

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java?rev=1728497&r1=1728496&r2=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/BrokerModel.java Thu Feb  4 15:38:05 2016
@@ -28,6 +28,7 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.qpid.server.plugin.ConfiguredObjectAttributeInjector;
 import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
 import org.apache.qpid.server.plugin.QpidServiceLoader;
 
@@ -117,7 +118,9 @@ public final class BrokerModel extends M
         addRelationship(Session.class, Publisher.class);
 
         _objectFactory = new ConfiguredObjectFactoryImpl(this);
-        _typeRegistry = new ConfiguredObjectTypeRegistry((new QpidServiceLoader()).instancesOf(ConfiguredObjectRegistration.class), getSupportedCategories(),
+        _typeRegistry = new ConfiguredObjectTypeRegistry((new QpidServiceLoader()).instancesOf(ConfiguredObjectRegistration.class),
+                                                         (new QpidServiceLoader()).instancesOf(ConfiguredObjectAttributeInjector.class),
+                                                         getSupportedCategories(),
                                                          _objectFactory);
     }
 

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java?rev=1728497&r1=1728496&r2=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java Thu Feb  4 15:38:05 2016
@@ -33,7 +33,8 @@ import java.util.regex.Pattern;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class ConfiguredAutomatedAttribute<C extends ConfiguredObject, T>  extends ConfiguredObjectAttribute<C,T>
+public class ConfiguredAutomatedAttribute<C extends ConfiguredObject, T>  extends ConfiguredObjectMethodAttribute<C,T>
+        implements ConfiguredSettableAttribute<C, T>
 {
     private static final Logger LOGGER = LoggerFactory.getLogger(ConfiguredAutomatedAttribute.class);
 
@@ -116,6 +117,7 @@ public class ConfiguredAutomatedAttribut
         return false;
     }
 
+    @Override
     public String defaultValue()
     {
         return _annotation.defaultValue();
@@ -126,11 +128,13 @@ public class ConfiguredAutomatedAttribut
         return _annotation.secure();
     }
 
+    @Override
     public boolean isMandatory()
     {
         return _annotation.mandatory();
     }
 
+    @Override
     public boolean isImmutable()
     {
         return _annotation.immutable();
@@ -169,6 +173,7 @@ public class ConfiguredAutomatedAttribut
         return _secureValuePattern;
     }
 
+    @Override
     public Collection<String> validValues()
     {
         if(_validValuesMethod != null)
@@ -190,6 +195,7 @@ public class ConfiguredAutomatedAttribut
     }
 
     /** Returns true iff this attribute has valid values defined */
+    @Override
     public boolean hasValidValues()
     {
         return validValues() != null && validValues().size() > 0;

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedInjectedAttribute.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedInjectedAttribute.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedInjectedAttribute.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedInjectedAttribute.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,176 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.regex.Pattern;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
+
+public class ConfiguredDerivedInjectedAttribute<C extends ConfiguredObject, T>
+        extends ConfiguredObjectInjectedAttributeOrStatistic<C, T> implements ConfiguredObjectInjectedAttribute<C, T>
+{
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ConfiguredDerivedInjectedAttribute.class);
+
+    private final Pattern _secureValuePattern;
+    private final boolean _secure;
+    private final boolean _persisted;
+    private final boolean _oversized;
+    private final String _oversizedAltText;
+    private final String _description;
+    private final Method _method;
+
+    public ConfiguredDerivedInjectedAttribute(final String name,
+                                              final Method method,
+                                              final boolean secure,
+                                              final boolean persisted,
+                                              final String secureValueFilter,
+                                              final boolean oversized,
+                                              final String oversizedAltText,
+                                              final String description,
+                                              final TypeValidator typeValidator)
+    {
+        super(name, (Class<T>) AttributeValueConverter.getTypeFromMethod(method),
+              method.getGenericReturnType(), typeValidator);
+
+        if(!(method.getParameterTypes().length == 1
+             && ConfiguredObject.class.isAssignableFrom(method.getParameterTypes()[0])
+             && Modifier.isStatic(method.getModifiers())))
+        {
+            throw new IllegalArgumentException("Injected derived attribute method must be static, and have a single argument which inherits from ConfiguredObject");
+        }
+        _method = method;
+        method.setAccessible(true);
+        _secure = secure;
+        _persisted = persisted;
+        _oversized = oversized;
+        _oversizedAltText = oversizedAltText;
+        _description = description;
+
+        if (secureValueFilter == null || "".equals(secureValueFilter))
+        {
+            _secureValuePattern = null;
+        }
+        else
+        {
+            _secureValuePattern = Pattern.compile(secureValueFilter);
+        }
+    }
+
+    @Override
+    public boolean isAutomated()
+    {
+        return false;
+    }
+
+    public boolean isDerived()
+    {
+        return true;
+    }
+
+    public boolean isSecure()
+    {
+        return _secure;
+    }
+
+    public boolean isPersisted()
+    {
+        return _persisted;
+    }
+
+    @Override
+    public boolean isOversized()
+    {
+        return _oversized;
+    }
+
+    @Override
+    public boolean updateAttributeDespiteUnchangedValue()
+    {
+        return false;
+    }
+
+    @Override
+    public String getOversizedAltText()
+    {
+        return _oversizedAltText;
+    }
+
+    public String getDescription()
+    {
+        return _description;
+    }
+
+    public Pattern getSecureValueFilter()
+    {
+        return _secureValuePattern;
+    }
+
+    @Override
+    public boolean isSecureValue(final Object value)
+    {
+        Pattern filter;
+        return isSecure() &&
+               ((filter = getSecureValueFilter()) == null || filter.matcher(String.valueOf(value)).matches());
+    }
+
+
+    @Override
+    public T getValue(final C configuredObject)
+    {
+        try
+        {
+            return (T) _method.invoke(null, configuredObject);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new ServerScopedRuntimeException("Unable to get value for '"+getName()
+                                                   +"' from configured object of category "
+                                                   + configuredObject.getCategoryClass().getSimpleName(), e);
+        }
+        catch (InvocationTargetException e)
+        {
+            Throwable targetException = e.getTargetException();
+            if(targetException instanceof RuntimeException)
+            {
+                throw (RuntimeException)targetException;
+            }
+            else if(targetException instanceof Error)
+            {
+                throw (Error)targetException;
+            }
+            else
+            {
+                // This should never happen as it would imply a getter which is declaring a checked exception
+                throw new ServerScopedRuntimeException("Unable to get value for '"+getName()
+                                                       +"' from configured object of category "
+                                                       + configuredObject.getCategoryClass().getSimpleName(), e);
+            }
+        }
+
+    }
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedInjectedAttribute.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedMethodAttribute.java (from r1728496, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedAttribute.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedMethodAttribute.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedMethodAttribute.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedAttribute.java&r1=1728496&r2=1728497&rev=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedAttribute.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredDerivedMethodAttribute.java Thu Feb  4 15:38:05 2016
@@ -23,14 +23,14 @@ package org.apache.qpid.server.model;
 import java.lang.reflect.Method;
 import java.util.regex.Pattern;
 
-public class ConfiguredDerivedAttribute<C extends ConfiguredObject, T>  extends ConfiguredObjectAttribute<C,T>
+public class ConfiguredDerivedMethodAttribute<C extends ConfiguredObject, T>  extends ConfiguredObjectMethodAttribute<C,T>
 {
     private final DerivedAttribute _annotation;
     private final Pattern _secureValuePattern;
 
-    ConfiguredDerivedAttribute(final Class<C> clazz,
-                               final Method getter,
-                               final DerivedAttribute annotation)
+    ConfiguredDerivedMethodAttribute(final Class<C> clazz,
+                                     final Method getter,
+                                     final DerivedAttribute annotation)
     {
         super(clazz, getter);
         _annotation = annotation;

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,50 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.regex.Pattern;
+
+public interface ConfiguredObjectAttribute<C extends ConfiguredObject, T>  extends ConfiguredObjectAttributeOrStatistic<C,T>
+{
+
+    boolean isAutomated();
+
+    boolean isDerived();
+
+    boolean isSecure();
+
+    boolean isPersisted();
+
+    boolean isOversized();
+
+    boolean updateAttributeDespiteUnchangedValue();
+
+    String getOversizedAltText();
+
+    String getDescription();
+
+    Pattern getSecureValueFilter();
+
+    boolean isSecureValue(Object value);
+
+    T convert(Object value, C object);
+
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,36 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.lang.reflect.Type;
+
+public interface ConfiguredObjectAttributeOrStatistic<C extends ConfiguredObject, T>
+{
+    String getName();
+
+    Class<T> getType();
+
+    Type getGenericType();
+
+    T getValue(C configuredObject);
+
+    AttributeValueConverter<T> getConverter();
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttribute.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttribute.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttribute.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttribute.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,25 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public interface ConfiguredObjectInjectedAttribute<C extends ConfiguredObject, T> extends InjectedAttributeOrStatistic<C,T>, ConfiguredObjectAttribute<C,T>
+{
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttribute.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttributeOrStatistic.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttributeOrStatistic.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttributeOrStatistic.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttributeOrStatistic.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,100 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.lang.reflect.Type;
+
+abstract class ConfiguredObjectInjectedAttributeOrStatistic<C extends ConfiguredObject, T>
+        implements ConfiguredObjectAttributeOrStatistic<C,T>, InjectedAttributeOrStatistic<C, T>
+{
+
+    private final String _name;
+    private final Class<T> _type;
+    private final Type _genericType;
+    private final AttributeValueConverter<T> _converter;
+    private final TypeValidator _typeValidator;
+
+    ConfiguredObjectInjectedAttributeOrStatistic(String name,
+                                                 Class<T> type,
+                                                 Type genericType,
+                                                 final TypeValidator typeValidator)
+    {
+
+        _name = name;
+        _type = type;
+        _genericType = genericType;
+        _typeValidator = typeValidator;
+        _converter = AttributeValueConverter.getConverter(type, genericType);
+
+
+    }
+
+    @Override
+    public final String getName()
+    {
+        return _name;
+    }
+
+    @Override
+    public final Class<T> getType()
+    {
+        return _type;
+    }
+
+    @Override
+    public final Type getGenericType()
+    {
+        return _genericType;
+    }
+
+    @Override
+    public final AttributeValueConverter<T> getConverter()
+    {
+        return _converter;
+    }
+
+    @Override
+    public final boolean appliesToConfiguredObjectType(final Class<? extends ConfiguredObject<?>> type)
+    {
+        return _typeValidator.appliesToType(type);
+    }
+
+    public final T convert(final Object value, final C object)
+    {
+        final AttributeValueConverter<T> converter = getConverter();
+        try
+        {
+            return converter.convert(value, object);
+        }
+        catch (IllegalArgumentException iae)
+        {
+            Type returnType = getGenericType();
+            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);
+        }
+    }
+
+
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedAttributeOrStatistic.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,127 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
+
+final public class ConfiguredObjectInjectedStatistic<C extends ConfiguredObject, T extends Number>
+        extends ConfiguredObjectInjectedAttributeOrStatistic<C, T> implements ConfiguredObjectStatistic<C, T>
+{
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(ConfiguredObjectInjectedStatistic.class);
+
+    private final String _description;
+    private final Method _method;
+    private final StatisticUnit _units;
+    private final StatisticType _type;
+    private final String _label;
+
+    public ConfiguredObjectInjectedStatistic(final String name,
+                                      final Method method,
+                                      final String description,
+                                      final TypeValidator typeValidator,
+                                      final StatisticUnit units,
+                                      final StatisticType type,
+                                      final String label)
+    {
+        super(name,
+              (Class<T>) AttributeValueConverter.getTypeFromMethod(method), method.getGenericReturnType(), typeValidator);
+        _units = units;
+        _type = type;
+        _label = label;
+        if(!(method.getParameterTypes().length == 1
+             && ConfiguredObject.class.isAssignableFrom(method.getParameterTypes()[0])
+             && Modifier.isStatic(method.getModifiers())
+             && Number.class.isAssignableFrom(AttributeValueConverter.getTypeFromMethod(method))))
+        {
+            throw new IllegalArgumentException("Injected statistic method must be static, have a single argument which inherits from ConfiguredObject, and return a Number");
+        }
+        _method = method;
+        method.setAccessible(true);
+        _description = description;
+
+    }
+
+    public String getDescription()
+    {
+        return _description;
+    }
+
+    @Override
+    public StatisticUnit getUnits()
+    {
+        return _units;
+    }
+
+    @Override
+    public StatisticType getStatisticType()
+    {
+        return _type;
+    }
+
+    @Override
+    public String getLabel()
+    {
+        return _label;
+    }
+
+    @Override
+    public T getValue(final C configuredObject)
+    {
+        try
+        {
+            return (T) _method.invoke(null, configuredObject);
+        }
+        catch (IllegalAccessException e)
+        {
+            throw new ServerScopedRuntimeException("Unable to get value for '"+getName()
+                                                   +"' from configured object of category "
+                                                   + configuredObject.getCategoryClass().getSimpleName(), e);
+        }
+        catch (InvocationTargetException e)
+        {
+            Throwable targetException = e.getTargetException();
+            if(targetException instanceof RuntimeException)
+            {
+                throw (RuntimeException)targetException;
+            }
+            else if(targetException instanceof Error)
+            {
+                throw (Error)targetException;
+            }
+            else
+            {
+                // This should never happen as it would imply a getter which is declaring a checked exception
+                throw new ServerScopedRuntimeException("Unable to get value for '"+getName()
+                                                       +"' from configured object of category "
+                                                       + configuredObject.getCategoryClass().getSimpleName(), e);
+            }
+        }
+
+    }
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectInjectedStatistic.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttribute.java (from r1728382, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttribute.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttribute.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java&r1=1728382&r2=1728497&rev=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttribute.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttribute.java Thu Feb  4 15:38:05 2016
@@ -24,10 +24,12 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.util.regex.Pattern;
 
-public abstract class ConfiguredObjectAttribute<C extends ConfiguredObject, T> extends ConfiguredObjectAttributeOrStatistic<C,T>
+public abstract class ConfiguredObjectMethodAttribute<C extends ConfiguredObject, T>
+        extends  ConfiguredObjectMethodAttributeOrStatistic<C,T>
+        implements ConfiguredObjectAttribute<C,T>
 {
-    ConfiguredObjectAttribute(Class<C> clazz,
-                              final Method getter)
+    ConfiguredObjectMethodAttribute(Class<C> clazz,
+                                    final Method getter)
     {
         super(getter);
         if(getter.getParameterTypes().length != 0)
@@ -36,24 +38,7 @@ public abstract class ConfiguredObjectAt
         }
     }
 
-    public abstract boolean isAutomated();
-
-    public abstract boolean isDerived();
-
-    public abstract boolean isSecure();
-
-    public abstract boolean isPersisted();
-
-    public abstract boolean isOversized();
-
-    public abstract boolean updateAttributeDespiteUnchangedValue();
-
-    public abstract String getOversizedAltText();
-
-    public abstract String getDescription();
-
-    public abstract Pattern getSecureValueFilter();
-
+    @Override
     public boolean isSecureValue(Object value)
     {
         if (isSecure())
@@ -71,6 +56,7 @@ public abstract class ConfiguredObjectAt
         return false;
     }
 
+    @Override
     public T convert(final Object value, C object)
     {
         final AttributeValueConverter<T> converter = getConverter();

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttributeOrStatistic.java (from r1728382, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttributeOrStatistic.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttributeOrStatistic.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java&r1=1728382&r2=1728497&rev=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectAttributeOrStatistic.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodAttributeOrStatistic.java Thu Feb  4 15:38:05 2016
@@ -22,10 +22,12 @@ package org.apache.qpid.server.model;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Type;
 
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
 
-abstract class ConfiguredObjectAttributeOrStatistic<C extends ConfiguredObject, T>
+abstract class ConfiguredObjectMethodAttributeOrStatistic<C extends ConfiguredObject, T>
+        implements ConfiguredObjectAttributeOrStatistic<C,T>
 {
 
     private final String _name;
@@ -33,7 +35,7 @@ abstract class ConfiguredObjectAttribute
     private final AttributeValueConverter<T> _converter;
     private final Method _getter;
 
-    ConfiguredObjectAttributeOrStatistic(final Method getter)
+    ConfiguredObjectMethodAttributeOrStatistic(final Method getter)
     {
 
         _getter = getter;
@@ -43,16 +45,25 @@ abstract class ConfiguredObjectAttribute
 
     }
 
+    @Override
     public String getName()
     {
         return _name;
     }
 
+    @Override
     public Class<T> getType()
     {
         return _type;
     }
 
+    @Override
+    public Type getGenericType()
+    {
+        return getGetter().getGenericReturnType();
+    }
+
+    @Override
     public T getValue(C configuredObject)
     {
         try
@@ -93,6 +104,7 @@ abstract class ConfiguredObjectAttribute
         return _getter;
     }
 
+    @Override
     public AttributeValueConverter<T> getConverter()
     {
         return _converter;

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java (from r1728382, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java&r1=1728382&r2=1728497&rev=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectMethodStatistic.java Thu Feb  4 15:38:05 2016
@@ -22,12 +22,12 @@ package org.apache.qpid.server.model;
 
 import java.lang.reflect.Method;
 
-public final class ConfiguredObjectStatistic<C extends ConfiguredObject, T extends Number> extends
-                                                                                   ConfiguredObjectAttributeOrStatistic<C,T>
+public final class ConfiguredObjectMethodStatistic<C extends ConfiguredObject, T extends Number>
+        extends ConfiguredObjectMethodAttributeOrStatistic<C,T> implements ConfiguredObjectStatistic<C, T>
 {
     private final ManagedStatistic _annotation;
 
-    ConfiguredObjectStatistic(Class<C> clazz, final Method getter, final ManagedStatistic annotation)
+    ConfiguredObjectMethodStatistic(Class<C> clazz, final Method getter, final ManagedStatistic annotation)
     {
         super(getter);
         _annotation = annotation;
@@ -42,21 +42,25 @@ public final class ConfiguredObjectStati
         }
     }
 
+    @Override
     public String getDescription()
     {
         return _annotation.description();
     }
 
+    @Override
     public StatisticUnit getUnits()
     {
         return _annotation.units();
     }
 
+    @Override
     public StatisticType getStatisticType()
     {
         return _annotation.statisticType();
     }
 
+    @Override
     public String getLabel()
     {
         return _annotation.label();

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public interface ConfiguredObjectStatistic<C extends ConfiguredObject, T extends Number> extends ConfiguredObjectAttributeOrStatistic<C,T>
+{
+    String getDescription();
+
+    StatisticUnit getUnits();
+
+    StatisticType getStatisticType();
+
+    String getLabel();
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectStatistic.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java?rev=1728497&r1=1728496&r2=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java Thu Feb  4 15:38:05 2016
@@ -48,6 +48,7 @@ import com.google.common.util.concurrent
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.apache.qpid.server.plugin.ConfiguredObjectAttributeInjector;
 import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
 import org.apache.qpid.server.plugin.ConfiguredObjectTypeFactory;
 import org.apache.qpid.server.util.Action;
@@ -197,12 +198,15 @@ public class ConfiguredObjectTypeRegistr
             Collections.synchronizedMap(new HashMap<Class<? extends ConfiguredObject>, Map<String, Collection<String>>>());
 
     private final ConfiguredObjectFactory _objectFactory;
+    private final Iterable<ConfiguredObjectAttributeInjector> _attributeInjectors;
 
     public ConfiguredObjectTypeRegistry(Iterable<ConfiguredObjectRegistration> configuredObjectRegistrations,
+                                        final Iterable<ConfiguredObjectAttributeInjector> attributeInjectors,
                                         Collection<Class<? extends ConfiguredObject>> categoriesRestriction,
                                         final ConfiguredObjectFactory objectFactory)
     {
         _objectFactory = objectFactory;
+        _attributeInjectors = attributeInjectors;
         Set<Class<? extends ConfiguredObject>> categories = new HashSet<>();
         Set<Class<? extends ConfiguredObject>> types = new HashSet<>();
 
@@ -671,6 +675,24 @@ public class ConfiguredObjectTypeRegistr
         {
             processMethod(clazz, attributeSet, statisticSet, operationsSet, method);
         }
+
+        for(ConfiguredObjectAttributeInjector injector : _attributeInjectors)
+        {
+            for(ConfiguredObjectInjectedAttribute<?,?> attr : injector.getInjectedAttributes())
+            {
+                if(attr.appliesToConfiguredObjectType((Class<? extends ConfiguredObject<?>>) clazz))
+                {
+                    attributeSet.add(attr);
+                }
+            }
+            for(ConfiguredObjectInjectedStatistic<?,?> attr : injector.getInjectedStatistics())
+            {
+                if(attr.appliesToConfiguredObjectType((Class<? extends ConfiguredObject<?>>) clazz))
+                {
+                    statisticSet.add(attr);
+                }
+            }
+        }
     }
 
     private <X extends ConfiguredObject> void processMethod(final Class<X> clazz,
@@ -707,7 +729,7 @@ public class ConfiguredObjectTypeRegistr
         {
             throw new ServerScopedRuntimeException("Can only define ManagedStatistics on interfaces which extend " + ConfiguredObject.class.getSimpleName() + ". " + clazz.getSimpleName() + " does not meet these criteria.");
         }
-        ConfiguredObjectStatistic statistic = new ConfiguredObjectStatistic(clazz, m, statAnnotation);
+        ConfiguredObjectStatistic statistic = new ConfiguredObjectMethodStatistic(clazz, m, statAnnotation);
         if(statisticSet.contains(statistic))
         {
             statisticSet.remove(statistic);
@@ -726,7 +748,7 @@ public class ConfiguredObjectTypeRegistr
             throw new ServerScopedRuntimeException("Can only define DerivedAttributes on interfaces which extend " + ConfiguredObject.class.getSimpleName() + ". " + clazz.getSimpleName() + " does not meet these criteria.");
         }
 
-        ConfiguredObjectAttribute<?,?> attribute = new ConfiguredDerivedAttribute<>(clazz, m, annotation);
+        ConfiguredObjectAttribute<?,?> attribute = new ConfiguredDerivedMethodAttribute<>(clazz, m, annotation);
         if(attributeSet.contains(attribute))
         {
             attributeSet.remove(attribute);
@@ -812,6 +834,16 @@ public class ConfiguredObjectTypeRegistr
             }
 
         }
+        for(ConfiguredObjectAttributeInjector injector : _attributeInjectors)
+        {
+            for(ConfiguredObjectInjectedAttribute<?,?> attr : injector.getInjectedAttributes())
+            {
+                if(!attrMap.containsKey(attr.getName()) && attr.appliesToConfiguredObjectType((Class<? extends ConfiguredObject<?>>) clazz))
+                {
+                    attrMap.put(attr.getName(), attr);
+                }
+            }
+        }
         _allAttributeTypes.put(clazz, attrMap);
         _allAutomatedFields.put(clazz, fieldMap);
     }

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableAttribute.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableAttribute.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableAttribute.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableAttribute.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,36 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+import java.util.Collection;
+
+public interface ConfiguredSettableAttribute<C extends ConfiguredObject, T> extends ConfiguredObjectAttribute<C,T>
+{
+    String defaultValue();
+
+    boolean isMandatory();
+
+    boolean isImmutable();
+
+    Collection<String> validValues();
+
+    boolean hasValidValues();
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableAttribute.java
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableInjectedAttribute.java (from r1728382, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableInjectedAttribute.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableInjectedAttribute.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java&r1=1728382&r2=1728497&rev=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredAutomatedAttribute.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredSettableInjectedAttribute.java Thu Feb  4 15:38:05 2016
@@ -33,31 +33,58 @@ import java.util.regex.Pattern;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class ConfiguredAutomatedAttribute<C extends ConfiguredObject, T>  extends ConfiguredObjectAttribute<C,T>
+public class ConfiguredSettableInjectedAttribute<C extends ConfiguredObject, T>
+        extends ConfiguredObjectInjectedAttributeOrStatistic<C,T> implements ConfiguredSettableAttribute<C,T>, ConfiguredObjectInjectedAttribute<C,T>
 {
-    private static final Logger LOGGER = LoggerFactory.getLogger(ConfiguredAutomatedAttribute.class);
 
-    private final ManagedAttribute _annotation;
+    private static final Logger LOGGER = LoggerFactory.getLogger(ConfiguredSettableInjectedAttribute.class);
+
     private final Method _validValuesMethod;
     private final Pattern _secureValuePattern;
+    private final String _defaultValue;
+    private final boolean _secure;
+    private final boolean _persisted;
+    private final boolean _immutable;
+    private final boolean _oversized;
+    private final String _oversizedAltText;
+    private final String _description;
+    private final String[] _validValues;
+
+    public ConfiguredSettableInjectedAttribute(final String name,
+                                        final Class<T> type,
+                                        final Type genericType,
+                                        final String defaultValue,
+                                        final boolean secure,
+                                        final boolean persisted,
+                                        final boolean immutable,
+                                        final String secureValueFilter,
+                                        final boolean oversized,
+                                        final String oversizedAltText,
+                                        final String description,
+                                        final String[] validValues,
+                                        final TypeValidator typeValidator)
+    {
+        super(name, type, genericType, typeValidator);
+
+        _defaultValue = defaultValue;
+        _secure = secure;
+        _persisted = persisted;
+        _immutable = immutable;
+        _oversized = oversized;
+        _oversizedAltText = oversizedAltText;
+        _description = description;
+        _validValues = validValues;
 
-    ConfiguredAutomatedAttribute(final Class<C> clazz,
-                                 final Method getter,
-                                 final ManagedAttribute annotation)
-    {
-        super(clazz, getter);
-        _annotation = annotation;
         Method validValuesMethod = null;
 
-        if(_annotation.validValues().length == 1)
+        if(_validValues != null && _validValues.length == 1)
         {
-            String validValue = _annotation.validValues()[0];
+            String validValue = _validValues[0];
 
-            validValuesMethod = getValidValuesMethod(validValue, clazz);
+            validValuesMethod = getValidValuesMethod(validValue);
         }
         _validValuesMethod = validValuesMethod;
 
-        String secureValueFilter = _annotation.secureValueFilter();
         if (secureValueFilter == null || "".equals(secureValueFilter))
         {
             _secureValuePattern = null;
@@ -68,15 +95,14 @@ public class ConfiguredAutomatedAttribut
         }
     }
 
-    private Method getValidValuesMethod(final String validValue, final Class<C> clazz)
+    private Method getValidValuesMethod(final String validValue)
     {
         if(validValue.matches("([\\w][\\w\\d_]+\\.)+[\\w][\\w\\d_\\$]*#[\\w\\d_]+\\s*\\(\\s*\\)"))
         {
-            String function = validValue;
             try
             {
-                String className = function.split("#")[0].trim();
-                String methodName = function.split("#")[1].split("\\(")[0].trim();
+                String className = validValue.split("#")[0].trim();
+                String methodName = validValue.split("#")[1].split("\\(")[0].trim();
                 Class<?> validValueCalculatingClass = Class.forName(className);
                 Method method = validValueCalculatingClass.getMethod(methodName);
                 if (Modifier.isStatic(method.getModifiers()) && Modifier.isPublic(method.getModifiers()))
@@ -98,7 +124,7 @@ public class ConfiguredAutomatedAttribut
             }
             catch (ClassNotFoundException | NoSuchMethodException e)
             {
-                LOGGER.warn("The validValues of the " + getName() + " attribute in class " + clazz.getSimpleName()
+                LOGGER.warn("The validValues of the " + getName()
                             + " has value '" + validValue + "' which looks like it should be a method,"
                             + " but no such method could be used.", e );
             }
@@ -108,7 +134,7 @@ public class ConfiguredAutomatedAttribut
 
     public boolean isAutomated()
     {
-        return true;
+        return false;
     }
 
     public boolean isDerived()
@@ -118,50 +144,50 @@ public class ConfiguredAutomatedAttribut
 
     public String defaultValue()
     {
-        return _annotation.defaultValue();
+        return _defaultValue;
     }
 
     public boolean isSecure()
     {
-        return _annotation.secure();
+        return _secure;
     }
 
     public boolean isMandatory()
     {
-        return _annotation.mandatory();
+        return false;
     }
 
     public boolean isImmutable()
     {
-        return _annotation.immutable();
+        return _immutable;
     }
 
     public boolean isPersisted()
     {
-        return _annotation.persist();
+        return _persisted;
     }
 
     @Override
     public boolean isOversized()
     {
-        return _annotation.oversize();
+        return _oversized;
     }
 
     @Override
     public boolean updateAttributeDespiteUnchangedValue()
     {
-        return _annotation.updateAttributeDespiteUnchangedValue();
+        return false;
     }
 
     @Override
     public String getOversizedAltText()
     {
-        return _annotation.oversizedAltText();
+        return _oversizedAltText;
     }
 
     public String getDescription()
     {
-        return _annotation.description();
+        return _description;
     }
 
     public Pattern getSecureValueFilter()
@@ -169,6 +195,14 @@ public class ConfiguredAutomatedAttribut
         return _secureValuePattern;
     }
 
+    @Override
+    public boolean isSecureValue(final Object value)
+    {
+        Pattern filter;
+        return isSecure() &&
+               ((filter = getSecureValueFilter()) == null || filter.matcher(String.valueOf(value)).matches());
+    }
+
     public Collection<String> validValues()
     {
         if(_validValuesMethod != null)
@@ -185,7 +219,7 @@ public class ConfiguredAutomatedAttribut
         }
         else
         {
-            return Arrays.asList(_annotation.validValues());
+            return _validValues == null ? Collections.<String>emptySet() : Arrays.asList(_validValues);
         }
     }
 
@@ -194,4 +228,16 @@ public class ConfiguredAutomatedAttribut
     {
         return validValues() != null && validValues().size() > 0;
     }
+
+    @Override
+    public final T getValue(final C configuredObject)
+    {
+        Object value = configuredObject.getActualAttributes().get(getName());
+        if(value == null)
+        {
+            value = defaultValue();
+        }
+        return convert(value, configuredObject);
+    }
+
 }

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/InjectedAttributeOrStatistic.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/InjectedAttributeOrStatistic.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/InjectedAttributeOrStatistic.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/InjectedAttributeOrStatistic.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,31 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model;
+
+public interface InjectedAttributeOrStatistic<C extends ConfiguredObject, T> extends ConfiguredObjectAttributeOrStatistic<C, T>
+{
+    boolean appliesToConfiguredObjectType(Class<? extends ConfiguredObject<?>> type);
+
+    interface TypeValidator
+    {
+        boolean appliesToType(Class<? extends ConfiguredObject<?>> type);
+    }
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/InjectedAttributeOrStatistic.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectAttributeInjector.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectAttributeInjector.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectAttributeInjector.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectAttributeInjector.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.plugin;
+
+import java.util.Collection;
+
+import org.apache.qpid.server.model.ConfiguredObjectInjectedAttribute;
+import org.apache.qpid.server.model.ConfiguredObjectInjectedStatistic;
+
+public interface ConfiguredObjectAttributeInjector extends Pluggable
+{
+    Collection<ConfiguredObjectInjectedAttribute<?,?>> getInjectedAttributes();
+    Collection<ConfiguredObjectInjectedStatistic<?,?>> getInjectedStatistics();
+}

Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/plugin/ConfiguredObjectAttributeInjector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java?rev=1728497&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java (added)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java Thu Feb  4 15:38:05 2016
@@ -0,0 +1,250 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.model.testmodels.hierarchy;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.security.AccessControlException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.TaskExecutor;
+import org.apache.qpid.server.model.*;
+import org.apache.qpid.server.plugin.ConfiguredObjectAttributeInjector;
+import org.apache.qpid.server.store.ConfiguredObjectRecord;
+import org.apache.qpid.test.utils.QpidTestCase;
+
+public class InjectedAttributeTest extends QpidTestCase
+{
+
+    private static class TestInjector implements ConfiguredObjectAttributeInjector
+    {
+
+        private Collection<ConfiguredObjectInjectedAttribute<?, ?>> _injectedAttributes;
+        private Collection<ConfiguredObjectInjectedStatistic<?, ?>> _injectedStatistics;
+
+        private TestInjector(final Collection<ConfiguredObjectInjectedAttribute<?, ?>> injectedAttributes,
+                             final Collection<ConfiguredObjectInjectedStatistic<?, ?>> injectedStatistics)
+        {
+            _injectedAttributes = injectedAttributes;
+            _injectedStatistics = injectedStatistics;
+        }
+
+        @Override
+        public Collection<ConfiguredObjectInjectedAttribute<?, ?>> getInjectedAttributes()
+        {
+            return _injectedAttributes;
+        }
+
+        @Override
+        public Collection<ConfiguredObjectInjectedStatistic<?, ?>> getInjectedStatistics()
+        {
+            return _injectedStatistics;
+        }
+
+        @Override
+        public String getType()
+        {
+            return "TEST";
+        }
+    }
+
+    public void testInjectedSettableAttributeWithDefault()
+    {
+        InjectedAttributeOrStatistic.TypeValidator validator =
+                new InjectedAttributeOrStatistic.TypeValidator()
+                {
+                    @Override
+                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
+                    {
+                        return TestCar.class.isAssignableFrom(type);
+                    }
+                };
+
+        final ConfiguredSettableInjectedAttribute<?, ?> attrInjector =
+                new ConfiguredSettableInjectedAttribute<TestCar<?>, Integer>("meaningOfLife",
+                                                                             Integer.class,
+                                                                             Integer.class,
+                                                                             "42",
+                                                                             false,
+                                                                             true,
+                                                                             false,
+                                                                             "",
+                                                                             false,
+                                                                             "",
+                                                                             "",
+                                                                             null,
+                                                                             validator);
+
+        TestModel model = new TestModel(null, Collections.<ConfiguredObjectAttributeInjector>singleton(new TestInjector(Collections.<ConfiguredObjectInjectedAttribute<?, ?>>singletonList(
+                attrInjector), Collections.<ConfiguredObjectInjectedStatistic<?, ?>>emptySet())));
+
+        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);
+
+        assertEquals("incorrect attribute value", Integer.valueOf(42), testCar.getAttribute("meaningOfLife"));
+
+        testCar.setAttributes(Collections.<String,Object>singletonMap("meaningOfLife", 54));
+
+        assertEquals("incorrect attribute value", Integer.valueOf(54), testCar.getAttribute("meaningOfLife"));
+
+        Map<String, String> context = new HashMap<>(testCar.getContext());
+        context.put("varieties","57");
+        testCar.setAttributes(Collections.<String,Object>singletonMap("context", context));
+        testCar.setAttributes(Collections.<String,Object>singletonMap("meaningOfLife", "${varieties}"));
+
+        assertEquals("incorrect attribute value", Integer.valueOf(57), testCar.getAttribute("meaningOfLife"));
+
+    }
+
+
+    public void testInjectedSettableAttributeValidValues()
+    {
+
+        InjectedAttributeOrStatistic.TypeValidator validator =
+                new InjectedAttributeOrStatistic.TypeValidator()
+                {
+                    @Override
+                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
+                    {
+                        return TestCar.class.isAssignableFrom(type);
+                    }
+                };
+
+        final ConfiguredSettableInjectedAttribute<?, ?> attrInjector =
+                new ConfiguredSettableInjectedAttribute<TestCar<?>, Integer>("meaningOfLife",
+                                                                             Integer.class,
+                                                                             Integer.class,
+                                                                             "42",
+                                                                             false,
+                                                                             true,
+                                                                             false,
+                                                                             "",
+                                                                             false,
+                                                                             "",
+                                                                             "",
+                                                                             new String[] { "42", "49" },
+                                                                             validator);
+
+        TestModel model = new TestModel(null, Collections.<ConfiguredObjectAttributeInjector>singleton(new TestInjector(Collections.<ConfiguredObjectInjectedAttribute<?, ?>>singletonList(
+                attrInjector), Collections.<ConfiguredObjectInjectedStatistic<?, ?>>emptySet())));
+
+        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);
+
+        assertEquals("incorrect attribute value", Integer.valueOf(42), testCar.getAttribute("meaningOfLife"));
+
+        testCar.setAttributes(Collections.<String,Object>singletonMap("meaningOfLife", 49));
+
+
+        assertEquals("incorrect attribute value", Integer.valueOf(49), testCar.getAttribute("meaningOfLife"));
+
+        try
+        {
+            testCar.setAttributes(Collections.<String, Object>singletonMap("meaningOfLife", 54));
+            fail("Should not be able to set attribute value to 54 as it is not a valid value");
+        }
+        catch (IllegalConfigurationException e)
+        {
+            // pass
+        }
+
+
+    }
+
+    public void testInjectedDerivedAttribute() throws Exception
+    {
+        Method method = InjectedAttributeTest.class.getDeclaredMethod("getMeaningOfLife", TestCar.class);
+        InjectedAttributeOrStatistic.TypeValidator validator =
+                new InjectedAttributeOrStatistic.TypeValidator()
+                {
+                    @Override
+                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
+                    {
+                        return TestCar.class.isAssignableFrom(type);
+                    }
+                };
+
+        final ConfiguredDerivedInjectedAttribute<?, ?> attrInjector =
+                new ConfiguredDerivedInjectedAttribute<TestCar<?>, Integer>("meaningOfLife",
+                                                                            method,
+                                                                            false,
+                                                                            false,
+                                                                            "",
+                                                                            false,
+                                                                            "",
+                                                                            "",
+                                                                            validator);
+
+        TestModel model = new TestModel(null, Collections.<ConfiguredObjectAttributeInjector>singleton(new TestInjector(Collections.<ConfiguredObjectInjectedAttribute<?, ?>>singletonList(
+                attrInjector), Collections.<ConfiguredObjectInjectedStatistic<?, ?>>emptySet())));
+
+        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);
+
+
+        assertEquals("incorrect attribute value", Integer.valueOf(42), testCar.getAttribute("meaningOfLife"));
+
+    }
+
+
+    public void testInjectedStatistic() throws Exception
+    {
+
+        Method method = InjectedAttributeTest.class.getDeclaredMethod("getMeaningOfLife", TestCar.class);
+        InjectedAttributeOrStatistic.TypeValidator validator =
+                new InjectedAttributeOrStatistic.TypeValidator()
+                {
+                    @Override
+                    public boolean appliesToType(final Class<? extends ConfiguredObject<?>> type)
+                    {
+                        return TestCar.class.isAssignableFrom(type);
+                    }
+                };
+
+        final ConfiguredObjectInjectedStatistic<?, ?> statInjector =
+                new ConfiguredObjectInjectedStatistic<TestCar<?>, Integer>("meaningOfLife",
+                                                                           method,
+                                                                           "",
+                                                                           validator,
+                                                                           StatisticUnit.COUNT,
+                                                                           StatisticType.POINT_IN_TIME,
+                                                                           "What is 6 x 9?");
+
+        TestModel model = new TestModel(null, Collections.<ConfiguredObjectAttributeInjector>singleton(new TestInjector(Collections.<ConfiguredObjectInjectedAttribute<?, ?>>emptyList(), Collections.<ConfiguredObjectInjectedStatistic<?, ?>>singletonList(statInjector))));
+
+        TestCar<?> testCar = new TestStandardCarImpl(Collections.<String,Object>singletonMap("name", "Arthur"), model);
+
+        final Map<String, Number> statistics = testCar.getStatistics();
+        assertEquals("incorrect number of statistics", 1, statistics.size());
+        assertEquals("incorrect statistic value", 42, statistics.get("meaningOfLife"));
+    }
+
+
+    public static int getMeaningOfLife(TestCar<?> car)
+    {
+        return 42;
+    }
+}

Propchange: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/InjectedAttributeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestModel.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestModel.java?rev=1728497&r1=1728496&r2=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestModel.java (original)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestModel.java Thu Feb  4 15:38:05 2016
@@ -23,12 +23,14 @@ package org.apache.qpid.server.model.tes
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Set;
 
 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.ConfiguredObjectTypeRegistry;
 import org.apache.qpid.server.model.Model;
+import org.apache.qpid.server.plugin.ConfiguredObjectAttributeInjector;
 import org.apache.qpid.server.plugin.ConfiguredObjectRegistration;
 
 public class TestModel extends Model
@@ -50,11 +52,17 @@ public class TestModel extends Model
 
     public TestModel(final ConfiguredObjectFactory objectFactory)
     {
+        this(objectFactory, Collections.<ConfiguredObjectAttributeInjector>emptySet());
+    }
+    public TestModel(final ConfiguredObjectFactory objectFactory, Set<ConfiguredObjectAttributeInjector> attributeInjectors)
+    {
         _objectFactory = objectFactory == null ? new ConfiguredObjectFactoryImpl(this) : objectFactory;
 
         ConfiguredObjectRegistration configuredObjectRegistration = new ConfiguredObjectRegistrationImpl();
 
-        _registry = new ConfiguredObjectTypeRegistry(Collections.singletonList(configuredObjectRegistration), Collections.EMPTY_LIST, _objectFactory);
+        _registry = new ConfiguredObjectTypeRegistry(Collections.singletonList(configuredObjectRegistration),
+                                                     attributeInjectors,
+                                                     Collections.EMPTY_LIST, _objectFactory);
     }
 
 

Modified: qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java?rev=1728497&r1=1728496&r2=1728497&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java (original)
+++ qpid/java/trunk/broker-core/src/test/java/org/apache/qpid/server/model/testmodels/hierarchy/TestStandardCarImpl.java Thu Feb  4 15:38:05 2016
@@ -51,6 +51,13 @@ public class TestStandardCarImpl extends
         _securityManager = new TestSecurityManager(this);
     }
 
+    public TestStandardCarImpl(final Map<String, Object> attributes, TestModel model)
+    {
+        super(parentsMap(), attributes, newTaskExecutor(), model);
+        _securityManager = new TestSecurityManager(this);
+    }
+
+
     private static CurrentThreadTaskExecutor newTaskExecutor()
     {
         CurrentThreadTaskExecutor currentThreadTaskExecutor = new CurrentThreadTaskExecutor();




---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org