This is an automated email from the ASF dual-hosted git repository. timothyjward pushed a commit to branch fix/tck in repository https://gitbox.apache.org/repos/asf/aries-typedevent.git
commit 0f0080d4f1b9f98918005bbf9143568b6cdd55c6 Author: Tim Ward <[email protected]> AuthorDate: Thu Jan 15 11:03:50 2026 +0000 Properly validate topics, topic filters, and events for null and syntax The specification requires that null and invalid topics are rejected with particular exception types. This commit ensures that the proper checks are made in all cases. Signed-off-by: Tim Ward <[email protected]> --- .../typedevent/bus/impl/TypedEventBusImpl.java | 17 ++++++++--- .../typedevent/bus/impl/TypedEventMonitorImpl.java | 9 +++--- .../typedevent/bus/impl/TypedEventBusImplTest.java | 33 ++++++++++++++++++++++ .../bus/impl/TypedEventMonitorImplTest.java | 33 ++++++++++++++++++++++ 4 files changed, 84 insertions(+), 8 deletions(-) diff --git a/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImpl.java b/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImpl.java index 02cfc37..9db87b6 100644 --- a/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImpl.java +++ b/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImpl.java @@ -625,13 +625,22 @@ public class TypedEventBusImpl implements TypedEventBus, AriesTypedEvents { } static void checkTopicSyntax(String topic) { + Objects.requireNonNull(topic, "The topic name must not be null"); String msg = checkTopicSyntax(topic, false); if(msg != null) { throw new IllegalArgumentException(msg); } } + + static void checkTopicFilterSyntax(String topic) { + Objects.requireNonNull(topic, "The topic filter must not be null"); + String msg = checkTopicSyntax(topic, true); + if(msg != null) { + throw new IllegalArgumentException(msg); + } + } - static String checkTopicSyntax(String topic, boolean wildcardPermitted) { + private static String checkTopicSyntax(String topic, boolean wildcardPermitted) { if(topic == null) { throw new IllegalArgumentException("The topic name is not permitted to be null"); @@ -740,15 +749,13 @@ public class TypedEventBusImpl implements TypedEventBus, AriesTypedEvents { @Override public <T> TypedEventPublisher<T> createPublisher(String topic, Class<T> eventType) { - Objects.requireNonNull(topic, "The event topic must not be null"); - Objects.requireNonNull(eventType, "The event type must not be null"); checkTopicSyntax(topic); + Objects.requireNonNull(eventType, "The event type must not be null"); return new TypedEventPublisherImpl<>(topic); } @Override public TypedEventPublisher<Object> createPublisher(String topic) { - Objects.requireNonNull(topic, "The event topic must not be null"); checkTopicSyntax(topic); return new TypedEventPublisherImpl<>(topic); } @@ -772,12 +779,14 @@ public class TypedEventBusImpl implements TypedEventBus, AriesTypedEvents { @Override public void deliver(T event) { checkOpen(); + Objects.requireNonNull(event); TypedEventBusImpl.this.deliver(topic, event, EventConverter::forTypedEvent); } @Override public void deliverUntyped(Map<String, ?> event) { checkOpen(); + Objects.requireNonNull(event); TypedEventBusImpl.this.deliver(topic, event, EventConverter::forUntypedEvent); } diff --git a/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventMonitorImpl.java b/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventMonitorImpl.java index 8a245ff..f4fec92 100644 --- a/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventMonitorImpl.java +++ b/org.apache.aries.typedevent.bus/src/main/java/org/apache/aries/typedevent/bus/impl/TypedEventMonitorImpl.java @@ -257,14 +257,14 @@ public class TypedEventMonitorImpl implements TypedEventMonitor { @Override public Predicate<String> topicFilterMatches(String topicFilter) { - TypedEventBusImpl.checkTopicSyntax(topicFilter, true); + TypedEventBusImpl.checkTopicFilterSyntax(topicFilter); EventSelector selector = new EventSelector(topicFilter, null); return selector::matchesTopic; } @Override public boolean topicFilterMatches(String topicName, String topicFilter) { - TypedEventBusImpl.checkTopicSyntax(topicFilter, true); + TypedEventBusImpl.checkTopicFilterSyntax(topicFilter); TypedEventBusImpl.checkTopicSyntax(topicName); EventSelector selector = new EventSelector(topicFilter, null); return selector.matchesTopic(topicName); @@ -291,7 +291,7 @@ public class TypedEventMonitorImpl implements TypedEventMonitor { @Override public RangePolicy getConfiguredHistoryStorage(String topicFilter) { - TypedEventBusImpl.checkTopicSyntax(topicFilter, true); + TypedEventBusImpl.checkTopicFilterSyntax(topicFilter); EventSelector selector = new EventSelector(topicFilter, null); lock.readLock().lock(); try { @@ -326,7 +326,7 @@ public class TypedEventMonitorImpl implements TypedEventMonitor { if(policy.getMinimum() > 0) { TypedEventBusImpl.checkTopicSyntax(topicFilter); } else { - TypedEventBusImpl.checkTopicSyntax(topicFilter, true); + TypedEventBusImpl.checkTopicFilterSyntax(topicFilter); } EventSelector key = new EventSelector(topicFilter, null); @@ -380,6 +380,7 @@ public class TypedEventMonitorImpl implements TypedEventMonitor { @Override public void removeHistoryStorage(String topicFilter) { + TypedEventBusImpl.checkTopicFilterSyntax(topicFilter); EventSelector selector = new EventSelector(topicFilter, null); lock.readLock().lock(); try { diff --git a/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImplTest.java b/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImplTest.java index 4bb1470..608187c 100644 --- a/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImplTest.java +++ b/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/impl/TypedEventBusImplTest.java @@ -138,7 +138,37 @@ public class TypedEventBusImplTest { impl.stop(); monitorImpl.destroy(); } + + /** + * Tests that null topics and filters are disallowed + * + * @throws InterruptedException + */ + @Test + public void testNullTopicsAndFilters() throws InterruptedException { + assertThrows(NullPointerException.class, () -> impl.createPublisher((String) null)); + assertThrows(NullPointerException.class, () -> impl.createPublisher(null, TestEvent.class)); + assertThrows(NullPointerException.class, () -> impl.deliver(null, new TestEvent())); + assertThrows(NullPointerException.class, () -> impl.deliverUntyped(null, new HashMap<>())); + } + /** + * Tests that illegal topics and filters are disallowed + * + * @throws InterruptedException + */ + @Test + public void testIllegalTopicsAndFilters() throws InterruptedException { + assertThrows(IllegalArgumentException.class, () -> impl.createPublisher("//")); + assertThrows(IllegalArgumentException.class, () -> impl.createPublisher("//", TestEvent.class)); + assertThrows(IllegalArgumentException.class, () -> impl.deliver("//", new TestEvent())); + assertThrows(IllegalArgumentException.class, () -> impl.deliverUntyped("//", null)); + assertThrows(IllegalArgumentException.class, () -> impl.createPublisher("+")); + assertThrows(IllegalArgumentException.class, () -> impl.createPublisher("+", TestEvent.class)); + assertThrows(IllegalArgumentException.class, () -> impl.deliver("+", new TestEvent())); + assertThrows(IllegalArgumentException.class, () -> impl.deliverUntyped("+", null)); + } + /** * Tests that events are delivered to Smart Behaviours based on type * @@ -695,6 +725,9 @@ public class TypedEventBusImplTest { TypedEventPublisher<TestEvent> publisher = impl.createPublisher(TestEvent.class); + assertThrows(NullPointerException.class, () -> publisher.deliver(null)); + assertThrows(NullPointerException.class, () -> publisher.deliverUntyped(null)); + publisher.deliver(event); assertTrue(semA.tryAcquire(1, TimeUnit.SECONDS)); diff --git a/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/impl/TypedEventMonitorImplTest.java b/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/impl/TypedEventMonitorImplTest.java index fcc2de8..8b286bb 100644 --- a/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/impl/TypedEventMonitorImplTest.java +++ b/org.apache.aries.typedevent.bus/src/test/java/org/apache/aries/typedevent/bus/impl/TypedEventMonitorImplTest.java @@ -51,6 +51,39 @@ public class TypedEventMonitorImplTest { monitorImpl.destroy(); } + /** + * Tests that null topics and filters are disallowed + * + * @throws InterruptedException + */ + @Test + public void testNullTopicsAndFilters() throws InterruptedException { + assertThrows(NullPointerException.class, () -> monitorImpl.configureHistoryStorage(null, RangePolicy.exact(1))); + assertThrows(NullPointerException.class, () -> monitorImpl.getConfiguredHistoryStorage(null)); + assertThrows(NullPointerException.class, () -> monitorImpl.getEffectiveHistoryStorage(null)); + assertThrows(NullPointerException.class, () -> monitorImpl.removeHistoryStorage(null)); + assertThrows(NullPointerException.class, () -> monitorImpl.topicFilterMatches(null)); + assertThrows(NullPointerException.class, () -> monitorImpl.topicFilterMatches(null, TOPIC_PATTERN_MULTI)); + assertThrows(NullPointerException.class, () -> monitorImpl.topicFilterMatches(TOPIC, null)); + } + + /** + * Tests that illegal topics and filters are disallowed + * + * @throws InterruptedException + */ + @Test + public void testIllegalTopicsAndFilters() throws InterruptedException { + assertThrows(IllegalArgumentException.class, () -> monitorImpl.configureHistoryStorage("//", RangePolicy.exact(1))); + assertThrows(IllegalArgumentException.class, () -> monitorImpl.getConfiguredHistoryStorage("//")); + assertThrows(IllegalArgumentException.class, () -> monitorImpl.getEffectiveHistoryStorage("//")); + assertThrows(IllegalArgumentException.class, () -> monitorImpl.removeHistoryStorage("//")); + assertThrows(IllegalArgumentException.class, () -> monitorImpl.topicFilterMatches("//")); + assertThrows(IllegalArgumentException.class, () -> monitorImpl.topicFilterMatches("//", TOPIC_PATTERN_MULTI)); + assertThrows(IllegalArgumentException.class, () -> monitorImpl.topicFilterMatches(TOPIC, "//")); + assertThrows(IllegalArgumentException.class, () -> monitorImpl.configureHistoryStorage("+", RangePolicy.exact(1))); + } + /** * Tests that history configuration works for topics *
