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 b64b654d23..7661df477e 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 @@ -682,6 +682,8 @@ public final class ActiveMQDefaultConfiguration { public static final long DEFAULT_EMBEDDED_WEB_SERVER_RESTART_TIMEOUT = 5000; + public static final String DEFAULT_LITERAL_MATCH_MARKERS = null; + /** * 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. */ @@ -1869,4 +1871,7 @@ public final class ActiveMQDefaultConfiguration { return DEFAULT_EMBEDDED_WEB_SERVER_RESTART_TIMEOUT; } + public static String getLiteralMatchMarkers() { + return DEFAULT_LITERAL_MATCH_MARKERS; + } } 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 686764a66c..4e8067866c 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 @@ -1457,4 +1457,8 @@ public interface Configuration { Eventually with some coordination we can update it from various server components. */ // Inspired by https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#:~:text=The%20status%20describes%20the%20current,the%20desired%20state%20you%20supplied void setStatus(String status); + + String getLiteralMatchMarkers(); + + Configuration setLiteralMatchMarkers(String literalMatchMarkers); } 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 ab1af3cbd6..5b70b38894 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 @@ -423,6 +423,8 @@ public class ConfigurationImpl implements Configuration, Serializable { private boolean suppressSessionNotifications = ActiveMQDefaultConfiguration.getDefaultSuppressSessionNotifications(); + private String literalMatchMarkers = ActiveMQDefaultConfiguration.getLiteralMatchMarkers(); + /** * Parent folder for all data folders. */ @@ -3194,6 +3196,17 @@ public class ConfigurationImpl implements Configuration, Serializable { this.jsonStatus = JsonUtil.mergeAndUpdate(getJsonStatus(), update); } + @Override + public String getLiteralMatchMarkers() { + return literalMatchMarkers; + } + + @Override + public Configuration setLiteralMatchMarkers(String literalMatchMarkers) { + this.literalMatchMarkers = literalMatchMarkers; + 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 { diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/Validators.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/Validators.java index a09f75d616..a21315201c 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/Validators.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/impl/Validators.java @@ -297,4 +297,14 @@ public final class Validators { } } }; + + public static final Validator NULL_OR_TWO_CHARACTERS = new Validator() { + @Override + public void validate(final String name, final Object value) { + String val = (String) value; + if (val != null && val.length() != 2) { + throw ActiveMQMessageBundle.BUNDLE.wrongLength(name, val, val.length(), 2); + } + } + }; } 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 61d9b37f4b..3f2649657b 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 @@ -810,6 +810,8 @@ public final class FileConfigurationParser extends XMLConfigurationUtil { config.setSuppressSessionNotifications(getBoolean(e, "suppress-session-notifications", config.isSuppressSessionNotifications())); + config.setLiteralMatchMarkers(getString(e, "literal-match-markers", config.getLiteralMatchMarkers(), Validators.NULL_OR_TWO_CHARACTERS)); + parseAddressSettings(e, config); parseResourceLimits(e, config); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java index 36477dd974..6085115820 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ActiveMQMessageBundle.java @@ -542,4 +542,7 @@ public interface ActiveMQMessageBundle { @Message(id = 229250, value = "Connection has been marked as destroyed for remote connection {}.") ActiveMQException connectionDestroyed(String remoteAddress); + + @Message(id = 229251, value = "{} value '{}' is too long. It is {} characters but must be {} characters.") + IllegalArgumentException wrongLength(String name, String val, int actualLength, int requiredLength); } 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 4a14e9548d..f18cf27e67 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 @@ -494,7 +494,7 @@ public class ActiveMQServerImpl implements ActiveMQServer { public String modify(String input) { return CompositeAddress.extractAddressName(input); } - }); + }, this.configuration.getLiteralMatchMarkers()); addressSettingsRepository.setDefault(new AddressSettings()); 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 852ef26b6c..9b8247d8bf 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 @@ -33,13 +33,30 @@ public interface HierarchicalRepository { /** * Add a new match to the repository * - * @param match The regex to use to match against + * @param match the pattern to use to match against * @param value the value to hold against the match */ void addMatch(String match, T value); + /** + * Add a new match to the repository + * + * @param match the pattern to use to match against + * @param value the value to hold against the match + * @param immutableMatch + */ void addMatch(String match, T value, boolean immutableMatch); + /** + * Add a new match to the repository + * + * @param match the pattern to use to match against + * @param value the value to hold against the match + * @param immutableMatch whether this match can be removed + * @param notifyListeners whether to notify any listeners that the match has been added + */ + void addMatch(String match, T value, boolean immutableMatch, boolean notifyListeners); + /** * return the value held against the nearest match * 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 a202c0f366..d63a1a9172 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 @@ -17,6 +17,7 @@ package org.apache.activemq.artemis.core.settings.impl; import java.io.Serializable; +import java.lang.invoke.MethodHandles; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -38,7 +39,6 @@ import org.apache.activemq.artemis.core.settings.HierarchicalRepositoryChangeLis import org.apache.activemq.artemis.core.settings.Mergeable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.lang.invoke.MethodHandles; /** * allows objects to be mapped against a regex pattern and held in order in a list @@ -60,6 +60,7 @@ public class HierarchicalObjectRepository implements HierarchicalRepository> wildcardMatches = new HashMap<>(); private final Map> exactMatches = new HashMap<>(); + private final Map> literalMatches = new HashMap<>(); /** * Certain values cannot be removed after installed. @@ -79,6 +80,12 @@ public class HierarchicalObjectRepository implements HierarchicalRepository implements HierarchicalRepository implements HierarchicalRepository values() { lock.readLock().lock(); try { - ArrayList values = new ArrayList<>(wildcardMatches.size() + exactMatches.size()); + ArrayList values = new ArrayList<>(wildcardMatches.size() + exactMatches.size() + literalMatches.size()); for (Match matchValue : wildcardMatches.values()) { values.add(matchValue.getValue()); @@ -160,27 +171,39 @@ public class HierarchicalObjectRepository implements HierarchicalRepository matchValue : literalMatches.values()) { + values.add(matchValue.getValue()); + } + return values; } finally { lock.readLock().unlock(); } } - /** - * Add a new match to the repository - * - * @param match The regex to use to match against - * @param value the value to hold against the match - */ + @Override + public void addMatch(final String match, final T value) { + addMatch(match, value, false); + } + @Override public void addMatch(final String match, final T value, final boolean immutableMatch) { addMatch(match, value, immutableMatch, true); } - private void addMatch(final String match, final T value, final boolean immutableMatch, boolean notifyListeners) { + @Override + public void addMatch(final String match, final T value, final boolean immutableMatch, final boolean notifyListeners) { + String modifiedMatch = match; + boolean literal = false; + if (checkLiteral) { + literal = match.charAt(0) == literalMatchMarkerStart && match.charAt(match.length() - 1) == literalMatchMarkerEnd; + if (literal) { + modifiedMatch = match.substring(1, match.length() - 1); + } + } + modifiedMatch = matchModifier.modify(modifiedMatch); lock.writeLock().lock(); try { - String modifiedMatch = matchModifier.modify(match); // an exact match (i.e. one without wildcards) won't impact any other matches so no need to clear the cache if (usesWildcards(modifiedMatch)) { clearCache(); @@ -192,8 +215,10 @@ public class HierarchicalObjectRepository implements HierarchicalRepository match1 = new Match<>(modifiedMatch, value, wildcardConfiguration); - if (usesWildcards(modifiedMatch)) { + Match match1 = new Match<>(modifiedMatch, value, wildcardConfiguration, literal); + if (literal) { + literalMatches.put(modifiedMatch, match1); + } else if (usesWildcards(modifiedMatch)) { wildcardMatches.put(modifiedMatch, match1); } else { exactMatches.put(modifiedMatch, match1); @@ -272,6 +297,9 @@ public class HierarchicalObjectRepository implements HierarchicalRepository implements HierarchicalRepository implements HierarchicalRepository implements HierarchicalRepository implements HierarchicalRepository { private final T value; + private final boolean literal; + public Match(final String match, final T value, final WildcardConfiguration wildcardConfiguration) { + this(match, value, wildcardConfiguration, false); + } + + public Match(final String match, final T value, final WildcardConfiguration wildcardConfiguration, final boolean literal) { this.match = match; this.value = value; pattern = createPattern(match, wildcardConfiguration, false); + this.literal = literal; } /** @@ -93,6 +100,10 @@ public class Match { return value; } + public final boolean isLiteral() { + return literal; + } + @Override public boolean equals(final Object o) { if (this == o) { diff --git a/artemis-server/src/main/resources/schema/artemis-configuration.xsd b/artemis-server/src/main/resources/schema/artemis-configuration.xsd index 04ed98588c..6186ff923e 100644 --- a/artemis-server/src/main/resources/schema/artemis-configuration.xsd +++ b/artemis-server/src/main/resources/schema/artemis-configuration.xsd @@ -909,6 +909,16 @@ + + + + The characters that mark a "literal" match. A literal match means the setting(s) will only apply to + the exact match regardless of wildcards. If this setting is not omitted then it must be two + characters - the start marker and the end marker. + + + + diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java index 4d78adc872..57e3d1a6c1 100644 --- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java +++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationParserTest.java @@ -443,6 +443,17 @@ public class FileConfigurationParserTest extends ActiveMQTestBase { Assert.assertEquals(-1, settings.getMaxReadPageMessages()); } + @Test + public void testLiteralMatchMarkers() throws Exception { + String configStr = "()\n\n-1\n\n"; + + FileConfigurationParser parser = new FileConfigurationParser(); + ByteArrayInputStream input = new ByteArrayInputStream(configStr.getBytes(StandardCharsets.UTF_8)); + + Configuration configuration = parser.parseMainConfig(input); + Assert.assertEquals("()", configuration.getLiteralMatchMarkers()); + } + // you should not use K, M notations on address settings max-size-messages @Test public void testExpectedErrorOverMaxMessageNotation() throws Exception { 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 791ae9273d..caa377e01b 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 @@ -152,6 +152,7 @@ public class FileConfigurationTest extends ConfigurationImplTest { Assert.assertEquals(false, conf.isCreateBindingsDir()); Assert.assertEquals(true, conf.isAmqpUseCoreSubscriptionNaming()); Assert.assertEquals(false, conf.isSuppressSessionNotifications()); + Assert.assertEquals("()", conf.getLiteralMatchMarkers()); Assert.assertEquals("max concurrent io", 17, conf.getPageMaxConcurrentIO()); Assert.assertEquals(true, conf.isReadWholePage()); diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ValidatorsTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ValidatorsTest.java index 6166e07d31..14598fd9b1 100644 --- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ValidatorsTest.java +++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/ValidatorsTest.java @@ -30,7 +30,7 @@ public class ValidatorsTest extends Assert { private static void failure(final Validators.Validator validator, final Object value) { try { validator.validate(RandomUtil.randomString(), value); - Assert.fail(validator + " must not validate " + value); + Assert.fail(validator + " must not validate '" + value + "'"); } catch (IllegalArgumentException e) { } @@ -141,4 +141,14 @@ public class ValidatorsTest extends Assert { ValidatorsTest.failure(Validators.MINUS_ONE_OR_POSITIVE_INT, Integer.MAX_VALUE + 1); } + @Test + public void testTWO_CHARACTERS() { + ValidatorsTest.failure(Validators.NULL_OR_TWO_CHARACTERS, "1234"); + ValidatorsTest.failure(Validators.NULL_OR_TWO_CHARACTERS, "123"); + ValidatorsTest.failure(Validators.NULL_OR_TWO_CHARACTERS, "1"); + + ValidatorsTest.success(Validators.NULL_OR_TWO_CHARACTERS, "12"); + ValidatorsTest.success(Validators.NULL_OR_TWO_CHARACTERS, null); + } + } diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/settings/RepositoryTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/settings/RepositoryTest.java index e293d2bc55..e4389748b8 100644 --- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/settings/RepositoryTest.java +++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/settings/RepositoryTest.java @@ -24,6 +24,7 @@ import org.apache.activemq.artemis.core.config.WildcardConfiguration; import org.apache.activemq.artemis.core.security.Role; import org.apache.activemq.artemis.core.settings.impl.HierarchicalObjectRepository; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -40,6 +41,14 @@ public class RepositoryTest extends ActiveMQTestBase { securityRepository = new HierarchicalObjectRepository<>(); } + @Override + @After + public void tearDown() throws Exception { + super.tearDown(); + + DummyMergeable.reset(); + } + @Test public void testDefault() { securityRepository.setDefault(new HashSet()); @@ -65,6 +74,32 @@ public class RepositoryTest extends ActiveMQTestBase { Assert.assertEquals("abd#", repo.getMatch("a.b.d")); } + /* + * A "literal" match is one which uses wild-cards but should not be applied to other matches "below" it in the hierarchy. + */ + @Test + public void testLiteral() { + HierarchicalObjectRepository repo = new HierarchicalObjectRepository<>(null, new HierarchicalObjectRepository.MatchModifier() { }, "()"); + + repo.addMatch("#", new DummyMergeable(0)); + repo.addMatch("(a.#)", new DummyMergeable(1)); + repo.addMatch("a.#", new DummyMergeable(2)); + repo.addMatch("a.b", new DummyMergeable(3)); + + repo.getMatch("a.b"); + assertTrue(DummyMergeable.contains(0)); + assertFalse(DummyMergeable.contains(1)); + assertTrue(DummyMergeable.contains(2)); + assertTrue(DummyMergeable.contains(3)); + + DummyMergeable.reset(); + repo.getMatch("a.#"); + assertTrue(DummyMergeable.contains(0)); + assertTrue(DummyMergeable.contains(1)); + assertFalse(DummyMergeable.contains(2)); + assertFalse(DummyMergeable.contains(3)); + } + @Test public void testCacheWithWildcards() throws Throwable { HierarchicalObjectRepository repo = new HierarchicalObjectRepository<>(); diff --git a/artemis-server/src/test/resources/ConfigurationTest-full-config.xml b/artemis-server/src/test/resources/ConfigurationTest-full-config.xml index caa686891a..325e4eacc4 100644 --- a/artemis-server/src/test/resources/ConfigurationTest-full-config.xml +++ b/artemis-server/src/test/resources/ConfigurationTest-full-config.xml @@ -69,6 +69,7 @@ 777 false false + () org.apache.activemq.artemis.tests.unit.core.config.impl.TestInterceptor1 org.apache.activemq.artemis.tests.unit.core.config.impl.TestInterceptor2 diff --git a/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml b/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml index 8c88127555..4870e370eb 100644 --- a/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml +++ b/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml @@ -68,6 +68,7 @@ 333 777 false + () org.apache.activemq.artemis.tests.unit.core.config.impl.TestInterceptor1 org.apache.activemq.artemis.tests.unit.core.config.impl.TestInterceptor2 diff --git a/artemis-server/src/test/resources/ConfigurationTest-xinclude-schema-config.xml b/artemis-server/src/test/resources/ConfigurationTest-xinclude-schema-config.xml index 773910cb43..be0641fc9a 100644 --- a/artemis-server/src/test/resources/ConfigurationTest-xinclude-schema-config.xml +++ b/artemis-server/src/test/resources/ConfigurationTest-xinclude-schema-config.xml @@ -68,6 +68,7 @@ 333 777 false + () true diff --git a/docs/user-manual/address-settings.adoc b/docs/user-manual/address-settings.adoc index ef922d3564..17de2ba614 100644 --- a/docs/user-manual/address-settings.adoc +++ b/docs/user-manual/address-settings.adoc @@ -5,14 +5,16 @@ With address settings you can provide a block of settings which will be applied to any addresses that match the string in the `match` attribute. In the below example the settings would only be applied to the address `order.foo` address, but it is also possible to use xref:wildcard-syntax.adoc#wildcard-syntax[wildcards] to apply settings. -For example, if you used the `match` string `queue.#` the settings would be applied to all addresses which start with `queue.` +For example, if you used the `match` string `queue.#` the settings would be applied to _all_ addresses which start with `queue.`. Address settings are *hierarchical*. Therefore, if more than one `address-setting` would match then the settings are applied in order of their specificity with the more specific match taking priority. -A match on the any-words delimiter (`#`) is considered less specific than a match without it. -A match with a single word delimiter `*` is considered less specific than a match on an exact queue name. +A match on the any-words delimiter (`#` by default) is considered less specific than a match without it. +A match with a single word delimiter (`*` by default) is considered less specific than a match on an exact queue name. In this way settings can be "layered" so that configuration details don't need to be repeated. +Address setting matches can also be "literal" which can be used to interrupt the hierarchy in useful ways. + The meaning of the specific settings are explained fully throughout the user manual, however here is a brief description with a link to the appropriate chapter if available. Here an example of an `address-setting` entry that might be found in the `broker.xml` file. @@ -389,3 +391,39 @@ defines the maximum size of the duplicate ID cache for an address, as each addre that helps to detect and prevent the processing of duplicate messages based on their unique identification. By default, the `id-cache-size` setting inherits from the global `id-cache-size`, with a default of `20000` elements if not explicitly configured. Read more about xref:duplicate-detection.adoc#configuring-the-duplicate-id-cache[duplicate id cache sizes]. + +## Literal Matches + +A _literal_ match is a match that contains wildcards but should be applied _without regard_ to those wildcards. In other words, the wildcards should be ignored and the address settings should only be applied to the literal (i.e. exact) match. + +This can be useful when an application uses a xref:wildcard-routing.adoc[wildcard address]. For example, if an application creates a multicast queue on the address `orders.#` and that queue needs a different configuration than other matching addresses like `orders.retail` and `orders.wholesale`. Generally speaking this kind of use-case is rare, but wildcard addresses are often used by MQTT clients, and this kind of configuration flexiblity is useful. + +### Configuring a Literal Match + +If you want to configure a literal match the first thing to do is to configure the `literal-match-markers` parameter in `broker.xml`. This defines the beginning and ending characters used to mark the literal match, e.g.: + +[,xml] +---- + + ... + () + ... + +---- + +By default, no value is defined for `literal-match-markers` which means that literal matches are disabled by default. The value must be only 2 characters. + +Once `literal-match-markers` is defined you can then use those markers in the `match` of the address setting, e.g. + +[,xml] +---- + + + true + + + false + + +---- +Using these settings metrics will be enabled on the address `orders.#` and any queues bound directly on that address, but metrics will _not_ be enabled for other matching addresses like `orders.retail` or `orders.wholesale` and any queues bound to those addresses. \ No newline at end of file diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/AddressSettingsTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/AddressSettingsTest.java index e563fca513..b8d8b14e25 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/AddressSettingsTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/AddressSettingsTest.java @@ -24,10 +24,12 @@ 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.Configuration; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.core.settings.HierarchicalRepository; import org.apache.activemq.artemis.core.settings.impl.AddressSettings; import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; +import org.apache.activemq.artemis.tests.util.RandomUtil; import org.junit.Assert; import org.junit.Test; @@ -113,6 +115,26 @@ public class AddressSettingsTest extends ActiveMQTestBase { } + @Test + public void testLiteralMatch() throws Exception { + final SimpleString literal = RandomUtil.randomSimpleString(); + final SimpleString nonLiteral = RandomUtil.randomSimpleString(); + + Configuration configuration = createDefaultConfig(false); + configuration.setLiteralMatchMarkers("()"); + ActiveMQServer server = createServer(false, configuration); + server.start(); + HierarchicalRepository repo = server.getAddressSettingsRepository(); + repo.addMatch("(foo.#)", new AddressSettings().setDeadLetterAddress(literal)); + repo.addMatch("foo.#", new AddressSettings().setDeadLetterAddress(nonLiteral)); + + // should be the DLA from foo.# - the literal match + Assert.assertEquals(literal, repo.getMatch("foo.#").getDeadLetterAddress()); + + Assert.assertEquals(nonLiteral, repo.getMatch("foo.bar").getDeadLetterAddress()); + + } + @Test public void test2LevelHierarchyWithDLA() throws Exception { ActiveMQServer server = createServer(false);