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

kwin pushed a commit to branch bugfix/quote-regex-in-simplerelocator
in repository https://gitbox.apache.org/repos/asf/maven-shade-plugin.git

commit d7c92ecf5018a175c67b81e8e6e5d7e656b7bb0d
Author: Konrad Windszus <[email protected]>
AuthorDate: Thu Mar 5 11:37:07 2026 +0100

    Quote text within regular expression patterns correctly
    
    Use compiled RegEx patterns to speed up replacement
    Clarify which pattern fields allow which wildcard (follow which syntax)
    
    This closes #790
---
 .../plugins/shade/relocation/SimpleRelocator.java  | 76 +++++++++++++++-------
 .../shade/relocation/SimpleRelocatorTest.java      |  4 ++
 2 files changed, 57 insertions(+), 23 deletions(-)

diff --git 
a/src/main/java/org/apache/maven/plugins/shade/relocation/SimpleRelocator.java 
b/src/main/java/org/apache/maven/plugins/shade/relocation/SimpleRelocator.java
index b801fd0..b1d1e9a 100644
--- 
a/src/main/java/org/apache/maven/plugins/shade/relocation/SimpleRelocator.java
+++ 
b/src/main/java/org/apache/maven/plugins/shade/relocation/SimpleRelocator.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import org.codehaus.plexus.util.SelectorUtils;
@@ -52,20 +53,34 @@ public class SimpleRelocator implements Relocator {
                     + "|"
                     + "([{}(=;,]|\\*/) $");
 
-    private final String pattern;
+    /** plain text, no wildcards, always refer to classes, not paths */
+    private final String originalPattern;
 
-    private final String pathPattern;
+    /** plain text, no wildcards, always refer to paths not classes */
+    private final String originalPathPattern;
 
+    private final Pattern regExPattern;
+
+    private final Pattern regExPathPattern;
+
+    // replacement (no wildcards)
     private final String shadedPattern;
 
+    // replacement (no wildcards)
     private final String shadedPathPattern;
 
+    // only ant patterns (used with SelectorUtils.matchPath), must not start 
with "%ant[" prefix, always refer to paths
+    // not classes
     private final Set<String> includes;
 
+    // only ant patterns (used with SelectorUtils.matchPath), must not start 
with "%ant[" prefix, always refer to paths
+    // not classes
     private final Set<String> excludes;
 
+    // prefix (no wildcards), derived from excludes
     private final Set<String> sourcePackageExcludes = new LinkedHashSet<>();
 
+    // prefix (no wildcards), derived from excludes
     private final Set<String> sourcePathExcludes = new LinkedHashSet<>();
 
     private final boolean rawString;
