ARTEMIS-4256 - support removal of configuration via properties
This commit is contained in:
parent
cf3afc4096
commit
c5d872575e
|
@ -569,8 +569,12 @@ public final class ActiveMQDefaultConfiguration {
|
||||||
|
|
||||||
public static final String BROKER_PROPERTIES_KEY_SURROUND = "\"";
|
public static final String BROKER_PROPERTIES_KEY_SURROUND = "\"";
|
||||||
|
|
||||||
|
public static final String BROKER_PROPERTIES_REMOVE_VALUE = "-";
|
||||||
|
|
||||||
public static final String BROKER_PROPERTIES_KEY_SURROUND_PROPERTY = "key.surround";
|
public static final String BROKER_PROPERTIES_KEY_SURROUND_PROPERTY = "key.surround";
|
||||||
|
|
||||||
|
public static final String BROKER_PROPERTIES_REMOVE_VALUE_PROPERTY = "remove.value";
|
||||||
|
|
||||||
public static String DEFAULT_NETWORK_CHECK_LIST = null;
|
public static String DEFAULT_NETWORK_CHECK_LIST = null;
|
||||||
|
|
||||||
public static String DEFAULT_NETWORK_CHECK_URL_LIST = null;
|
public static String DEFAULT_NETWORK_CHECK_URL_LIST = null;
|
||||||
|
@ -1625,6 +1629,10 @@ public final class ActiveMQDefaultConfiguration {
|
||||||
return BROKER_PROPERTIES_KEY_SURROUND;
|
return BROKER_PROPERTIES_KEY_SURROUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getDefaultBrokerPropertiesRemoveValue() {
|
||||||
|
return BROKER_PROPERTIES_REMOVE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
public static String getDefaultNetworkCheckList() {
|
public static String getDefaultNetworkCheckList() {
|
||||||
return DEFAULT_NETWORK_CHECK_LIST;
|
return DEFAULT_NETWORK_CHECK_LIST;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,7 @@ import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -379,6 +380,8 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
||||||
|
|
||||||
private String brokerPropertiesKeySurround = ActiveMQDefaultConfiguration.getDefaultBrokerPropertiesKeySurround();
|
private String brokerPropertiesKeySurround = ActiveMQDefaultConfiguration.getDefaultBrokerPropertiesKeySurround();
|
||||||
|
|
||||||
|
private String brokerPropertiesRemoveValue = ActiveMQDefaultConfiguration.getDefaultBrokerPropertiesRemoveValue();
|
||||||
|
|
||||||
private String networkCheckList = ActiveMQDefaultConfiguration.getDefaultNetworkCheckList();
|
private String networkCheckList = ActiveMQDefaultConfiguration.getDefaultNetworkCheckList();
|
||||||
|
|
||||||
private String networkURLList = ActiveMQDefaultConfiguration.getDefaultNetworkCheckURLList();
|
private String networkURLList = ActiveMQDefaultConfiguration.getDefaultNetworkCheckURLList();
|
||||||
|
@ -502,6 +505,14 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
||||||
this.brokerPropertiesKeySurround = brokerPropertiesKeySurround;
|
this.brokerPropertiesKeySurround = brokerPropertiesKeySurround;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getBrokerPropertiesRemoveValue() {
|
||||||
|
return brokerPropertiesRemoveValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBrokerPropertiesRemoveValue(String brokerPropertiesRemoveValue) {
|
||||||
|
this.brokerPropertiesRemoveValue = brokerPropertiesRemoveValue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Configuration parseProperties(String fileUrlToProperties) throws Exception {
|
public Configuration parseProperties(String fileUrlToProperties) throws Exception {
|
||||||
// system property overrides location of file(s)
|
// system property overrides location of file(s)
|
||||||
|
@ -588,7 +599,7 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void populateWithProperties(final Object target, final String propsId, Map<String, Object> beanProperties) throws InvocationTargetException, IllegalAccessException {
|
public void populateWithProperties(final Object target, final String propsId, Map<String, Object> beanProperties) throws InvocationTargetException, IllegalAccessException {
|
||||||
CollectionAutoFillPropertiesUtil autoFillCollections = new CollectionAutoFillPropertiesUtil();
|
CollectionAutoFillPropertiesUtil autoFillCollections = new CollectionAutoFillPropertiesUtil(getBrokerPropertiesRemoveValue(beanProperties));
|
||||||
BeanUtilsBean beanUtils = new BeanUtilsBean(new ConvertUtilsBean(), autoFillCollections) {
|
BeanUtilsBean beanUtils = new BeanUtilsBean(new ConvertUtilsBean(), autoFillCollections) {
|
||||||
// override to treat missing properties as errors, not skip as the default impl does
|
// override to treat missing properties as errors, not skip as the default impl does
|
||||||
@Override
|
@Override
|
||||||
|
@ -613,8 +624,38 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
||||||
}
|
}
|
||||||
logger.trace("resolved target, bean: {}, name: {}", target.getClass(), name);
|
logger.trace("resolved target, bean: {}, name: {}", target.getClass(), name);
|
||||||
|
|
||||||
// Declare local variables we will require
|
|
||||||
final String propName = resolver.getProperty(name); // Simple name of target property
|
final String propName = resolver.getProperty(name); // Simple name of target property
|
||||||
|
if (autoFillCollections.isRemoveValue(value)) {
|
||||||
|
logger.trace("removing from target, bean: {}, name: {}", target.getClass(), name);
|
||||||
|
|
||||||
|
// we may do a further get but no longer want to reference our nested collection stack
|
||||||
|
if (!autoFillCollections.collections.isEmpty()) {
|
||||||
|
autoFillCollections.collections.pop();
|
||||||
|
}
|
||||||
|
if (target instanceof Map) {
|
||||||
|
Map targetMap = (Map) target;
|
||||||
|
Iterator<Map.Entry<String, Object>> i = targetMap.entrySet().iterator();
|
||||||
|
while (i.hasNext()) {
|
||||||
|
String key = i.next().getKey();
|
||||||
|
if (propName.equals(key)) {
|
||||||
|
i.remove();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (target instanceof Collection) {
|
||||||
|
try {
|
||||||
|
autoFillCollections.removeByNameProperty(propName, (Collection) target);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
throw new InvocationTargetException(e, "Can only remove named entries from collections or maps" + name + ", on: " + target);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new InvocationTargetException(null, "Can only remove entries from collections or maps" + name + ", on: " + target);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.trace("removed from target, bean: {}, name: {}", target.getClass(), name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Class<?> type = null; // Java type of target property
|
Class<?> type = null; // Java type of target property
|
||||||
final int index = resolver.getIndex(name); // Indexed subscript value (if any)
|
final int index = resolver.getIndex(name); // Indexed subscript value (if any)
|
||||||
final String key = resolver.getKey(name); // Mapped key value (if any)
|
final String key = resolver.getKey(name); // Mapped key value (if any)
|
||||||
|
@ -814,12 +855,20 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
||||||
|
|
||||||
private String getBrokerPropertiesKeySurround(Map<String, Object> propertiesToApply) {
|
private String getBrokerPropertiesKeySurround(Map<String, Object> propertiesToApply) {
|
||||||
if (propertiesToApply.containsKey(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_KEY_SURROUND_PROPERTY)) {
|
if (propertiesToApply.containsKey(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_KEY_SURROUND_PROPERTY)) {
|
||||||
return String.valueOf(propertiesToApply.get(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_KEY_SURROUND_PROPERTY));
|
return String.valueOf(propertiesToApply.remove(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_KEY_SURROUND_PROPERTY));
|
||||||
} else {
|
} else {
|
||||||
return System.getProperty(getSystemPropertyPrefix() + ActiveMQDefaultConfiguration.BROKER_PROPERTIES_KEY_SURROUND_PROPERTY, getBrokerPropertiesKeySurround());
|
return System.getProperty(getSystemPropertyPrefix() + ActiveMQDefaultConfiguration.BROKER_PROPERTIES_KEY_SURROUND_PROPERTY, getBrokerPropertiesKeySurround());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getBrokerPropertiesRemoveValue(Map<String, Object> propertiesToApply) {
|
||||||
|
if (propertiesToApply.containsKey(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_REMOVE_VALUE_PROPERTY)) {
|
||||||
|
return String.valueOf(propertiesToApply.remove(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_REMOVE_VALUE_PROPERTY));
|
||||||
|
} else {
|
||||||
|
return System.getProperty(getSystemPropertyPrefix() + ActiveMQDefaultConfiguration.BROKER_PROPERTIES_REMOVE_VALUE_PROPERTY, getBrokerPropertiesRemoveValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isClustered() {
|
public boolean isClustered() {
|
||||||
return !getClusterConfigurations().isEmpty();
|
return !getClusterConfigurations().isEmpty();
|
||||||
|
@ -3077,8 +3126,13 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
||||||
|
|
||||||
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[]{};
|
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[]{};
|
||||||
final Stack<Pair<String, Object>> collections = new Stack<>();
|
final Stack<Pair<String, Object>> collections = new Stack<>();
|
||||||
|
final String removeValue;
|
||||||
private BeanUtilsBean beanUtilsBean;
|
private BeanUtilsBean beanUtilsBean;
|
||||||
|
|
||||||
|
CollectionAutoFillPropertiesUtil(String brokerPropertiesRemoveValue) {
|
||||||
|
this.removeValue = brokerPropertiesRemoveValue;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setProperty(final Object bean, final String name, final Object value) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
|
public void setProperty(final Object bean, final String name, final Object value) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
|
||||||
// any set will invalidate our collections stack
|
// any set will invalidate our collections stack
|
||||||
|
@ -3144,6 +3198,18 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object removeByNameProperty(String key, Collection collection) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
|
||||||
|
// locate on name property, may be a SimpleString
|
||||||
|
for (Object candidate : collection) {
|
||||||
|
Object candidateName = getProperty(candidate, "name");
|
||||||
|
if (candidateName != null && key.equals(candidateName.toString())) {
|
||||||
|
collection.remove(candidate);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// allow finding beans in collections via name() such that a mapped key (key)
|
// allow finding beans in collections via name() such that a mapped key (key)
|
||||||
// can be used to access and *not* auto create entries
|
// can be used to access and *not* auto create entries
|
||||||
@Override
|
@Override
|
||||||
|
@ -3257,6 +3323,10 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
||||||
// we want type conversion
|
// we want type conversion
|
||||||
this.beanUtilsBean = beanUtilsBean;
|
this.beanUtilsBean = beanUtilsBean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRemoveValue(Object value) {
|
||||||
|
return removeValue != null && removeValue.equals(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SurroundResolver extends DefaultResolver {
|
private static class SurroundResolver extends DefaultResolver {
|
||||||
|
|
|
@ -967,6 +967,46 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
|
||||||
Assert.assertEquals(false, configuration.getAddressConfigurations().get(0).getQueueConfigs().get(0).isDurable());
|
Assert.assertEquals(false, configuration.getAddressConfigurations().get(0).getQueueConfigs().get(0).isDurable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddressRemovalViaProperties() throws Throwable {
|
||||||
|
ConfigurationImpl configuration = new ConfigurationImpl();
|
||||||
|
|
||||||
|
Properties properties = new Properties();
|
||||||
|
|
||||||
|
properties.put("addressConfigurations.\"LB.TEST\".queueConfigs.\"LB.TEST\".routingType", "ANYCAST");
|
||||||
|
configuration.parsePrefixedProperties(properties, null);
|
||||||
|
|
||||||
|
Assert.assertEquals(1, configuration.getAddressConfigurations().size());
|
||||||
|
Assert.assertEquals(1, configuration.getAddressConfigurations().get(0).getQueueConfigs().size());
|
||||||
|
Assert.assertTrue(configuration.getStatus().contains("\"errors\":[]"));
|
||||||
|
|
||||||
|
properties.clear();
|
||||||
|
properties.put("addressConfigurations.\"LB.TEST\"", "-");
|
||||||
|
configuration.parsePrefixedProperties(properties, null);
|
||||||
|
|
||||||
|
Assert.assertEquals(0, configuration.getAddressConfigurations().size());
|
||||||
|
Assert.assertTrue(configuration.getStatus().contains("\"errors\":[]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRoleRemovalViaCustomRemoveProperties() throws Throwable {
|
||||||
|
ConfigurationImpl configuration = new ConfigurationImpl();
|
||||||
|
|
||||||
|
Properties properties = new Properties();
|
||||||
|
|
||||||
|
properties.put("securityRoles.TEST.users.send", "true");
|
||||||
|
configuration.parsePrefixedProperties(properties, null);
|
||||||
|
Assert.assertEquals(1, configuration.getSecurityRoles().size());
|
||||||
|
Assert.assertTrue(configuration.getStatus().contains("\"errors\":[]"));
|
||||||
|
|
||||||
|
properties.clear();
|
||||||
|
properties.put(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_REMOVE_VALUE_PROPERTY, "^");
|
||||||
|
properties.put("securityRoles.TEST", "^");
|
||||||
|
configuration.parsePrefixedProperties(properties, null);
|
||||||
|
Assert.assertEquals(0, configuration.getSecurityRoles().size());
|
||||||
|
Assert.assertTrue(configuration.getStatus().contains("\"errors\":[]"));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIDCacheSizeViaProperties() throws Throwable {
|
public void testIDCacheSizeViaProperties() throws Throwable {
|
||||||
ConfigurationImpl configuration = new ConfigurationImpl();
|
ConfigurationImpl configuration = new ConfigurationImpl();
|
||||||
|
@ -1639,6 +1679,8 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
|
||||||
Assert.assertEquals(SimpleString.toSimpleString("sharedExpiry"), configuration.getAddressSettings().get("#").getExpiryAddress());
|
Assert.assertEquals(SimpleString.toSimpleString("sharedExpiry"), configuration.getAddressSettings().get("#").getExpiryAddress());
|
||||||
Assert.assertEquals(SimpleString.toSimpleString("important"), configuration.getAddressSettings().get("NeedToTrackExpired").getExpiryAddress());
|
Assert.assertEquals(SimpleString.toSimpleString("important"), configuration.getAddressSettings().get("NeedToTrackExpired").getExpiryAddress());
|
||||||
Assert.assertEquals(SimpleString.toSimpleString("moreImportant"), configuration.getAddressSettings().get("Name.With.Dots").getExpiryAddress());
|
Assert.assertEquals(SimpleString.toSimpleString("moreImportant"), configuration.getAddressSettings().get("Name.With.Dots").getExpiryAddress());
|
||||||
|
|
||||||
|
Assert.assertTrue(configuration.getStatus().contains("\"errors\":[]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
@ -91,6 +91,7 @@ reflect the camelCase java naming convention.
|
||||||
|
|
||||||
Collections need some special treatment to allow additions and reference. We utilise the name attribute of configuration
|
Collections need some special treatment to allow additions and reference. We utilise the name attribute of configuration
|
||||||
entities to find existing entries and when populating new entities, we set the name to match the requested key.
|
entities to find existing entries and when populating new entities, we set the name to match the requested key.
|
||||||
|
Removal of configuration from named collections is supported by setting a key value to "-". The remove match value can be configured with a property key "remove.value".
|
||||||
|
|
||||||
For example, a properties file containing:
|
For example, a properties file containing:
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue