ARTEMIS-3895 - treat properties url with trailing slash as directory of .properties files and apply in lexical order of name

This commit is contained in:
Gary Tully 2022-07-15 14:30:20 +01:00
parent a0fb174c8f
commit 7bc3b02809
3 changed files with 93 additions and 37 deletions

View File

@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FilenameFilter;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
@ -471,22 +472,33 @@ public class ConfigurationImpl implements Configuration, Serializable {
fileUrlToProperties = System.getProperty(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME, fileUrlToProperties);
if (fileUrlToProperties != null) {
for (String fileUrl : fileUrlToProperties.split(",")) {
Properties brokerProperties = new Properties() {
final LinkedHashMap<Object, Object> orderedMap = new LinkedHashMap<>();
@Override
public Object put(Object key, Object value) {
return orderedMap.put(key.toString(), value.toString());
Properties brokerProperties = new InsertionOrderedProperties();
if (fileUrl.endsWith("/")) {
// treat as a directory and parse every property file in alphabetical order
File dir = new File(fileUrl);
if (dir.exists()) {
String[] files = dir.list(new FilenameFilter() {
@Override
public boolean accept(File file, String s) {
return s.endsWith(".properties");
}
});
if (files != null && files.length > 0) {
Arrays.sort(files);
for (String fileName : files) {
try (FileInputStream fileInputStream = new FileInputStream(new File(dir, fileName)); BufferedInputStream reader = new BufferedInputStream(fileInputStream)) {
brokerProperties.clear();
brokerProperties.load(reader);
parsePrefixedProperties(brokerProperties, null);
}
}
}
}
@Override
public Set<Map.Entry<Object, Object>> entrySet() {
return orderedMap.entrySet();
} else {
try (FileInputStream fileInputStream = new FileInputStream(fileUrl); BufferedInputStream reader = new BufferedInputStream(fileInputStream)) {
brokerProperties.load(reader);
parsePrefixedProperties(brokerProperties, null);
}
};
try (FileInputStream fileInputStream = new FileInputStream(fileUrl); BufferedInputStream reader = new BufferedInputStream(fileInputStream)) {
brokerProperties.load(reader);
parsePrefixedProperties(brokerProperties, null);
}
}
}
@ -3009,4 +3021,24 @@ public class ConfigurationImpl implements Configuration, Serializable {
return super.getProperty(expression);
}
}
static class InsertionOrderedProperties extends Properties {
final LinkedHashMap<Object, Object> orderedMap = new LinkedHashMap<>();
@Override
public Object put(Object key, Object value) {
return orderedMap.put(key.toString(), value.toString());
}
@Override
public Set<Map.Entry<Object, Object>> entrySet() {
return orderedMap.entrySet();
}
@Override
public void clear() {
orderedMap.clear();
}
}
}

View File

@ -156,9 +156,15 @@ public class EmbeddedActiveMQ {
}
if (propertiesResourcePath != null) {
URL brokerPropertiesFromClasspath = this.getClass().getClassLoader().getResource(propertiesResourcePath);
if (brokerPropertiesFromClasspath != null) {
activeMQServer.setProperties(new File(brokerPropertiesFromClasspath.toURI()).getAbsolutePath());
if (propertiesResourcePath == ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME) {
// try and locate on the classpath, broker.properties
URL brokerPropertiesFromClasspath = this.getClass().getClassLoader().getResource(propertiesResourcePath);
if (brokerPropertiesFromClasspath != null) {
activeMQServer.setProperties(new File(brokerPropertiesFromClasspath.toURI()).getAbsolutePath());
}
} else {
// pass through non default configured value
activeMQServer.setProperties(propertiesResourcePath);
}
}
}

View File

@ -22,9 +22,7 @@ import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@ -618,7 +616,7 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
public void testSetConnectionRoutersPolicyConfiguration() throws Throwable {
ConfigurationImpl configuration = new ConfigurationImpl();
Properties insertionOrderedProperties = new InsertionOrderedProperties();
Properties insertionOrderedProperties = new ConfigurationImpl.InsertionOrderedProperties();
insertionOrderedProperties.put("connectionRouters.autoShard.localTargetFilter", "NULL|$STATEFUL_SET_ORDINAL");
insertionOrderedProperties.put("connectionRouters.autoShard.keyType", KeyType.CLIENT_ID);
insertionOrderedProperties.put("connectionRouters.autoShard.policyConfiguration", ConsistentHashModuloPolicy.NAME);
@ -638,7 +636,7 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
final String queueName = "q";
final String forwardingAddress = "fa";
Properties properties = new InsertionOrderedProperties();
Properties properties = new ConfigurationImpl.InsertionOrderedProperties();
properties.put("bridgeConfigurations.b1.queueName", queueName);
properties.put("bridgeConfigurations.b1.forwardingAddress", forwardingAddress);
@ -795,7 +793,7 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
final String forwardAddress = "forwardAddress";
final String className = "s.o.m.e.class";
Properties properties = new InsertionOrderedProperties();
Properties properties = new ConfigurationImpl.InsertionOrderedProperties();
properties.put("divertConfigurations.divert1.routingName", routingName);
properties.put("divertConfigurations.divert1.address", address);
@ -1031,7 +1029,6 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
files.addLast(tmpFile.getAbsolutePath());
}
final AtomicReference<String> errorAt = new AtomicReference<>();
ConfigurationImpl configuration = new ConfigurationImpl() {
@Override
public ConfigurationImpl setName(String name) {
@ -1045,6 +1042,41 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
assertEquals("second won", "two", configuration.getName());
}
@Test
public void testPropertiesFilesInDir() throws Exception {
LinkedList<String> files = new LinkedList<>();
LinkedList<String> names = new LinkedList<>();
names.addLast("a_one");
names.addLast("b_two");
for (String name : names) {
File tmpFile = File.createTempFile(name, ".properties", temporaryFolder.getRoot());
FileOutputStream fileOutputStream = new FileOutputStream(tmpFile);
PrintWriter printWriter = new PrintWriter(fileOutputStream);
printWriter.println("name=" + name);
printWriter.flush();
fileOutputStream.flush();
fileOutputStream.close();
files.addLast(tmpFile.getAbsolutePath());
}
ConfigurationImpl configuration = new ConfigurationImpl() {
@Override
public ConfigurationImpl setName(String name) {
if (!(name.equals(names.remove()))) {
fail("Expected names from files in order");
}
return super.setName(name);
}
};
configuration.parseProperties(temporaryFolder.getRoot() + "/");
assertEquals("second won", "b_two", configuration.getName());
assertTrue("all names applied", names.isEmpty());
}
@Test
public void testNameWithDotsSurroundWithDollarDollar() throws Throwable {
ConfigurationImpl configuration = new ConfigurationImpl();
@ -1131,18 +1163,4 @@ public class ConfigurationImplTest extends ActiveMQTestBase {
return new ConfigurationImpl();
}
private static class InsertionOrderedProperties extends Properties {
final LinkedHashMap<Object, Object> orderedMap = new LinkedHashMap<>();
@Override
public Object put(Object key, Object value) {
return orderedMap.put(key.toString(), value.toString());
}
@Override
public Set<Map.Entry<Object, Object>> entrySet() {
return orderedMap.entrySet();
}
}
}