This is an automated email from the ASF dual-hosted git repository.

cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git


The following commit(s) were added to refs/heads/master by this push:
     new beb63f6f6 GH-1668: Add catch-all for group filter (#1694)
beb63f6f6 is described below

commit beb63f6f62a0a739ea225d4206caafc2bbca3368
Author: Tamas Cservenak <[email protected]>
AuthorDate: Fri Nov 28 15:44:47 2025 +0100

    GH-1668: Add catch-all for group filter (#1694)
    
    Introduced `*` "root" entry, that may define the "default acceptance".
    
    Fixes #1668
---
 .../internal/impl/filter/ruletree/GroupTree.java   |  15 ++-
 .../aether/internal/impl/filter/ruletree/Node.java |   6 +-
 .../impl/filter/ruletree/GroupTreeTest.java        | 118 +++++++++++++++++++++
 src/site/markdown/remote-repository-filtering.md   |  10 ++
 4 files changed, 145 insertions(+), 4 deletions(-)

diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/ruletree/GroupTree.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/ruletree/GroupTree.java
index e2d0295d3..b4e29dfbd 100644
--- 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/ruletree/GroupTree.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/ruletree/GroupTree.java
@@ -36,7 +36,10 @@ import static java.util.stream.Collectors.toList;
  *     <li>a valid Maven groupID ie "org.apache.maven".</li>
  * </ul>
  * By default, a G entry ie {@code org.apache.maven} means "allow {@code 
org.apache.maven} G and all Gs below
- * (so {@code org.apache.maven.plugins} etc. are all allowed).
+ * (so {@code org.apache.maven.plugins} etc. are all allowed). There is one 
special entry {@code "*"} (asterisk)
+ * that means "root" and defines the default acceptance: {@code "*"} means "by 
default accept" and {@code "!*"}
+ * means "by default deny" (same effect as when this character is not present 
in file). Use of limiter modifier
+ * on "root" like {@code "=*"} has no effect, is simply ignored.
  *
  * Examples:
  * <pre>
@@ -61,6 +64,7 @@ import static java.util.stream.Collectors.toList;
 public class GroupTree extends Node {
     public static final GroupTree SENTINEL = new GroupTree("sentinel");
 
+    private static final String ROOT = "*";
     private static final String MOD_EXCLUSION = "!";
     private static final String MOD_STOP = "=";
 
@@ -69,7 +73,7 @@ public class GroupTree extends Node {
     }
 
     public GroupTree(String name) {
-        super(name, false, null);
+        super(name, false, false);
     }
 
     public int loadNodes(Stream<String> linesStream) {
@@ -95,6 +99,10 @@ public class GroupTree extends Node {
                 stop = true;
                 line = line.substring(MOD_STOP.length());
             }
+            if (ROOT.equals(line)) {
+                this.setAllow(allow);
+                return true;
+            }
             List<String> groupElements = elementsOfGroup(line);
             for (String groupElement : groupElements.subList(0, 
groupElements.size() - 1)) {
                 currentNode = currentNode.addSibling(groupElement, false, 
null);
@@ -122,6 +130,7 @@ public class GroupTree extends Node {
                 accepted = currentNode.isAllow();
             }
         }
-        return accepted != null && accepted;
+        // use `accepted`, if defined; otherwise fallback to root (it always 
has `allow` set)
+        return accepted != null ? accepted : this.isAllow();
     }
 }
diff --git 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/ruletree/Node.java
 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/ruletree/Node.java