@@ -77,28 +92,28 @@ public class SimpleRelocator implements Relocator {
     public SimpleRelocator(
             String patt, String shadedPattern, List<String> includes, 
List<String> excludes, boolean rawString) {
         this.rawString = rawString;
-
         if (rawString) {
-            this.pathPattern = patt;
+            originalPathPattern = patt;
             this.shadedPathPattern = shadedPattern;
 
-            this.pattern = null; // not used for raw string relocator
+            originalPattern = null; // not used for raw string relocator
             this.shadedPattern = null; // not used for raw string relocator
         } else {
             if (patt == null) {
-                this.pattern = "";
-                this.pathPattern = "";
+                // what does this mean?
+                originalPattern = null;
+                originalPathPattern = null;
             } else {
-                this.pattern = patt.replace('/', '.');
-                this.pathPattern = patt.replace('.', '/');
+                originalPattern = patt.replace('/', '.');
+                originalPathPattern = patt.replace('.', '/');
             }
 
             if (shadedPattern != null) {
                 this.shadedPattern = shadedPattern.replace('/', '.');
                 this.shadedPathPattern = shadedPattern.replace('.', '/');
             } else {
-                this.shadedPattern = "hidden." + this.pattern;
-                this.shadedPathPattern = "hidden/" + this.pathPattern;
+                this.shadedPattern = "hidden." + originalPattern;
+                this.shadedPathPattern = "hidden/" + originalPathPattern;
             }
         }
 
@@ -118,17 +133,26 @@ public class SimpleRelocator implements Relocator {
             // Create exclude pattern sets for sources
             for (String exclude : this.excludes) {
                 // Excludes should be subpackages of the global pattern
-                if (exclude.startsWith(pattern)) {
+                if (exclude.startsWith(originalPattern)) {
                     sourcePackageExcludes.add(
-                            
exclude.substring(pattern.length()).replaceFirst("[.][*]$", ""));
+                            
exclude.substring(originalPattern.length()).replaceFirst("[.][*]$", ""));
                 }
                 // Excludes should be subpackages of the global pattern
-                if (exclude.startsWith(pathPattern)) {
+                if (exclude.startsWith(originalPathPattern)) {
                     sourcePathExcludes.add(
-                            
exclude.substring(pathPattern.length()).replaceFirst("[/][*]$", ""));
+                            
exclude.substring(originalPathPattern.length()).replaceFirst("[/][*]$", ""));
                 }
             }
         }
+        // raw strings are already treated as regex patterns, so don't quote 
them, otherwise the regex won't work as
+        // intended
+        if (!rawString) {
+            regExPattern = originalPattern != null ? 
Pattern.compile(Pattern.quote(originalPattern)) : null;
+            regExPathPattern = originalPathPattern != null ? 
Pattern.compile(Pattern.quote(originalPathPattern)) : null;
+        } else {
+            this.regExPattern = originalPattern != null ? 
Pattern.compile(originalPattern) : null;
+            this.regExPathPattern = originalPathPattern != null ? 
Pattern.compile(originalPathPattern) : null;
+        }
     }
 
     private static Set<String> normalizePatterns(Collection<String> patterns) {
@@ -177,7 +201,7 @@ public class SimpleRelocator implements Relocator {
     @Override
     public boolean canRelocatePath(String path) {
         if (rawString) {
-            return Pattern.compile(pathPattern).matcher(path).find();
+            return regExPathPattern.matcher(path).find();
         }
 
         if (path.endsWith(".class")) {
@@ -190,7 +214,13 @@ public class SimpleRelocator implements Relocator {
             path = path.substring(1);
         }
 
-        return isIncluded(path) && !isExcluded(path) && 
path.startsWith(pathPattern);
+        if (isIncluded(path) && !isExcluded(path)) {
+            Matcher matcher = regExPathPattern.matcher(path);
+            if (matcher.find()) {
+                return matcher.start() == 0;
+            }
+        }
+        return false;
     }
 
     @Override
@@ -201,20 +231,20 @@ public class SimpleRelocator implements Relocator {
     @Override
     public String relocatePath(String path) {
         if (rawString) {
-            return path.replaceAll(pathPattern, shadedPathPattern);
+            return 
regExPathPattern.matcher(path).replaceAll(shadedPathPattern);
         } else {
-            return path.replaceFirst(pathPattern, shadedPathPattern);
+            return 
regExPathPattern.matcher(path).replaceFirst(shadedPathPattern);
         }
     }
 
     @Override
     public String relocateClass(String input) {
-        return rawString ? input : input.replaceFirst(pattern, shadedPattern);
+        return rawString ? input : 
regExPattern.matcher(input).replaceFirst(shadedPattern);
     }
 
     @Override
     public String relocateAllClasses(String input) {
-        return rawString ? input : input.replaceAll(pattern, shadedPattern);
+        return rawString ? input : 
regExPattern.matcher(input).replaceAll(shadedPattern);
     }
 
     @Override
@@ -222,8 +252,8 @@ public class SimpleRelocator implements Relocator {
         if (rawString) {
             return sourceContent;
         }
-        sourceContent = shadeSourceWithExcludes(sourceContent, pattern, 
shadedPattern, sourcePackageExcludes);
-        return shadeSourceWithExcludes(sourceContent, pathPattern, 
shadedPathPattern, sourcePathExcludes);
+        sourceContent = shadeSourceWithExcludes(sourceContent, 
originalPattern, shadedPattern, sourcePackageExcludes);
+        return shadeSourceWithExcludes(sourceContent, originalPathPattern, 
shadedPathPattern, sourcePathExcludes);
     }
 
     private String shadeSourceWithExcludes(
diff --git 
a/src/test/java/org/apache/maven/plugins/shade/relocation/SimpleRelocatorTest.java
 
b/src/test/java/org/apache/maven/plugins/shade/relocation/SimpleRelocatorTest.java
index 44afee3..45f6601 100644
--- 
a/src/test/java/org/apache/maven/plugins/shade/relocation/SimpleRelocatorTest.java
+++ 
b/src/test/java/org/apache/maven/plugins/shade/relocation/SimpleRelocatorTest.java
@@ -155,6 +155,8 @@ public class SimpleRelocatorTest {
 
         relocator = new SimpleRelocator("org.foo", "private.stuff", null, 
null);
         assertEquals("private.stuff.bar.Class", 
relocator.relocateClass("org.foo.bar.Class"));
+        // make sure that "." does not match "x" in "orgxfoo.bar.Class"
+        assertEquals("orgxfoo.bar.Class", 
relocator.relocateClass("orgxfoo.bar.Class"));
     }
 
     @Test
@@ -170,6 +172,8 @@ public class SimpleRelocatorTest {
         assertEquals(
                 "private.stuff.bar.Class, private.stuff.bar.Class and 
private.stuff.bar.Class",
                 relocator.relocateAllClasses("org.foo.bar.Class, 
private.stuff.bar.Class and org.foo.bar.Class"));
+        // make sure that "." does not match "x" in "orgxfoo.bar.Class"
+        assertEquals("orgxfoo.bar.Class", 
relocator.relocateClass("orgxfoo.bar.Class"));
     }
 
     @Test

Reply via email to