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
      * 

Reply via email to