index 453a08704..beccf29c2 100644
--- 
a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/ruletree/Node.java
+++ 
b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/ruletree/Node.java
@@ -26,7 +26,7 @@ import java.util.HashMap;
 class Node {
     private final String name;
     private final boolean stop;
-    private final Boolean allow;
+    private Boolean allow;
     private final HashMap<String, Node> siblings;
 
     protected Node(String name, boolean stop, Boolean allow) {
@@ -52,6 +52,10 @@ class Node {
         return allow;
     }
 
+    public void setAllow(Boolean allow) {
+        this.allow = allow;
+    }
+
     protected Node addSibling(String name, boolean stop, Boolean allow) {
         return siblings.computeIfAbsent(name, n -> new Node(n, stop, allow));
     }
diff --git 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/filter/ruletree/GroupTreeTest.java
 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/filter/ruletree/GroupTreeTest.java
index ffe8cc170..1cdecd136 100644
--- 
a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/filter/ruletree/GroupTreeTest.java
+++ 
b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/filter/ruletree/GroupTreeTest.java
@@ -18,10 +18,13 @@
  */
 package org.eclipse.aether.internal.impl.filter.ruletree;
 
+import java.util.Arrays;
+import java.util.HashMap;
 import java.util.stream.Stream;
 
 import org.junit.jupiter.api.Test;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
@@ -50,5 +53,120 @@ public class GroupTreeTest {
 
         assertTrue(groupTree.acceptedGroupId("org.apache.baz"));
         assertFalse(groupTree.acceptedGroupId("org.apache.baz.aaa"));
+
+        assertFalse(groupTree.acceptedGroupId("not.in.list.but.uses.default"));
+    }
+
+    @Test
+    void smokeWithPositiveDefault() {
+        GroupTree groupTree = new GroupTree("root");
+        groupTree.loadNodes(Stream.of(
+                "# comment",
+                "",
+                "org.apache.maven",
+                "!=org.apache.maven.foo",
+                "!org.apache.maven.bar",
+                "=org.apache.baz",
+                "*"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven.aaa"));
+
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.foo"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven.foo.aaa"));
+
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.bar"));
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.bar.aaa"));
+
+        assertTrue(groupTree.acceptedGroupId("org.apache.baz"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.baz.aaa"));
+
+        assertTrue(groupTree.acceptedGroupId("not.in.list.but.uses.default"));
+    }
+
+    @Test
+    void smokeWithPositiveDefaultExclusionsOnly() {
+        GroupTree groupTree = new GroupTree("root");
+        groupTree.loadNodes(Stream.of("# comment", "*", 
"!org.apache.maven.foo", "!=org.apache.maven.bar"));
+        // no applicable rule; root=ALLOW
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven.aaa"));
+
+        // exclusion rule present (this and below)
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.foo"));
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.foo.aaa"));
+
+        // exclusion+stop rule present (only this)
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.bar"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven.bar.aaa"));
+
+        // no applicable rule; root=ALLOW
+        assertTrue(groupTree.acceptedGroupId("not.in.list.but.uses.default"));
+    }
+
+    @Test
+    void smokeWithNegativeDefault() {
+        GroupTree groupTree = new GroupTree("root");
+        groupTree.loadNodes(Stream.of(
+                "# comment",
+                "",
+                "org.apache.maven",
+                "!=org.apache.maven.foo",
+                "!org.apache.maven.bar",
+                "=org.apache.baz",
+                "!*"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven.aaa"));
+
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.foo"));
+        assertTrue(groupTree.acceptedGroupId("org.apache.maven.foo.aaa"));
+
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.bar"));
+        assertFalse(groupTree.acceptedGroupId("org.apache.maven.bar.aaa"));
+
+        assertTrue(groupTree.acceptedGroupId("org.apache.baz"));
+        assertFalse(groupTree.acceptedGroupId("org.apache.baz.aaa"));
+
+        assertFalse(groupTree.acceptedGroupId("not.in.list.but.uses.default"));
+    }
+
+    @Test
+    void implicitAndExplicitDefaultIsSame() {
+        // w/o asterisk: uses coded defaults
+        GroupTree implicitTree = new GroupTree("root");
+        implicitTree.loadNodes(Stream.of(
+                "# comment",
+                "",
+                "org.apache.maven",
+                "!=org.apache.maven.foo",
+                "!org.apache.maven.bar",
+                "=org.apache.baz"));
+        HashMap<String, Boolean> implicitResults = new HashMap<>();
+        // w/ asterisk: set to same value as default (should cause no change)
+        GroupTree explicitTree = new GroupTree("root");
+        explicitTree.loadNodes(Stream.of(
+                "# comment",
+                "",
+                "org.apache.maven",
+                "!=org.apache.maven.foo",
+                "!org.apache.maven.bar",
+                "=org.apache.baz",
+                "!*"));
+        HashMap<String, Boolean> explicitResults = new HashMap<>();
+
+        for (String key : Arrays.asList(
+                "org.apache.maven",
+                "org.apache.maven.aaa",
+                "org.apache.maven.foo",
+                "org.apache.maven.foo.aaa",
+                "org.apache.maven.bar",
+                "org.apache.maven.bar.aaa",
+                "org.apache.baz",
+                "org.apache.baz.aaa",
+                "not.in.list.but.uses.default")) {
+            implicitResults.put(key, implicitTree.acceptedGroupId(key));
+            explicitResults.put(key, explicitTree.acceptedGroupId(key));
+        }
+
+        assertEquals(implicitResults, explicitResults);
     }
 }
diff --git a/src/site/markdown/remote-repository-filtering.md 
b/src/site/markdown/remote-repository-filtering.md
index c8420d514..8012895fd 100644
--- a/src/site/markdown/remote-repository-filtering.md
+++ b/src/site/markdown/remote-repository-filtering.md
@@ -181,6 +181,16 @@ Lines 1 and 2 are ignored. Line 3 means "allow 
`org.apache.maven` G and below".
 only" (so `org.apache.maven.foo.bar` is allowed due first line). Line 5 means 
"disallow `org.apache.maven.indexer` and below"
 and finally line 6 means "allow `org.apache.bar` ONLY" (so 
`org.apache.bar.foo` is NOT enabled).
 
+One can use one special entry "root" `*` (asterisk) to define the "default 
acceptance" (that without it 
+defaults to REJECTED). Similarly, adding `!*` to file defines "default 
acceptance" of FALSE/REJECTED as well, 
+and adding it to file changes nothing, as this is the default acceptance (but 
may serve some documentation purposes). 
+Be aware: In case a line with single asterisk `*` is present, the whole logic 
of Group filter is getting inverted, 
+hence there is no need to add "allowed entries" (they are allowed by default), 
but one can add "disallowed entries" by 
+adding `!com.foo` and alike.
+
+Conflicting rules: rule parser is intentionally trivial, so in case of 
conflicting rules the "first wins" strategy is 
+applied. Ideally, user should keep files sorted or handle them in a way one 
can detect conflicts in it.
+
 ## Operation
 
 To make RRF filters operate, as they are by default enabled, you have to make 
sure that:

Reply via email to