From 85857ab8eb1b1eca2498306239740e0e39d2acd4 Mon Sep 17 00:00:00 2001 From: jbertram Date: Thu, 4 Aug 2016 16:23:59 -0500 Subject: [PATCH 1/2] Fix improper IDs in logger --- .../core/server/ActiveMQServerLogger.java | 33 +++++++++---------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java index c2c2e0a6fc..51e6b423aa 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java @@ -77,6 +77,10 @@ public interface ActiveMQServerLogger extends BasicLogger { */ ActiveMQServerLogger LOGGER = Logger.getMessageLogger(ActiveMQServerLogger.class, ActiveMQServerLogger.class.getPackage().getName()); + @LogMessage(level = Logger.Level.DEBUG) + @Message(id = 223000, value = "Received Interrupt Exception whilst waiting for component to shutdown: {0}", format = Message.Format.MESSAGE_FORMAT) + void interruptWhilstStoppingComponent(String componentClassName); + @LogMessage(level = Logger.Level.INFO) @Message(id = 221000, value = "{0} Message Broker is starting with configuration {1}", format = Message.Format.MESSAGE_FORMAT) void serverStarting(String type, Configuration configuration); @@ -315,6 +319,15 @@ public interface ActiveMQServerLogger extends BasicLogger { format = Message.Format.MESSAGE_FORMAT) void disallowedProtocol(String protocol, String acceptorName); + @LogMessage(level = Logger.Level.INFO) + @Message(id = 221054, value = "libaio was found but the filesystem does not support AIO. Switching the configuration into NIO. Journal path: {0}", format = Message.Format.MESSAGE_FORMAT) + void switchingNIOonPath(String journalPath); + + @LogMessage(level = Logger.Level.INFO) + @Message(id = 221055, value = "There were too many old replicated folders upon startup, removing {0}", + format = Message.Format.MESSAGE_FORMAT) + void removingBackupData(String path); + @LogMessage(level = Logger.Level.WARN) @Message(id = 222000, value = "ActiveMQServer is being finalized and has not been stopped. Please remember to stop the server before letting it go out of scope", format = Message.Format.MESSAGE_FORMAT) @@ -1219,10 +1232,10 @@ public interface ActiveMQServerLogger extends BasicLogger { format = Message.Format.MESSAGE_FORMAT) void sslHandshakeFailed(String clientAddress, String cause); - @LogMessage(level = Logger.Level.INFO) - @Message(id = 222209, value = "There were too many old replicated folders upon startup, removing {0}", + @LogMessage(level = Logger.Level.WARN) + @Message(id = 222209, value = "Could not contact group handler coordinator after 10 retries, message being routed without grouping information", format = Message.Format.MESSAGE_FORMAT) - void removingBackupData(String path); + void impossibleToRouteGrouped(); @LogMessage(level = Logger.Level.ERROR) @Message(id = 224000, value = "Failure in initialisation", format = Message.Format.MESSAGE_FORMAT) @@ -1454,11 +1467,6 @@ public interface ActiveMQServerLogger extends BasicLogger { @Message(id = 224060, value = "Invalid protocol specified. Supported protocols are: {0}", format = Message.Format.MESSAGE_FORMAT) void invalidProtocol(String validProtocols); - @LogMessage(level = Logger.Level.WARN) - @Message(id = 224069, value = "Could not contact group handler coordinator after 10 retries, message being routed without grouping information", - format = Message.Format.MESSAGE_FORMAT) - void impossibleToRouteGrouped(); - @LogMessage(level = Logger.Level.ERROR) @Message(id = 224061, value = "Setting both <{0}> and is invalid. Please use exclusively as <{0}> is deprecated. Ignoring <{0}> value.", format = Message.Format.MESSAGE_FORMAT) void incompatibleWithHAPolicy(String parameter); @@ -1490,13 +1498,4 @@ public interface ActiveMQServerLogger extends BasicLogger { @LogMessage(level = Logger.Level.ERROR) @Message(id = 224068, value = "Unable to stop component: {0}", format = Message.Format.MESSAGE_FORMAT) void errorStoppingComponent(@Cause Throwable t, String componentClassName); - - @LogMessage(level = Logger.Level.DEBUG) - @Message(id = 224070, value = "Received Interrupt Exception whilst waiting for component to shutdown: {0}", format = Message.Format.MESSAGE_FORMAT) - void interruptWhilstStoppingComponent(String componentClassName); - - @LogMessage(level = Logger.Level.INFO) - @Message(id = 224072, value = "libaio was found but the filesystem does not support AIO. Switching the configuration into NIO. Journal path: {0}", format = Message.Format.MESSAGE_FORMAT) - void switchingNIOonPath(String journalPath); - } From 1ef9e74f146d1f406053c1e719962017f0afee98 Mon Sep 17 00:00:00 2001 From: jbertram Date: Wed, 3 Aug 2016 17:27:26 -0500 Subject: [PATCH 2/2] ARTEMIS-601 load runtime security cfg file changes --- .../activemq/cli/test/FileBrokerTest.java | 76 +++++++++++++++++++ .../src/test/resources/broker-reload.xml | 76 +++++++++++++++++++ .../config/ActiveMQDefaultConfiguration.java | 7 ++ .../config/impl/FileJMSConfiguration.java | 3 +- .../artemis/core/config/Configuration.java | 9 +++ .../core/config/FileDeploymentManager.java | 2 +- .../core/config/impl/ConfigurationImpl.java | 27 +++++++ .../core/config/impl/FileConfiguration.java | 5 +- .../artemis/core/deployers/Deployable.java | 3 +- .../impl/FileConfigurationParser.java | 2 + .../core/server/ActiveMQServerLogger.java | 4 + .../core/server/impl/ActiveMQServerImpl.java | 40 ++++++++++ .../core/settings/HierarchicalRepository.java | 4 + .../impl/HierarchicalObjectRepository.java | 26 ++++++- .../schema/artemis-configuration.xsd | 8 ++ .../config/impl/FileConfigurationTest.java | 1 + .../ConfigurationTest-full-config.xml | 1 + 17 files changed, 289 insertions(+), 5 deletions(-) create mode 100644 artemis-cli/src/test/resources/broker-reload.xml diff --git a/artemis-cli/src/test/java/org/apache/activemq/cli/test/FileBrokerTest.java b/artemis-cli/src/test/java/org/apache/activemq/cli/test/FileBrokerTest.java index 0feaf8fb7e..7e34ccdf29 100644 --- a/artemis-cli/src/test/java/org/apache/activemq/cli/test/FileBrokerTest.java +++ b/artemis-cli/src/test/java/org/apache/activemq/cli/test/FileBrokerTest.java @@ -16,14 +16,31 @@ */ package org.apache.activemq.cli.test; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.attribute.FileTime; + +import org.apache.activemq.artemis.api.core.client.ActiveMQClient; +import org.apache.activemq.artemis.api.core.client.ClientProducer; +import org.apache.activemq.artemis.api.core.client.ClientSession; +import org.apache.activemq.artemis.api.core.client.ClientSessionFactory; +import org.apache.activemq.artemis.api.core.client.ServerLocator; +import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration; import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl; import org.apache.activemq.artemis.dto.ServerDTO; import org.apache.activemq.artemis.integration.FileBroker; import org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl; import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager; +import org.apache.activemq.artemis.spi.core.security.jaas.InVMLoginModule; import org.junit.Assert; import org.junit.Test; +import static org.junit.Assert.fail; + public class FileBrokerTest { @Test @@ -71,4 +88,63 @@ public class FileBrokerTest { broker.stop(); } } + + @Test + public void testConfigFileReload() throws Exception { + ServerDTO serverDTO = new ServerDTO(); + serverDTO.configuration = "broker-reload.xml"; + FileBroker broker = null; + String path = null; + try { + SecurityConfiguration securityConfiguration = new SecurityConfiguration(); + securityConfiguration.addUser("myUser", "myPass"); + securityConfiguration.addRole("myUser", "guest"); + ActiveMQJAASSecurityManager securityManager = new ActiveMQJAASSecurityManager(InVMLoginModule.class.getName(), securityConfiguration); + broker = new FileBroker(serverDTO, securityManager); + broker.start(); + ActiveMQServerImpl activeMQServer = (ActiveMQServerImpl) broker.getComponents().get("core"); + Assert.assertNotNull(activeMQServer); + Assert.assertTrue(activeMQServer.isStarted()); + Assert.assertTrue(broker.isStarted()); + path = activeMQServer.getConfiguration().getConfigurationUrl().getPath(); + Assert.assertNotNull(activeMQServer.getConfiguration().getConfigurationUrl()); + + Thread.sleep(activeMQServer.getConfiguration().getConfigurationFileRefreshPeriod() * 2); + + ServerLocator locator = ActiveMQClient.createServerLocator("tcp://localhost:61616"); + ClientSessionFactory sf = locator.createSessionFactory(); + ClientSession session = sf.createSession("myUser", "myPass", false, true, false, false, 0); + ClientProducer producer = session.createProducer("jms.queue.DLQ"); + producer.send(session.createMessage(true)); + + replacePatternInFile(path, "guest", "X"); + + Thread.sleep(activeMQServer.getConfiguration().getConfigurationFileRefreshPeriod() * 2); + + try { + producer.send(session.createMessage(true)); + fail("Should throw a security exception"); + } + catch (Exception e) { + } + + locator.close(); + } + finally { + assert broker != null; + broker.stop(); + if (path != null) { + replacePatternInFile(path, "X", "guest"); + } + } + } + + private void replacePatternInFile(String file, String regex, String replacement) throws IOException { + Path path = Paths.get(file); + Charset charset = StandardCharsets.UTF_8; + String content = new String(Files.readAllBytes(path), charset); + String replaced = content.replaceAll(regex, replacement); + Files.write(path, replaced.getBytes(charset)); + Files.setLastModifiedTime(path, FileTime.fromMillis(System.currentTimeMillis())); + } } diff --git a/artemis-cli/src/test/resources/broker-reload.xml b/artemis-cli/src/test/resources/broker-reload.xml new file mode 100644 index 0000000000..3063f5f6a4 --- /dev/null +++ b/artemis-cli/src/test/resources/broker-reload.xml @@ -0,0 +1,76 @@ + + + + + + + + + + ./target/paging + + ./target/bindings + + ./target/journal + + 2 + + ./target/large-messages + + 500 + + + + tcp://${activemq.remoting.default.host:localhost}:${activemq.remoting.default.port:61616} + + + + + tcp://${activemq.remoting.default.host:localhost}:${activemq.remoting.default.port:61616} + + + tcp://${activemq.remoting.amqp.host:localhost}:${activemq.remoting.amqp.port:5672}?protocols=AMQP + + + tcp://${activemq.remoting.stomp.host:localhost}:${activemq.remoting.stomp.port:61613}?protocols=STOMP + + + tcp://${activemq.remoting.hornetq.host:localhost}:${activemq.remoting.hornetq.port:5445}?protocols=CORE,STOMP + + + + + + + + + + + + jms.queue.DLQ + jms.queue.ExpiryQueue + 0 + 10485760 + 10 + BLOCK + + + + 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 b95e5157ed..aecf90259c 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 @@ -426,6 +426,9 @@ public final class ActiveMQDefaultConfiguration { // Default period to wait between connection TTL checks public static final long DEFAULT_CONNECTION_TTL_CHECK_INTERVAL = 2000; + // Default period to wait between configuration file checks + public static final long DEFAULT_CONFIGURATION_FILE_REFRESH_PERIOD = 5000; + /** * If true then the ActiveMQ Artemis Server will make use of any Protocol Managers that are in available on the classpath. If false then only the core protocol will be available, unless in Embedded mode where users can inject their own Protocol Managers. */ @@ -1137,4 +1140,8 @@ public final class ActiveMQDefaultConfiguration { public static long getDefaultConnectionTtlCheckInterval() { return DEFAULT_CONNECTION_TTL_CHECK_INTERVAL; } + + public static long getDefaultConfigurationFileRefreshPeriod() { + return DEFAULT_CONFIGURATION_FILE_REFRESH_PERIOD; + } } diff --git a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/FileJMSConfiguration.java b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/FileJMSConfiguration.java index 0a657ebb3f..f17568d4fb 100644 --- a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/FileJMSConfiguration.java +++ b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/server/config/impl/FileJMSConfiguration.java @@ -33,6 +33,7 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.management.MBeanServer; +import java.net.URL; import java.util.ArrayList; import java.util.Map; @@ -57,7 +58,7 @@ public class FileJMSConfiguration extends JMSConfigurationImpl implements Deploy private boolean parsed = false; @Override - public void parse(Element config) throws Exception { + public void parse(Element config, URL url) throws Exception { parseConfiguration(config); parsed = true; } 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 400709ef1f..fc381551d5 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 @@ -17,6 +17,7 @@ package org.apache.activemq.artemis.core.config; import java.io.File; +import java.net.URL; import java.util.List; import java.util.Map; import java.util.Set; @@ -959,4 +960,12 @@ public interface Configuration { long getConnectionTtlCheckInterval(); + URL getConfigurationUrl(); + + Configuration setConfigurationUrl(URL configurationUrl); + + long getConfigurationFileRefreshPeriod(); + + Configuration setConfigurationFileRefreshPeriod(long configurationFileRefreshPeriod); + } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/FileDeploymentManager.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/FileDeploymentManager.java index abf0170ed1..0f9794afa9 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/FileDeploymentManager.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/FileDeploymentManager.java @@ -83,7 +83,7 @@ public class FileDeploymentManager { if (root != null && children.getLength() > 0) { Node item = children.item(0); XMLUtil.validate(item, deployable.getSchema()); - deployable.parse((Element) item); + deployable.parse((Element) item, url); } } } 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 8f1f6f5117..216348c6e4 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 @@ -26,6 +26,7 @@ import java.io.Serializable; import java.io.StringWriter; import java.lang.reflect.Array; import java.net.URI; +import java.net.URL; import java.security.AccessController; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; @@ -241,6 +242,10 @@ public class ConfigurationImpl implements Configuration, Serializable { private long connectionTtlCheckInterval = ActiveMQDefaultConfiguration.getDefaultConnectionTtlCheckInterval(); + private URL configurationUrl; + + private long configurationFileRefreshPeriod = ActiveMQDefaultConfiguration.getDefaultConfigurationFileRefreshPeriod(); + /** * Parent folder for all data folders. */ @@ -1759,6 +1764,28 @@ public class ConfigurationImpl implements Configuration, Serializable { return this; } + @Override + public URL getConfigurationUrl() { + return configurationUrl; + } + + @Override + public ConfigurationImpl setConfigurationUrl(URL configurationUrl) { + this.configurationUrl = configurationUrl; + return this; + } + + @Override + public long getConfigurationFileRefreshPeriod() { + return configurationFileRefreshPeriod; + } + + @Override + public ConfigurationImpl setConfigurationFileRefreshPeriod(long configurationFileRefreshPeriod) { + this.configurationFileRefreshPeriod = configurationFileRefreshPeriod; + return this; + } + /** * It will find the right location of a subFolder, related to artemisInstance */ 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 e0d9d4467b..b0c7440f87 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 @@ -16,6 +16,7 @@ */ package org.apache.activemq.artemis.core.config.impl; +import java.net.URL; import java.util.Map; import org.apache.activemq.artemis.core.deployers.Deployable; @@ -44,7 +45,7 @@ public final class FileConfiguration extends ConfigurationImpl implements Deploy private boolean parsed = false; @Override - public void parse(Element config) throws Exception { + public void parse(Element config, URL url) throws Exception { FileConfigurationParser parser = new FileConfigurationParser(); // https://jira.jboss.org/browse/HORNETQ-478 - We only want to validate AIO when @@ -54,6 +55,8 @@ public final class FileConfiguration extends ConfigurationImpl implements Deploy parser.parseMainConfig(config, this); + setConfigurationUrl(url); + parsed = true; } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/Deployable.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/Deployable.java index 7ab197e97d..20a0c2e8f2 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/Deployable.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/Deployable.java @@ -21,6 +21,7 @@ import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager; import org.w3c.dom.Element; import javax.management.MBeanServer; +import java.net.URL; import java.util.Map; /** @@ -32,7 +33,7 @@ public interface Deployable { /* * parse the element from the xml configuration */ - void parse(Element config) throws Exception; + void parse(Element config, URL url) throws Exception; /* * has this Deployable been parsed 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 5fdc9cab98..c77157bd72 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 @@ -280,6 +280,8 @@ public final class FileConfigurationParser extends XMLConfigurationUtil { config.setConnectionTtlCheckInterval(getLong(e, "connection-ttl-check-interval", config.getConnectionTtlCheckInterval(), Validators.GT_ZERO)); + config.setConfigurationFileRefreshPeriod(getLong(e, "configuration-file-refresh-period", config.getConfigurationFileRefreshPeriod(), Validators.GT_ZERO)); + // parsing cluster password String passwordText = getString(e, "cluster-password", null, Validators.NO_CHECK); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java index 51e6b423aa..342a592831 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQServerLogger.java @@ -1498,4 +1498,8 @@ public interface ActiveMQServerLogger extends BasicLogger { @LogMessage(level = Logger.Level.ERROR) @Message(id = 224068, value = "Unable to stop component: {0}", format = Message.Format.MESSAGE_FORMAT) void errorStoppingComponent(@Cause Throwable t, String componentClassName); + + @LogMessage(level = Logger.Level.ERROR) + @Message(id = 224069, value = "Change detected in broker configuration file, but reload failed", format = Message.Format.MESSAGE_FORMAT) + void configurationReloadFailed(@Cause Throwable t); } 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 9067f86f98..2a8bacffac 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 @@ -23,6 +23,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.management.ManagementFactory; +import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.ArrayList; @@ -55,6 +56,7 @@ import org.apache.activemq.artemis.core.config.CoreQueueConfiguration; import org.apache.activemq.artemis.core.config.DivertConfiguration; import org.apache.activemq.artemis.core.config.StoreConfiguration; import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl; +import org.apache.activemq.artemis.core.deployers.impl.FileConfigurationParser; import org.apache.activemq.artemis.core.filter.Filter; import org.apache.activemq.artemis.core.filter.impl.FilterImpl; import org.apache.activemq.artemis.core.io.IOCriticalErrorListener; @@ -450,6 +452,10 @@ public class ActiveMQServerImpl implements ActiveMQServer { // start connector service connectorsService = new ConnectorsService(configuration, storageManager, scheduledPool, postOffice, serviceRegistry); connectorsService.start(); + + if (configuration.getConfigurationUrl() != null && getScheduledPool() != null) { + getScheduledPool().scheduleWithFixedDelay(new ConfigurationFileReloader(this), configuration.getConfigurationFileRefreshPeriod(), configuration.getConfigurationFileRefreshPeriod(), TimeUnit.MILLISECONDS); + } } finally { // this avoids embedded applications using dirty contexts from startup @@ -2351,4 +2357,38 @@ public class ActiveMQServerImpl implements ActiveMQServer { } } + + private final class ConfigurationFileReloader extends Thread { + long lastModified; + boolean first = true; + ActiveMQServer server; + + ConfigurationFileReloader(ActiveMQServer server) { + this.server = server; + } + + public void run() { + try { + URL url = server.getConfiguration().getConfigurationUrl(); + long currentLastModified = new File(url.toURI()).lastModified(); + if (first) { + first = false; + lastModified = currentLastModified; + return; + } + if (currentLastModified > lastModified) { + if (ActiveMQServerLogger.LOGGER.isDebugEnabled()) { + ActiveMQServerLogger.LOGGER.debug("Configuration file change detected. Reloading..."); + } + Configuration config = new FileConfigurationParser().parseMainConfig(url.openStream()); + securityRepository.swap(config.getSecurityRoles().entrySet()); + + lastModified = currentLastModified; + } + } + catch (Exception e) { + ActiveMQServerLogger.LOGGER.configurationReloadFailed(e); + } + } + } } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/HierarchicalRepository.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/HierarchicalRepository.java index 6e2ba77f32..1e1c8c4ea9 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/HierarchicalRepository.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/HierarchicalRepository.java @@ -17,6 +17,8 @@ package org.apache.activemq.artemis.core.settings; import java.util.List; +import java.util.Map; +import java.util.Set; /** * allows objects to be mapped against a regex pattern and held in order in a list @@ -85,6 +87,8 @@ public interface HierarchicalRepository { */ void clear(); + void swap(Set> entries); + /** * Removes all listeners. */ diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/HierarchicalObjectRepository.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/HierarchicalObjectRepository.java index 5ec898e649..6e032d191c 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/HierarchicalObjectRepository.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/HierarchicalObjectRepository.java @@ -147,6 +147,10 @@ public class HierarchicalObjectRepository implements HierarchicalRepository implements HierarchicalRepository implements HierarchicalRepository> entries) { + lock.writeLock().lock(); + try { + clearCache(); + immutables.clear(); + matches.clear(); + for (Map.Entry entry : entries) { + addMatch(entry.getKey(), entry.getValue(), true, false); + } + } + finally { + lock.writeLock().unlock(); + } + + onChange(); + } + @Override public void clearListeners() { listeners.clear(); diff --git a/artemis-server/src/main/resources/schema/artemis-configuration.xsd b/artemis-server/src/main/resources/schema/artemis-configuration.xsd index 815ef7cea4..56c5e26c3c 100644 --- a/artemis-server/src/main/resources/schema/artemis-configuration.xsd +++ b/artemis-server/src/main/resources/schema/artemis-configuration.xsd @@ -246,6 +246,14 @@ + + + + how often (in ms) to check the configuration file for modifications + + + + diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java index 27c997fd37..ba2cb7f136 100644 --- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java +++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java @@ -104,6 +104,7 @@ public class FileConfigurationTest extends ConfigurationImplTest { Assert.assertEquals(12345, conf.getGracefulShutdownTimeout()); Assert.assertEquals(true, conf.isPopulateValidatedUser()); Assert.assertEquals(98765, conf.getConnectionTtlCheckInterval()); + Assert.assertEquals(1234567, conf.getConfigurationFileRefreshPeriod()); Assert.assertEquals("largemessagesdir", conf.getLargeMessagesDirectory()); Assert.assertEquals(95, conf.getMemoryWarningThreshold()); diff --git a/artemis-server/src/test/resources/ConfigurationTest-full-config.xml b/artemis-server/src/test/resources/ConfigurationTest-full-config.xml index 3639da4a93..78d55c2a14 100644 --- a/artemis-server/src/test/resources/ConfigurationTest-full-config.xml +++ b/artemis-server/src/test/resources/ConfigurationTest-full-config.xml @@ -52,6 +52,7 @@ true true 98765 + 1234567 org.apache.activemq.artemis.tests.unit.core.config.impl.TestInterceptor1 org.apache.activemq.artemis.tests.unit.core.config.impl.TestInterceptor2