This is an automated email from the ASF dual-hosted git repository.
gtully pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git
The following commit(s) were added to refs/heads/main by this push:
new 10d93d9 ARTEMIS-3627 - support broker.properties for augmenting or
supplying additional configuration via nested properties of the internal
configuratinimpl bean - elements with a name attribute can be configured in
collections, the type inferred by the add singular fluent api
10d93d9 is described below
commit 10d93d9c92f1b0f276c88a8b782152af596cd7da
Author: gtully <[email protected]>
AuthorDate: Fri Jan 7 17:50:03 2022 +0000
ARTEMIS-3627 - support broker.properties for augmenting or supplying
additional configuration via nested properties of the internal configuratinimpl
bean - elements with a name attribute can be configured in collections, the
type inferred by the add singular fluent api
---
.../apache/activemq/artemis/cli/commands/Run.java | 15 +-
.../org/apache/activemq/cli/test/ArtemisTest.java | 34 +++
artemis-cli/src/test/resources/broker.properties | 19 ++
.../api/config/ActiveMQDefaultConfiguration.java | 10 +
.../artemis/api/core/TransportConfiguration.java | 4 +
.../artemis/core/config/Configuration.java | 5 +-
.../AMQPBrokerConnectConfiguration.java | 13 +-
.../AMQPBrokerConnectionElement.java | 11 +
.../core/config/impl/ConfigurationImpl.java | 282 ++++++++++++++++++++-
.../core/config/impl/FileConfiguration.java | 2 -
.../deployers/impl/FileConfigurationParser.java | 4 +-
.../artemis/core/server/ActiveMQServer.java | 3 +
.../core/server/embedded/EmbeddedActiveMQ.java | 8 +
.../core/server/impl/ActiveMQServerImpl.java | 10 +-
.../core/settings/impl/ResourceLimitSettings.java | 4 +
.../core/config/impl/ConfigurationImplTest.java | 123 ++++++++-
.../server/config/JMSServerPropertyConfigTest.java | 87 +++++++
.../src/test/resources/broker.properties | 18 ++
18 files changed, 625 insertions(+), 27 deletions(-)
diff --git
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
index b594e37..dd00eb5 100644
---
a/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
+++
b/artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/Run.java
@@ -23,6 +23,7 @@ import java.util.concurrent.atomic.AtomicReference;
import io.airlift.airline.Command;
import io.airlift.airline.Option;
+import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.cli.Artemis;
import org.apache.activemq.artemis.cli.commands.tools.LockAbstract;
@@ -47,6 +48,9 @@ public class Run extends LockAbstract {
@Option(name = "--allow-kill", description = "This will allow the server to
kill itself. Useful for tests (failover tests for instance)")
boolean allowKill;
+ @Option(name = "--properties", description = "A file url to a properties
file that is applied to the server's internal ConfigurationImpl bean")
+ String properties;
+
private static boolean embedded = false;
public static final ReusableLatch latchRunning = new ReusableLatch(0);
@@ -112,6 +116,14 @@ public class Run extends LockAbstract {
server.createComponents();
server.getServer().registerActivationFailureListener(exception ->
serverActivationFailed.set(exception));
+
+ if (properties == null) {
+ File propertiesFileFromEtc = new File(getBrokerEtc(),
ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME);
+ if (propertiesFileFromEtc.exists()) {
+ properties = propertiesFileFromEtc.getAbsolutePath();
+ }
+ }
+ server.getServer().setProperties(properties);
server.start();
server.getServer().addExternalComponent(managementContext, false);
@@ -121,7 +133,7 @@ public class Run extends LockAbstract {
for (ComponentDTO componentDTO : broker.components) {
Class clazz =
this.getClass().getClassLoader().loadClass(componentDTO.componentClassName);
- ExternalComponent component = (ExternalComponent)
clazz.newInstance();
+ ExternalComponent component = (ExternalComponent)
clazz.getDeclaredConstructor(null).newInstance();
component.configure(componentDTO, getBrokerInstance(),
getBrokerHome());
server.getServer().addExternalComponent(component, true);
assert component.isStarted();
@@ -129,6 +141,7 @@ public class Run extends LockAbstract {
} catch (Throwable t) {
t.printStackTrace();
serverActivationFailed.set(t);
+ latchRunning.countDown();
}
if (serverActivationFailed.get() != null) {
diff --git
a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
index 753f3f4..6020f78 100644
--- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
+++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/ArtemisTest.java
@@ -39,6 +39,7 @@ import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
+import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
@@ -1921,6 +1922,39 @@ public class ArtemisTest extends CliTestBase {
}
@Test
+ public void testRunPropertiesArgumentSetsAcceptorPort() throws Exception {
+ File instanceFile = new File(temporaryFolder.getRoot(),
"testRunPropertiesArgumentSetsAcceptorPort");
+ setupAuth(instanceFile);
+ Run.setEmbedded(true);
+ Artemis.main("create", instanceFile.getAbsolutePath(), "--silent",
"--no-fsync", "--no-autotune", "--no-web", "--require-login");
+ System.setProperty("artemis.instance", instanceFile.getAbsolutePath());
+
+ // configure
+ URL brokerPropertiesFromClasspath =
this.getClass().getClassLoader().getResource(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME);
+ Artemis.internalExecute("run", "--properties", new
File(brokerPropertiesFromClasspath.toURI()).getAbsolutePath());
+
+ // verify
+ try (ActiveMQConnectionFactory cf = new
ActiveMQConnectionFactory("tcp://localhost:61618"); Connection connection =
cf.createConnection("admin", "admin");) {
+ connection.start();
+ } finally {
+ stopServer();
+ }
+ }
+
+ @Test
+ public void testRunPropertiesDudArgument() throws Exception {
+ File instanceFile = new File(temporaryFolder.getRoot(),
"testRunPropertiesDudArgument");
+ setupAuth(instanceFile);
+ Run.setEmbedded(true);
+ Artemis.main("create", instanceFile.getAbsolutePath(), "--silent",
"--no-fsync", "--no-autotune", "--no-web", "--require-login");
+ System.setProperty("artemis.instance", instanceFile.getAbsolutePath());
+
+ // verify error
+ Object ret = Artemis.internalExecute("run", "--properties",
"https://www.apache.org");
+ assertTrue(ret instanceof IllegalStateException);
+ }
+
+ @Test
public void testVersionCommand() throws Exception {
TestActionContext context = new TestActionContext();
PrintVersion printVersion = new PrintVersion();
diff --git a/artemis-cli/src/test/resources/broker.properties
b/artemis-cli/src/test/resources/broker.properties
new file mode 100644
index 0000000..4f6c2a1
--- /dev/null
+++ b/artemis-cli/src/test/resources/broker.properties
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+name=ConfiguredViaProperties
+acceptorConfigurations.artemis.params.port=61618
diff --git
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
index 092887e..f56d443 100644
---
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
+++
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java
@@ -557,6 +557,12 @@ public final class ActiveMQDefaultConfiguration {
public static final String DEFAULT_SYSTEM_PROPERTY_PREFIX = "brokerconfig.";
+ public static final String BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME =
"broker.properties";
+
+ public static final String BROKER_PROPERTIES_KEY_SURROUND = "\"";
+
+ public static final String BROKER_PROPERTIES_KEY_SURROUND_PROPERTY =
"key.surround";
+
public static String DEFAULT_NETWORK_CHECK_LIST = null;
public static String DEFAULT_NETWORK_CHECK_URL_LIST = null;
@@ -1587,6 +1593,10 @@ public final class ActiveMQDefaultConfiguration {
return DEFAULT_SYSTEM_PROPERTY_PREFIX;
}
+ public static String getDefaultBrokerPropertiesKeySurround() {
+ return BROKER_PROPERTIES_KEY_SURROUND;
+ }
+
public static String getDefaultNetworkCheckList() {
return DEFAULT_NETWORK_CHECK_LIST;
}
diff --git
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/TransportConfiguration.java
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/TransportConfiguration.java
index 2d9f415..84d7a8a 100644
---
a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/TransportConfiguration.java
+++
b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/TransportConfiguration.java
@@ -164,6 +164,10 @@ public class TransportConfiguration implements
Serializable {
return name;
}
+ public void setName(String name) {
+ this.name = name;
+ }
+
/**
* Returns the class name of ConnectorFactory being used by this
TransportConfiguration
*
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
index a67d09b..8cc7d48 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/Configuration.java
@@ -20,7 +20,6 @@ import java.io.File;
import java.net.URL;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -87,9 +86,7 @@ public interface Configuration {
*/
String getSystemPropertyPrefix();
- Configuration parseSystemProperties() throws Exception;
-
- Configuration parseSystemProperties(Properties properties) throws Exception;
+ Configuration parseProperties(String optionalUrlToPropertiesFile) throws
Exception;
boolean isCriticalAnalyzer();
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectConfiguration.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectConfiguration.java
index 25b5309..0dbdc56 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectConfiguration.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectConfiguration.java
@@ -31,16 +31,17 @@ public class AMQPBrokerConnectConfiguration extends
BrokerConnectConfiguration {
List<TransportConfiguration> transportConfigurations;
- List<AMQPBrokerConnectionElement> connectionElements;
+ List<AMQPBrokerConnectionElement> connectionElements = new ArrayList<>();
+
+ public AMQPBrokerConnectConfiguration() {
+ super(null, null);
+ }
public AMQPBrokerConnectConfiguration(String name, String uri) {
super(name, uri);
}
public AMQPBrokerConnectConfiguration
addElement(AMQPBrokerConnectionElement amqpBrokerConnectionElement) {
- if (connectionElements == null) {
- connectionElements = new ArrayList<>();
- }
amqpBrokerConnectionElement.setParent(this);
@@ -53,6 +54,10 @@ public class AMQPBrokerConnectConfiguration extends
BrokerConnectConfiguration {
return this;
}
+ public AMQPBrokerConnectConfiguration
addConnectionElement(AMQPMirrorBrokerConnectionElement
amqpBrokerConnectionElement) {
+ return addElement(amqpBrokerConnectionElement);
+ }
+
public List<AMQPBrokerConnectionElement> getConnectionElements() {
return connectionElements;
}
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectionElement.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectionElement.java
index f2a174f..89851c6 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectionElement.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectionElement.java
@@ -23,6 +23,7 @@ import
org.apache.activemq.artemis.core.config.WildcardConfiguration;
import org.apache.activemq.artemis.core.postoffice.impl.AddressImpl;
public class AMQPBrokerConnectionElement implements Serializable {
+ String name;
SimpleString matchAddress;
SimpleString queueName;
AMQPBrokerConnectionAddressType type;
@@ -84,4 +85,14 @@ public class AMQPBrokerConnectionElement implements
Serializable {
this.type = type;
return this;
}
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
}
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
index 4abd5a8..3c13f70 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImpl.java
@@ -16,21 +16,27 @@
*/
package org.apache.activemq.artemis.core.config.impl;
+import java.beans.PropertyDescriptor;
+import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
@@ -38,12 +44,14 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import java.util.Stack;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.BroadcastGroupConfiguration;
import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
+import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
@@ -65,6 +73,8 @@ import
org.apache.activemq.artemis.core.config.WildcardConfiguration;
import org.apache.activemq.artemis.core.config.ha.ReplicaPolicyConfiguration;
import
org.apache.activemq.artemis.core.config.ha.ReplicatedPolicyConfiguration;
import
org.apache.activemq.artemis.core.config.storage.DatabaseStorageConfiguration;
+import
org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory;
+import
org.apache.activemq.artemis.core.remoting.impl.netty.NettyConnectorFactory;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.JournalType;
@@ -89,7 +99,14 @@ import
org.apache.activemq.artemis.core.settings.impl.ResourceLimitSettings;
import org.apache.activemq.artemis.utils.Env;
import org.apache.activemq.artemis.utils.ObjectInputStreamWithClassLoader;
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
-import org.apache.activemq.artemis.utils.uri.BeanSupport;
+import
org.apache.activemq.artemis.utils.uri.FluentPropertyBeanIntrospectorWithIgnores;
+import org.apache.commons.beanutils.BeanUtilsBean;
+import org.apache.commons.beanutils.ConvertUtilsBean;
+import org.apache.commons.beanutils.Converter;
+import org.apache.commons.beanutils.MappedPropertyDescriptor;
+import org.apache.commons.beanutils.MethodUtils;
+import org.apache.commons.beanutils.PropertyUtilsBean;
+import org.apache.commons.beanutils.expression.DefaultResolver;
import org.jboss.logging.Logger;
public class ConfigurationImpl implements Configuration, Serializable {
@@ -338,6 +355,8 @@ public class ConfigurationImpl implements Configuration,
Serializable {
private String systemPropertyPrefix =
ActiveMQDefaultConfiguration.getDefaultSystemPropertyPrefix();
+ private String brokerPropertiesKeySurround =
ActiveMQDefaultConfiguration.getDefaultBrokerPropertiesKeySurround();
+
private String networkCheckList =
ActiveMQDefaultConfiguration.getDefaultNetworkCheckList();
private String networkURLList =
ActiveMQDefaultConfiguration.getDefaultNetworkCheckURLList();
@@ -429,31 +448,73 @@ public class ConfigurationImpl implements Configuration,
Serializable {
return systemPropertyPrefix;
}
+ public String getBrokerPropertiesKeySurround() {
+ return brokerPropertiesKeySurround;
+ }
+
+ public void setBrokerPropertiesKeySurround(String
brokerPropertiesKeySurround) {
+ this.brokerPropertiesKeySurround = brokerPropertiesKeySurround;
+ }
+
@Override
- public Configuration parseSystemProperties() throws Exception {
- parseSystemProperties(System.getProperties());
+ public Configuration parseProperties(String fileUrlToProperties) throws
Exception {
+ // system property overrides
+ fileUrlToProperties =
System.getProperty(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME,
fileUrlToProperties);
+ if (fileUrlToProperties != null) {
+ Properties brokerProperties = new Properties();
+ try (FileInputStream fileInputStream = new
FileInputStream(fileUrlToProperties); BufferedInputStream reader = new
BufferedInputStream(fileInputStream)) {
+ brokerProperties.load(reader);
+ parsePrefixedProperties(brokerProperties, null);
+ }
+ }
+ parsePrefixedProperties(System.getProperties(), systemPropertyPrefix);
return this;
}
- @Override
- public Configuration parseSystemProperties(Properties properties) throws
Exception {
+ public void parsePrefixedProperties(Properties properties, String prefix)
throws Exception {
Map<String, Object> beanProperties = new HashMap<>();
synchronized (properties) {
+ String key = null;
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
- if (entry.getKey().toString().startsWith(systemPropertyPrefix)) {
- String key =
entry.getKey().toString().substring(systemPropertyPrefix.length());
- logger.debug("Setting up config, " + key + "=" +
entry.getValue());
- beanProperties.put(key, entry.getValue());
+ key = entry.getKey().toString();
+ if (prefix != null) {
+ if (!key.startsWith(prefix)) {
+ continue;
+ }
+ key = entry.getKey().toString().substring(prefix.length());
}
+ logger.debug("Setting up config, " + key + "=" + entry.getValue());
+ beanProperties.put(key, entry.getValue());
}
}
if (!beanProperties.isEmpty()) {
- BeanSupport.setData(this, beanProperties);
+ populateWithProperties(beanProperties);
}
+ }
- return this;
+ public void populateWithProperties(Map<String, Object> beanProperties)
throws InvocationTargetException, IllegalAccessException {
+ BeanUtilsBean beanUtils = new BeanUtilsBean(new ConvertUtilsBean(), new
CollectionAutoFillPropertiesUtil());
+ // nested property keys delimited by . and enclosed by '"' if they key's
themselves contain dots
+ beanUtils.getPropertyUtils().setResolver(new
SurroundResolver(getBrokerPropertiesKeySurround(beanProperties)));
+ beanUtils.getConvertUtils().register(new Converter() {
+ @Override
+ public <T> T convert(Class<T> type, Object value) {
+ return (T) SimpleString.toSimpleString(value.toString());
+ }
+ }, SimpleString.class);
+ beanUtils.getPropertyUtils().addBeanIntrospector(new
FluentPropertyBeanIntrospectorWithIgnores());
+
+ beanUtils.populate(this, beanProperties);
+ }
+
+ 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));
+ } else {
+ return System.getProperty(getSystemPropertyPrefix() +
ActiveMQDefaultConfiguration.BROKER_PROPERTIES_KEY_SURROUND_PROPERTY,
getBrokerPropertiesKeySurround());
+ }
}
@Override
@@ -698,6 +759,11 @@ public class ConfigurationImpl implements Configuration,
Serializable {
return this;
}
+ public ConfigurationImpl addConnectorConfiguration(final
TransportConfiguration info) {
+ connectorConfigs.put(info.getName(), info);
+ return this;
+ }
+
@Override
public ConfigurationImpl addConnectorConfiguration(final String name, final
String uri) throws Exception {
@@ -795,6 +861,10 @@ public class ConfigurationImpl implements Configuration,
Serializable {
return this.amqpBrokerConnectConfigurations;
}
+ public List<AMQPBrokerConnectConfiguration> getAMQPConnections() {
+ return this.amqpBrokerConnectConfigurations;
+ }
+
@Override
public ConfigurationImpl clearClusterConfigurations() {
clusterConfigurations.clear();
@@ -1555,6 +1625,10 @@ public class ConfigurationImpl implements Configuration,
Serializable {
return this;
}
+ public ConfigurationImpl addResourceLimitSetting(ResourceLimitSettings
resourceLimitSettings) {
+ return this.addResourceLimitSettings(resourceLimitSettings);
+ }
+
@Override
public Map<String, Set<Role>> getSecurityRoles() {
for (SecuritySettingPlugin securitySettingPlugin :
securitySettingPlugins) {
@@ -2603,4 +2677,190 @@ public class ConfigurationImpl implements
Configuration, Serializable {
return this;
}
+ // extend property utils with ability to auto-fill and locate from
collections
+ // collection entries are identified by the name() property
+ private static class CollectionAutoFillPropertiesUtil extends
PropertyUtilsBean {
+
+ private static final Object[] EMPTY_OBJECT_ARRAY = new Object[]{};
+ final Stack<Pair<String, Object>> collections = new Stack<>();
+
+ @Override
+ public void setProperty(final Object bean, final String name, final
Object value) throws InvocationTargetException, IllegalAccessException,
NoSuchMethodException {
+ // any set will invalidate our collections stack
+ if (!collections.isEmpty()) {
+ Pair<String, Object> collectionInfo = collections.pop();
+ }
+ super.setProperty(bean, name, value);
+ }
+
+ // need to track collections such that we can locate or create entries
on demand
+ @Override
+ public Object getProperty(final Object bean,
+ final String name) throws
IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+
+ if (!collections.isEmpty()) {
+ final String key = getResolver().getProperty(name);
+ Pair<String, Object> collectionInfo = collections.pop();
+ if (bean instanceof Map) {
+ Map map = (Map) bean;
+ if (!map.containsKey(key)) {
+ map.put(key,
newNamedInstanceForCollection(collectionInfo.getA(), collectionInfo.getB(),
key));
+ }
+ return map.get(key);
+ } else { // collection
+ // locate on name property
+ for (Object candidate : (Collection) bean) {
+ if (key.equals(getProperty(candidate, "name"))) {
+ return candidate;
+ }
+ }
+ // or create it
+ Object created =
newNamedInstanceForCollection(collectionInfo.getA(), collectionInfo.getB(),
key);
+ ((Collection) bean).add(created);
+ return created;
+ }
+ }
+
+ Object resolved = getNestedProperty(bean, name);
+
+ if (resolved instanceof Collection || resolved instanceof Map) {
+ collections.push(new Pair<String, Object>(name, bean));
+ }
+ return resolved;
+ }
+
+ // allow finding beans in collections via name() such that a mapped key
(key)
+ // can be used to access and *not* auto create entries
+ @Override
+ public Object getMappedProperty(final Object bean,
+ final String name, final String key)
+ throws IllegalAccessException, InvocationTargetException,
+ NoSuchMethodException {
+
+ if (bean == null) {
+ throw new IllegalArgumentException("No bean specified");
+ }
+ if (name == null) {
+ throw new IllegalArgumentException("No name specified for bean
class '" +
+ bean.getClass() + "'");
+ }
+ if (key == null) {
+ throw new IllegalArgumentException("No key specified for property
'" +
+ name + "' on bean class " +
bean.getClass() + "'");
+ }
+
+ Object result = null;
+
+ final PropertyDescriptor descriptor = getPropertyDescriptor(bean,
name);
+ if (descriptor == null) {
+ throw new NoSuchMethodException("Unknown property '" +
+ name + "'+ on bean class '" +
bean.getClass() + "'");
+ }
+
+ if (descriptor instanceof MappedPropertyDescriptor) {
+ // Call the keyed getter method if there is one
+ Method readMethod = ((MappedPropertyDescriptor) descriptor).
+ getMappedReadMethod();
+ readMethod = MethodUtils.getAccessibleMethod(bean.getClass(),
readMethod);
+ if (readMethod != null) {
+ final Object[] keyArray = new Object[1];
+ keyArray[0] = key;
+ result = readMethod.invoke(bean, keyArray);
+ } else {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no mapped getter
method on bean class '" +
+ bean.getClass() + "'");
+ }
+ } else {
+ final Method readMethod =
MethodUtils.getAccessibleMethod(bean.getClass(), descriptor.getReadMethod());
+ if (readMethod != null) {
+ final Object invokeResult = readMethod.invoke(bean,
EMPTY_OBJECT_ARRAY);
+ if (invokeResult instanceof Map) {
+ result = ((Map<?, ?>)invokeResult).get(key);
+ } else if (invokeResult instanceof Collection) {
+ // locate on name property
+ for (Object candidate : (Collection) invokeResult) {
+ if (key.equals(getProperty(candidate, "name"))) {
+ return candidate;
+ }
+ }
+ }
+ } else {
+ throw new NoSuchMethodException("Property '" + name +
+ "' has no mapped getter
method on bean class '" +
+ bean.getClass() + "'");
+ }
+ }
+ return result;
+ }
+
+ private Object newNamedInstanceForCollection(String
collectionPropertyName, Object hostingBean, String name) {
+ // find the add X and init an instance of the type with name=name
+
+ // expect an add... without the plural
+ String addPropertyName = "add" +
Character.toUpperCase(collectionPropertyName.charAt(0)) +
collectionPropertyName.substring(1, collectionPropertyName.length() - 1);
+
+ // we don't know the type, infer from add method add(X x) or
add(String key, X x)
+ final Method[] methods = hostingBean.getClass().getMethods();
+ for (Method candidate : methods) {
+ if (candidate.getName().equals(addPropertyName) &&
+ (candidate.getParameterCount() == 1 ||
+ (candidate.getParameterCount() == 2
+ // has a String key
+ && String.class.equals(candidate.getParameterTypes()[0])
+ // but not initialised from a String form (eg: uri)
+ &&
!String.class.equals(candidate.getParameterTypes()[1])))) {
+
+ // create one and initialise with name
+ try {
+ Object instance =
candidate.getParameterTypes()[candidate.getParameterCount() -
1].getDeclaredConstructor().newInstance(null);
+ try {
+ setProperty(instance, "name", name);
+ } catch (NoSuchMethodException okIgnore) {
+ }
+
+ // this is always going to be a little hacky b/c our config
is not natively property friendly
+ if (instance instanceof TransportConfiguration) {
+ setProperty(instance, "factoryClassName",
"invm".equals(name) ? InVMConnectorFactory.class.getName() :
NettyConnectorFactory.class.getName());
+ }
+ return instance;
+
+ } catch (Exception e) {
+ logger.debug("Failed to add entry for " + name + " with
method: " + candidate, e);
+ throw new IllegalArgumentException("failed to add entry for
collection key " + name, e);
+ }
+ }
+ }
+ throw new IllegalArgumentException("failed to locate add method for
collection property " + addPropertyName);
+ }
+ }
+
+ private static class SurroundResolver extends DefaultResolver {
+ final String surroundString;
+
+ SurroundResolver(String surroundString) {
+ this.surroundString = surroundString;
+ }
+
+ @Override
+ public String next(String expression) {
+ String result = super.next(expression);
+ if (result != null) {
+ if (result.startsWith(surroundString)) {
+ // we need to recompute to properly terminate this SURROUND
+ result =
expression.substring(expression.indexOf(surroundString));
+ return result.substring(0, result.indexOf(surroundString,
surroundString.length()) + surroundString.length());
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public String getProperty(final String expression) {
+ if (expression.startsWith(surroundString) &&
expression.endsWith(surroundString)) {
+ return expression.substring(surroundString.length(),
expression.length() - surroundString.length());
+ }
+ return super.getProperty(expression);
+ }
+ }
}
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileConfiguration.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileConfiguration.java
index 01ac199..1c253ef 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileConfiguration.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/FileConfiguration.java
@@ -57,8 +57,6 @@ public final class FileConfiguration extends
ConfigurationImpl implements Deploy
setConfigurationUrl(url);
- parseSystemProperties();
-
parsed = true;
}
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
index 4d9b9cd..85049c1 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java
@@ -2052,7 +2052,7 @@ public final class FileConfigurationParser extends
XMLConfigurationUtil {
String uri = e.getAttribute("uri");
int retryInterval = getAttributeInteger(e, "retry-interval", 5000,
Validators.GT_ZERO);
- int reconnectAttemps = getAttributeInteger(e, "reconnect-attempts", -1,
Validators.MINUS_ONE_OR_GT_ZERO);
+ int reconnectAttempts = getAttributeInteger(e, "reconnect-attempts", -1,
Validators.MINUS_ONE_OR_GT_ZERO);
String user = getAttributeValue(e, "user");
String password = getAttributeValue(e, "password");
boolean autoStart = getBooleanAttribute(e, "auto-start", true);
@@ -2061,7 +2061,7 @@ public final class FileConfigurationParser extends
XMLConfigurationUtil {
AMQPBrokerConnectConfiguration config = new
AMQPBrokerConnectConfiguration(name, uri);
config.parseURI();
-
config.setRetryInterval(retryInterval).setReconnectAttempts(reconnectAttemps).setUser(user).setPassword(password).setAutostart(autoStart);
+
config.setRetryInterval(retryInterval).setReconnectAttempts(reconnectAttempts).setUser(user).setPassword(password).setAutostart(autoStart);
mainConfig.addAMQPConnection(config);
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java
index 35d4f63..8bd978c 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServer.java
@@ -961,4 +961,7 @@ public interface ActiveMQServer extends ServiceComponent {
BrokerBalancerManager getBalancerManager();
String validateUser(String username, String password, RemotingConnection
connection, String securityDomain) throws Exception;
+
+ default void setProperties(String fileUrltoBrokerProperties) {
+ }
}
\ No newline at end of file
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/embedded/EmbeddedActiveMQ.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/embedded/EmbeddedActiveMQ.java
index fe0ed5e..6c12d36 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/embedded/EmbeddedActiveMQ.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/embedded/EmbeddedActiveMQ.java
@@ -17,8 +17,11 @@
package org.apache.activemq.artemis.core.server.embedded;
import javax.management.MBeanServer;
+import java.io.File;
+import java.net.URL;
import java.util.concurrent.TimeUnit;
+import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.FileDeploymentManager;
import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
@@ -140,6 +143,11 @@ public class EmbeddedActiveMQ {
} else {
activeMQServer = new ActiveMQServerImpl(configuration, mbeanServer,
securityManager);
}
+
+ URL brokerPropertiesFromClasspath =
this.getClass().getClassLoader().getResource(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME);
+ if (brokerPropertiesFromClasspath != null) {
+ activeMQServer.setProperties(new
File(brokerPropertiesFromClasspath.toURI()).getAbsolutePath());
+ }
}
public EmbeddedActiveMQ stop() throws Exception {
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
index be7a540..48d827f 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ActiveMQServerImpl.java
@@ -369,6 +369,8 @@ public class ActiveMQServerImpl implements ActiveMQServer {
private volatile FederationManager federationManager;
+ private String propertiesFileUrl;
+
private final ActiveMQComponent networkCheckMonitor = new
ActiveMQComponent() {
@Override
public void start() throws Exception {
@@ -593,13 +595,18 @@ public class ActiveMQServerImpl implements ActiveMQServer
{
return this.analyzer;
}
+ @Override
+ public void setProperties(String fileUrltoBrokerProperties) {
+ propertiesFileUrl = fileUrltoBrokerProperties;
+ }
+
private void internalStart() throws Exception {
if (state != SERVER_STATE.STOPPED) {
logger.debug("Server already started!");
return;
}
- configuration.parseSystemProperties();
+ configuration.parseProperties(propertiesFileUrl);
initializeExecutorServices();
@@ -4323,6 +4330,7 @@ public class ActiveMQServerImpl implements ActiveMQServer
{
configuration.setQueueConfigs(config.getQueueConfigs());
configurationReloadDeployed.set(false);
if (isActive()) {
+ configuration.parseProperties(propertiesFileUrl);
deployReloadableConfigFromConfiguration();
}
}
diff --git
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/ResourceLimitSettings.java
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/ResourceLimitSettings.java
index e8c0aae..c776e32 100644
---
a/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/ResourceLimitSettings.java
+++
b/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/ResourceLimitSettings.java
@@ -48,6 +48,10 @@ public class ResourceLimitSettings implements Serializable,
EncodingSupport {
// SimpleString queueNameRegex = null;
+ public void setName(String name) {
+ setMatch(SimpleString.toSimpleString(name));
+ }
+
public SimpleString getMatch() {
return match != null ? match : DEFAULT_MATCH;
}
diff --git
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImplTest.java
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImplTest.java
index 146386d..317d6dd 100644
---
a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImplTest.java
+++
b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ConfigurationImplTest.java
@@ -24,7 +24,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.activemq.artemis.ArtemisConstants;
import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
+import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
+import
org.apache.activemq.artemis.core.config.amqpBrokerConnectivity.AMQPBrokerConnectConfiguration;
+import
org.apache.activemq.artemis.core.config.amqpBrokerConnectivity.AMQPBrokerConnectionAddressType;
+import
org.apache.activemq.artemis.core.config.amqpBrokerConnectivity.AMQPMirrorBrokerConnectionElement;
import org.apache.activemq.artemis.core.config.ha.LiveOnlyPolicyConfiguration;
import org.apache.activemq.artemis.core.server.JournalType;
import
org.apache.activemq.artemis.core.server.plugin.impl.LoggingActiveMQServerPlugin;
@@ -584,12 +588,127 @@ public class ConfigurationImplTest extends
ActiveMQTestBase {
properties.put(configuration.getSystemPropertyPrefix() +
"fileDeployerScanPeriod", "1234");
properties.put(configuration.getSystemPropertyPrefix() +
"globalMaxSize", "4321");
- configuration.parseSystemProperties(properties);
+ configuration.parsePrefixedProperties(properties,
configuration.getSystemPropertyPrefix());
Assert.assertEquals(1234, configuration.getFileDeployerScanPeriod());
Assert.assertEquals(4321, configuration.getGlobalMaxSize());
}
+ @Test
+ public void testSetNestedPropertyOnCollections() throws Throwable {
+ ConfigurationImpl configuration = new ConfigurationImpl();
+
+ Properties properties = new Properties();
+ properties.put("balancerConfigurations.joe.localTargetFilter", "LF");
+ properties.put("balancerConfigurations(joe).targetKeyFilter", "TF");
+
+ properties.put("acceptorConfigurations.tcp.params.HOST", "LOCALHOST");
+ properties.put("acceptorConfigurations.tcp.params.PORT", "61616");
+
+ properties.put("acceptorConfigurations.invm.params.ID", "0");
+
+ // <amqp-connection uri="tcp://HOST:PORT" name="other-server"
retry-interval="100" reconnect-attempts="-1" user="john" password="doe">
+ properties.put("AMQPConnections.other-server.uri", "tcp://HOST:PORT");
+ properties.put("AMQPConnections.other-server.retryInterval", "100");
+ properties.put("AMQPConnections.other-server.reconnectAttempts", "100");
+ properties.put("AMQPConnections.other-server.user", "john");
+ properties.put("AMQPConnections.other-server.password", "doe");
+
+ // <amqp-connection uri="tcp://brokerB:5672" name="brokerB"> <mirror/>
</amqp-connection>
+ properties.put("AMQPConnections.brokerB.uri", "tcp://brokerB:5672");
+ properties.put("AMQPConnections.brokerB.type",
AMQPBrokerConnectionAddressType.MIRROR.toString());
+
properties.put("AMQPConnections.brokerB.connectionElements.mirror.mirrorSNF",
"mirrorSNFQueue");
+
+ properties.put("resourceLimitSettings.joe.maxConnections", "100");
+
+ configuration.parsePrefixedProperties(properties, null);
+
+ Assert.assertEquals(1, configuration.getBalancerConfigurations().size());
+ Assert.assertEquals("LF",
configuration.getBalancerConfigurations().get(0).getLocalTargetFilter());
+ Assert.assertEquals("TF",
configuration.getBalancerConfigurations().get(0).getTargetKeyFilter());
+
+ Assert.assertEquals(2, configuration.getAcceptorConfigurations().size());
+
+ for (TransportConfiguration acceptor :
configuration.getAcceptorConfigurations()) {
+ if ("tcp".equals(acceptor.getName())) {
+ Assert.assertEquals("61616", acceptor.getParams().get("PORT"));
+ }
+ if ("invm".equals(acceptor.getName())) {
+ Assert.assertEquals("0", acceptor.getParams().get("ID"));
+ }
+ }
+
+ Assert.assertEquals(2, configuration.getAMQPConnection().size());
+ for (AMQPBrokerConnectConfiguration amqpBrokerConnectConfiguration :
configuration.getAMQPConnection()) {
+ if ("brokerB".equals(amqpBrokerConnectConfiguration.getName())) {
+
Assert.assertEquals(AMQPBrokerConnectionAddressType.MIRROR.toString(),
amqpBrokerConnectConfiguration.getConnectionElements().get(0).getType().toString());
+ Assert.assertEquals("mirrorSNFQueue",
((AMQPMirrorBrokerConnectionElement)amqpBrokerConnectConfiguration.getConnectionElements().get(0)).getMirrorSNF().toString());
+
+ } else if
("other-server".equals(amqpBrokerConnectConfiguration.getName())) {
+ Assert.assertEquals(100,
amqpBrokerConnectConfiguration.getReconnectAttempts());
+ } else {
+ fail("unexpected amqp broker connection configuration: " +
amqpBrokerConnectConfiguration.getName());
+ }
+ }
+
+ Assert.assertEquals(100,
configuration.getResourceLimitSettings().get("joe").getMaxConnections());
+ }
+
+ @Test
+ public void
testSetNestedPropertyOnExistingCollectionEntryViaMappedNotation() throws
Throwable {
+ ConfigurationImpl configuration = new ConfigurationImpl();
+
+ Properties properties = new Properties();
+ properties.put("balancerConfigurations.joe.localTargetFilter", "LF");
+ // does not exist, ignored
+ properties.put("balancerConfigurations(bob).targetKeyFilter", "TF");
+ properties.put("balancerConfigurations(joe).targetKeyFilter", "TF");
+
+ configuration.parsePrefixedProperties(properties, null);
+
+ Assert.assertEquals(1, configuration.getBalancerConfigurations().size());
+ Assert.assertEquals("LF",
configuration.getBalancerConfigurations().get(0).getLocalTargetFilter());
+ Assert.assertEquals("TF",
configuration.getBalancerConfigurations().get(0).getTargetKeyFilter());
+ }
+
+ @Test
+ public void testAddressSettingsViaProperties() throws Throwable {
+ ConfigurationImpl configuration = new ConfigurationImpl();
+
+ Properties properties = new Properties();
+
+ properties.put("addressesSettings.#.expiryAddress", "sharedExpiry");
+ properties.put("addressesSettings.NeedToTrackExpired.expiryAddress",
"important");
+ properties.put("addressesSettings.\"Name.With.Dots\".expiryAddress",
"moreImportant");
+
+ configuration.parsePrefixedProperties(properties, null);
+
+ Assert.assertEquals(3, configuration.getAddressesSettings().size());
+ Assert.assertEquals(SimpleString.toSimpleString("sharedExpiry"),
configuration.getAddressesSettings().get("#").getExpiryAddress());
+ Assert.assertEquals(SimpleString.toSimpleString("important"),
configuration.getAddressesSettings().get("NeedToTrackExpired").getExpiryAddress());
+ Assert.assertEquals(SimpleString.toSimpleString("moreImportant"),
configuration.getAddressesSettings().get("Name.With.Dots").getExpiryAddress());
+ }
+
+ @Test
+ public void testNameWithDotsSurroundWithDollarDollar() throws Throwable {
+ ConfigurationImpl configuration = new ConfigurationImpl();
+
+ Properties properties = new Properties();
+
+ // overrides the default surrounding string of '"' with '$$' using a
property
+
properties.put(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_KEY_SURROUND_PROPERTY,
"$$");
+ properties.put("addressesSettings.#.expiryAddress", "sharedExpiry");
+ properties.put("addressesSettings.NeedToTrackExpired.expiryAddress",
"important");
+ properties.put("addressesSettings.$$Name.With.Dots$$.expiryAddress",
"moreImportant");
+
+ configuration.parsePrefixedProperties(properties, null);
+
+ Assert.assertEquals(3, configuration.getAddressesSettings().size());
+ Assert.assertEquals(SimpleString.toSimpleString("sharedExpiry"),
configuration.getAddressesSettings().get("#").getExpiryAddress());
+ Assert.assertEquals(SimpleString.toSimpleString("important"),
configuration.getAddressesSettings().get("NeedToTrackExpired").getExpiryAddress());
+ Assert.assertEquals(SimpleString.toSimpleString("moreImportant"),
configuration.getAddressesSettings().get("Name.With.Dots").getExpiryAddress());
+ }
+
/**
* To test ARTEMIS-926
* @throws Throwable
@@ -632,7 +751,7 @@ public class ConfigurationImplTest extends ActiveMQTestBase
{
properties.put(configuration.getSystemPropertyPrefix() +
"fileDeployerScanPeriod", "1234");
properties.put(configuration.getSystemPropertyPrefix() +
"globalMaxSize", "4321");
- configuration.parseSystemProperties(properties);
+ configuration.parsePrefixedProperties(properties,
configuration.getSystemPropertyPrefix());
} finally {
diff --git
a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/server/config/JMSServerPropertyConfigTest.java
b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/server/config/JMSServerPropertyConfigTest.java
new file mode 100644
index 0000000..5e1c468
--- /dev/null
+++
b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/server/config/JMSServerPropertyConfigTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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.activemq.artemis.tests.integration.jms.server.config;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+
+import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
+import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
+import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
+import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
+import org.junit.Test;
+
+public class JMSServerPropertyConfigTest extends ActiveMQTestBase {
+
+ @Test
+ public void testConfigViaBrokerPropertiesSystemProperty() throws Exception {
+ EmbeddedActiveMQ server = new EmbeddedActiveMQ();
+ ConfigurationImpl configuration = new ConfigurationImpl();
+
+ configuration.setJournalDirectory(new File(getTestDir(),
"./journal").getAbsolutePath()).
+ setPagingDirectory(new File(getTestDir(),
"./paging").getAbsolutePath()).
+ setLargeMessagesDirectory(new File(getTestDir(),
"./largemessages").getAbsolutePath()).
+ setBindingsDirectory(new File(getTestDir(),
"./bindings").getAbsolutePath()).setPersistenceEnabled(true);
+
+ File bindingsDir = new File(configuration.getBindingsDirectory());
+ bindingsDir.mkdirs();
+ File propertiesInBindingsDir = new File(bindingsDir,
ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME);
+
+ try (PrintStream out = new PrintStream(new BufferedOutputStream(new
FileOutputStream(propertiesInBindingsDir)))) {
+ // use the same name property as from the classpath broker.properties
to verify precedence of system prop
+ out.println("name=nameFromCopiedPropertiesRefViaSystemProp");
+ }
+
+
System.setProperty(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME,
propertiesInBindingsDir.getAbsolutePath());
+ try {
+
+ server.setConfiguration(configuration);
+ server.start();
+
+ assertEquals("nameFromCopiedPropertiesRefViaSystemProp",
server.getActiveMQServer().getConfiguration().getName());
+
+ } finally {
+
System.getProperties().remove(ActiveMQDefaultConfiguration.BROKER_PROPERTIES_SYSTEM_PROPERTY_NAME);
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testConfigViaBrokerPropertiesFromClasspath() throws Exception {
+
+ EmbeddedActiveMQ server = new EmbeddedActiveMQ();
+ ConfigurationImpl configuration = new ConfigurationImpl();
+
+ configuration.setJournalDirectory(new File(getTestDir(),
"./journal").getAbsolutePath()).
+ setPagingDirectory(new File(getTestDir(),
"./paging").getAbsolutePath()).
+ setLargeMessagesDirectory(new File(getTestDir(),
"./largemessages").getAbsolutePath()).
+ setBindingsDirectory(new File(getTestDir(),
"./bindings").getAbsolutePath()).setPersistenceEnabled(true);
+
+ try {
+
+ server.setConfiguration(configuration);
+ server.start();
+
+ assertEquals("ConfiguredViaProperties",
server.getActiveMQServer().getConfiguration().getName());
+
+ } finally {
+ server.stop();
+ }
+ }
+}
diff --git a/tests/integration-tests/src/test/resources/broker.properties
b/tests/integration-tests/src/test/resources/broker.properties
new file mode 100644
index 0000000..d257e85
--- /dev/null
+++ b/tests/integration-tests/src/test/resources/broker.properties
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+name=ConfiguredViaProperties
\ No newline at end of file