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_REMOVE_VALUE = "-";
|
||||
|
||||
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_URL_LIST = null;
|
||||
|
@ -1625,6 +1629,10 @@ public final class ActiveMQDefaultConfiguration {
|
|||
return BROKER_PROPERTIES_KEY_SURROUND;
|
||||
}
|
||||
|
||||
public static String getDefaultBrokerPropertiesRemoveValue() {
|
||||
return BROKER_PROPERTIES_REMOVE_VALUE;
|
||||
}
|
||||
|
||||
public static String getDefaultNetworkCheckList() {
|
||||
return DEFAULT_NETWORK_CHECK_LIST;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
@ -379,6 +380,8 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
|||
|
||||
private String brokerPropertiesKeySurround = ActiveMQDefaultConfiguration.getDefaultBrokerPropertiesKeySurround();
|
||||
|
||||
private String brokerPropertiesRemoveValue = ActiveMQDefaultConfiguration.getDefaultBrokerPropertiesRemoveValue();
|
||||
|
||||
private String networkCheckList = ActiveMQDefaultConfiguration.getDefaultNetworkCheckList();
|
||||
|
||||
private String networkURLList = ActiveMQDefaultConfiguration.getDefaultNetworkCheckURLList();
|
||||
|
@ -502,6 +505,14 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
|||
this.brokerPropertiesKeySurround = brokerPropertiesKeySurround;
|
||||
}
|
||||
|
||||
public String getBrokerPropertiesRemoveValue() {
|
||||
return brokerPropertiesRemoveValue;
|
||||
}
|
||||
|
||||
public void setBrokerPropertiesRemoveValue(String brokerPropertiesRemoveValue) {
|
||||
this.brokerPropertiesRemoveValue = brokerPropertiesRemoveValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Configuration parseProperties(String fileUrlToProperties) throws Exception {
|
||||
// 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 {
|
||||
CollectionAutoFillPropertiesUtil autoFillCollections = new CollectionAutoFillPropertiesUtil();
|
||||
CollectionAutoFillPropertiesUtil autoFillCollections = new CollectionAutoFillPropertiesUtil(getBrokerPropertiesRemoveValue(beanProperties));
|
||||
BeanUtilsBean beanUtils = new BeanUtilsBean(new ConvertUtilsBean(), autoFillCollections) {
|
||||
// override to treat missing properties as errors, not skip as the default impl does
|
||||
@Override
|
||||
|
@ -613,8 +624,38 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
|||
}
|
||||
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
|
||||
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
|
||||
final int index = resolver.getIndex(name); // Indexed subscript 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) {
|
||||
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 {
|
||||
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
|
||||
public boolean isClustered() {
|
||||
return !getClusterConfigurations().isEmpty();
|
||||
|
@ -3077,8 +3126,13 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
|||
|
||||
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[]{};
|
||||
final Stack<Pair<String, Object>> collections = new Stack<>();
|
||||
final String removeValue;
|
||||
private BeanUtilsBean beanUtilsBean;
|
||||
|
||||
CollectionAutoFillPropertiesUtil(String brokerPropertiesRemoveValue) {
|
||||
this.removeValue = brokerPropertiesRemoveValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setProperty(final Object bean, final String name, final Object value) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
|
||||
// any set will invalidate our collections stack
|
||||
|
@ -3144,6 +3198,18 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
|||
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)
|
||||
// can be used to access and *not* auto create entries
|
||||
@Override
|
||||
|
@ -3257,6 +3323,10 @@ public class ConfigurationImpl implements Configuration, Serializable {
|
|||
// we want type conversion
|
||||
this.beanUtilsBean = beanUtilsBean;
|
||||
}
|
||||
|
||||
public boolean isRemoveValue(Object value) {
|
||||
return removeValue != null && removeValue.equals(value);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
@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
|
||||
public void testIDCacheSizeViaProperties() throws Throwable {
|
||||
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("important"), configuration.getAddressSettings().get("NeedToTrackExpired").getExpiryAddress());
|
||||
Assert.assertEquals(SimpleString.toSimpleString("moreImportant"), configuration.getAddressSettings().get("Name.With.Dots").getExpiryAddress());
|
||||
|
||||
Assert.assertTrue(configuration.getStatus().contains("\"errors\":[]"));
|
||||
}
|
||||
|
||||
@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
|
||||
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:
|
||||
|
||||
|
|
Loading…
Reference in New Issue