ARTEMIS-4270 Allow hierarchy of wildcard bindings

In case the bindings "news.#" and "news.europe.#" are registered, only the first one matches with the address "news.europe" while both are supposed to match. Those changes are meant to get rid of this limitation.
This commit is contained in:
Nicolas Filotto 2023-09-14 18:40:00 +02:00 committed by Justin Bertram
parent 09cc76c7e8
commit 1d3fd65008
3 changed files with 97 additions and 11 deletions

View File

@ -225,10 +225,9 @@ public final class AddressPartNode<T> {
// non wildcard paths, match any expanded wildcards in the map
public void visitMatchingWildcards(final String[] paths, final int startIndex, final AddressMapVisitor<T> collector) throws Exception {
boolean canVisitAnyDescendent = true;
AddressPartNode<T> node = this;
AddressPartNode<T> anyDescendentNode = null;
AddressPartNode<T> anyChildNode = null;
AddressPartNode<T> anyDescendentNode;
AddressPartNode<T> anyChildNode;
final int size = paths.length;
for (int i = startIndex; i < size && node != null; i++) {
@ -240,7 +239,6 @@ public final class AddressPartNode<T> {
anyDescendentNode.visitValues(collector);
// match tail with current path, such that ANY_DESCENDENT can match zero
anyDescendentNode.visitPathTailMatch(paths, i, collector);
canVisitAnyDescendent = false;
}
anyChildNode = node.getChild(ANY_CHILD);
@ -260,13 +258,10 @@ public final class AddressPartNode<T> {
node.visitValues(collector);
if (canVisitAnyDescendent) {
// allow zero node any descendant at the end of path node
anyDescendentNode = node.getChild(ANY_DESCENDENT);
if (anyDescendentNode != null) {
anyDescendentNode.visitValues(collector);
}
// allow zero node any descendant at the end of path node
anyDescendentNode = node.getChild(ANY_DESCENDENT);
if (anyDescendentNode != null) {
anyDescendentNode.visitValues(collector);
}
}
}

View File

@ -24,6 +24,8 @@ import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.StreamMessage;
import javax.jms.TextMessage;
import javax.jms.Topic;
import java.lang.invoke.MethodHandles;
@ -253,6 +255,42 @@ public class MessageTest extends JMSTestBase {
}
}
/**
* @see <a href="https://issues.apache.org/jira/browse/ARTEMIS-4270">ARTEMIS-4270</a>
*/
@Test
public void testWildcardRoutingHierarchyWithMultipleConsumers() throws Exception {
Topic parentTopic = createTopic(true, "a.#");
Topic childTopic = createTopic(true, "a.b.#");
try (Connection conn = cf.createConnection()) {
conn.start();
try (Session session = conn.createSession(false, Session.CLIENT_ACKNOWLEDGE)) {
MessageConsumer parentConsumer = session.createConsumer(parentTopic);
MessageConsumer childConsumer = session.createConsumer(childTopic);
MessageProducer producer = session.createProducer(null);
producer.send(session.createTopic("a.b.c"), session.createTextMessage("m1"));
producer.send(session.createTopic("a.b"), session.createTextMessage("m2"));
Message m = parentConsumer.receive(5_000);
assertTrue(m instanceof TextMessage);
assertEquals("m1", ((TextMessage) m).getText());
m = parentConsumer.receive(5_000);
assertTrue(m instanceof TextMessage);
assertEquals("m2", ((TextMessage) m).getText());
m = childConsumer.receive(5_000);
assertTrue(m instanceof TextMessage);
assertEquals("m1", ((TextMessage) m).getText());
m = childConsumer.receive(5_000);
assertTrue(m instanceof TextMessage);
assertEquals("m2", ((TextMessage) m).getText());
}
}
}
// https://issues.jboss.org/browse/HORNETQ-988
@Test
public void testShouldNotThrowException() throws Exception {

View File

@ -221,6 +221,59 @@ public class WildcardAddressManagerUnitTest extends ActiveMQTestBase {
}
@Test
public void testSingleWordWildCardAddressBindingsForRouting() throws Exception {
WildcardAddressManager ad = new WildcardAddressManager(new BindingFactoryFake(), null, null);
ad.addAddressInfo(new AddressInfo(SimpleString.toSimpleString("news.*"), RoutingType.MULTICAST));
ad.addAddressInfo(new AddressInfo(SimpleString.toSimpleString("news.*.sport"), RoutingType.MULTICAST));
ad.addBinding(new BindingFake("news.*", "one"));
ad.addBinding(new BindingFake("news.*.sport", "two"));
Collection<Binding> bindings = ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe")).getBindings();
assertEquals(1, bindings.size());
assertEquals("one", bindings.iterator().next().getUniqueName().toString());
bindings = ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.usa")).getBindings();
assertEquals(1, bindings.size());
assertEquals("one", bindings.iterator().next().getUniqueName().toString());
bindings = ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe.sport")).getBindings();
assertEquals(1, bindings.size());
assertEquals("two", bindings.iterator().next().getUniqueName().toString());
bindings = ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.usa.sport")).getBindings();
assertEquals(1, bindings.size());
assertEquals("two", bindings.iterator().next().getUniqueName().toString());
assertNull(ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe.fr.sport")));
}
@Test
public void testAnyWordsWildCardAddressBindingsForRouting() throws Exception {
WildcardAddressManager ad = new WildcardAddressManager(new BindingFactoryFake(), null, null);
ad.addAddressInfo(new AddressInfo(SimpleString.toSimpleString("news.europe.#"), RoutingType.MULTICAST));
ad.addBinding(new BindingFake("news.europe.#", "one"));
assertEquals(1, ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe")).getBindings().size());
assertEquals(1, ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe.sport")).getBindings().size());
assertEquals(1, ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe.politics.fr")).getBindings().size());
assertNull(ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.usa")));
assertNull(ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("europe")));
}
@Test
public void testAnyWordsMultipleWildCardsAddressBindingsForRouting() throws Exception {
WildcardAddressManager ad = new WildcardAddressManager(new BindingFactoryFake(), null, null);
ad.addAddressInfo(new AddressInfo(SimpleString.toSimpleString("news.#"), RoutingType.MULTICAST));
ad.addAddressInfo(new AddressInfo(SimpleString.toSimpleString("news.europe.#"), RoutingType.MULTICAST));
ad.addBinding(new BindingFake("news.#", "one"));
ad.addBinding(new BindingFake("news.europe.#", "two"));
assertEquals(2, ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe")).getBindings().size());
assertEquals(2, ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe.sport")).getBindings().size());
assertEquals(2, ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.europe.politics.fr")).getBindings().size());
Collection<Binding> bindings = ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("news.usa")).getBindings();
assertEquals(1, bindings.size());
assertEquals("one", bindings.iterator().next().getUniqueName().toString());
assertNull(ad.getBindingsForRoutingAddress(SimpleString.toSimpleString("europe")));
}
@Test
public void testNumberOfBindingsThatMatch() throws Exception {