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

tkobayas pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git


The following commit(s) were added to refs/heads/main by this push:
     new 24aab71eb2 [incubator-kie-drools-6309] Normalize spring boot path 
(#6312)
24aab71eb2 is described below

commit 24aab71eb2c0c6d34eaf8391c2201b4ce9d48a5f
Author: Toshiya Kobayashi <[email protected]>
AuthorDate: Thu Apr 24 17:42:41 2025 +0900

    [incubator-kie-drools-6309] Normalize spring boot path (#6312)
---
 .../ruleunits/impl/RuleUnitProviderImpl.java       | 20 +++++++++---
 .../src/main/java/org/drools/util/JarUtils.java    | 38 ++++++++++++++++++----
 .../test/java/org/drools/util/JarUtilsTest.java    | 35 ++++++++++++++------
 3 files changed, 72 insertions(+), 21 deletions(-)

diff --git 
a/drools-ruleunits/drools-ruleunits-impl/src/main/java/org/drools/ruleunits/impl/RuleUnitProviderImpl.java
 
b/drools-ruleunits/drools-ruleunits-impl/src/main/java/org/drools/ruleunits/impl/RuleUnitProviderImpl.java
index a81be34f7f..5ade99472f 100644
--- 
a/drools-ruleunits/drools-ruleunits-impl/src/main/java/org/drools/ruleunits/impl/RuleUnitProviderImpl.java
+++ 
b/drools-ruleunits/drools-ruleunits-impl/src/main/java/org/drools/ruleunits/impl/RuleUnitProviderImpl.java
@@ -57,6 +57,7 @@ import org.slf4j.LoggerFactory;
 
 import static org.drools.util.IoUtils.readFileAsString;
 import static org.drools.util.IoUtils.readJarEntryAsString;
+import static org.drools.util.JarUtils.getPathWithoutScheme;
 import static org.drools.util.JarUtils.normalizeSpringBootResourceUrlPath;
 
 public class RuleUnitProviderImpl implements RuleUnitProvider {
@@ -185,15 +186,24 @@ public class RuleUnitProviderImpl implements 
RuleUnitProvider {
         return unitValues != null && unitValues.stream().anyMatch(valueArray 
-> valueArray.length > 0 && valueArray[0] != null && 
valueArray[0].trim().equals(unitName));
     }
 
-    private static void collectResourcesInJar(KieServices ks, 
Collection<Resource> resources, Class<?> unitClass, String unitStatement, URL 
resourceUrl) {
-        String path = resourceUrl.getPath();                       // 
file:/path/to/xxx.jar!org/example
+    /**
+     * Collects rule unit resources under a specific package directory in a 
jar file.
+     * This method is protected, so that it can be enhanced when there is a 
framework specific issue
+     * @param ks
+     * @param resources
+     * @param unitClass
+     * @param unitStatement
+     * @param resourceUrl
+     */
+    protected static void collectResourcesInJar(KieServices ks, 
Collection<Resource> resources, Class<?> unitClass, String unitStatement, URL 
resourceUrl) {
+        String path = getPathWithoutScheme(resourceUrl);  // 
/path/to/xxx.jar!/org/example
+
+        path = normalizeSpringBootResourceUrlPath(path); // any spring-boot 
specific path should be normalized
 
         int jarSuffixIndex = path.indexOf(".jar!/");
-        String jarPath = path.substring(5, jarSuffixIndex + 4);    // 
/path/to/xxx.jar
+        String jarPath = path.substring(0, jarSuffixIndex + 4);    // 
/path/to/xxx.jar
         String directoryPath = path.substring(jarSuffixIndex + 6); // 
org/example
 
-        directoryPath = normalizeSpringBootResourceUrlPath(directoryPath);
-
         try (JarFile jarFile = new JarFile(new File(jarPath))) {
             Enumeration<JarEntry> entries = jarFile.entries();
             while (entries.hasMoreElements()) {
diff --git a/drools-util/src/main/java/org/drools/util/JarUtils.java 
b/drools-util/src/main/java/org/drools/util/JarUtils.java
index eb7789f632..b5fcf0b195 100644
--- a/drools-util/src/main/java/org/drools/util/JarUtils.java
+++ b/drools-util/src/main/java/org/drools/util/JarUtils.java
@@ -18,6 +18,8 @@
  */
 package org.drools.util;
 
+import java.net.URL;
+
 /**
  * Utility to access jar files
  */
@@ -25,6 +27,7 @@ public class JarUtils {
 
     private static final String SPRING_BOOT_PREFIX = "BOOT-INF/classes/"; // 
Actual path prefix in Spring Boot JAR
     private static final String SPRING_BOOT_URL_PREFIX = "BOOT-INF/classes!/"; 
// Spring Boot adds "!" to resource url as a "nest" separator
+    private static final String SPRING_BOOT_URL_PREFIX_3_2 = 
"BOOT-INF/classes/!/"; // Spring Boot 3.2 adds "!/" to resource url as a "nest" 
separator
 
     private static final String SPRING_BOOT_NESTED_PREFIX_BEFORE_3_2 = 
"!/BOOT-INF/"; // Before Spring Boot 3.2
     private static final String SPRING_BOOT_NESTED_PREFIX_AFTER_3_2 = 
"/!BOOT-INF/"; // Since Spring Boot 3.2
@@ -34,16 +37,25 @@ public class JarUtils {
     }
 
     /**
-     * Spring Boot executable jar contains path 
"BOOT-INF/classes/org/example/MyClass.class" in the jar file.
-     * However, when resource urls are acquired by spring boot classloader's 
getResources(),
-     * "!" is added to the path prefix as a "nest" separator, resulting in 
"BOOT-INF/classes!/org/example/MyClass.class".
-     * This method removes the "!" from the path to make it consistent with 
the actual path in the jar file.
+     * Fix resource urls are acquired by spring boot classloader's 
getResources() for Spring Boot fat jar
+     * in order to be consistent with the actual path in the jar file.
+     *
+     * For example, Spring Boot 3.2 classloader's getResources() returns like
+     * 
"jar:nested:/path/to/demo.jar/!BOOT-INF/classes/!/org/example/MyClass.class"
+     * while the actual path in the jar file is
+     * 
"jar:nested:/path/to/demo.jar!/BOOT-INF/classes/org/example/MyClass.class"
+     *
+     * This method normalizes only the path part. The scheme part (e.g. 
"jar:nested:") can be handled by getPathWithoutScheme
      * @param resourceUrlPath resource url path
      * @return normalized resource url path
      */
     public static String normalizeSpringBootResourceUrlPath(String 
resourceUrlPath) {
-        if (resourceUrlPath.startsWith(SPRING_BOOT_URL_PREFIX)) {
-            return resourceUrlPath.replace(SPRING_BOOT_URL_PREFIX, 
SPRING_BOOT_PREFIX); // Remove "!"
+        resourceUrlPath = replaceNestedPathForSpringBoot32(resourceUrlPath);
+
+        if (resourceUrlPath.contains(SPRING_BOOT_URL_PREFIX)) {
+            return resourceUrlPath.replace(SPRING_BOOT_URL_PREFIX, 
SPRING_BOOT_PREFIX);
+        } else if (resourceUrlPath.contains(SPRING_BOOT_URL_PREFIX_3_2)) {
+            return resourceUrlPath.replace(SPRING_BOOT_URL_PREFIX_3_2, 
SPRING_BOOT_PREFIX);
         } else {
             return resourceUrlPath;
         }
@@ -61,4 +73,18 @@ public class JarUtils {
             return urlPath;
         }
     }
+
+    /**
+     * get path removing scheme prefix including additional scheme e.g. 
"jar:nested:"
+     */
+    public static String getPathWithoutScheme(URL url) {
+        String path = url.getPath(); // "jar:" scheme is removed here
+        if (path.startsWith("file:")) {
+            return path.substring("file:".length());
+        } else if (path.startsWith("nested:")) {
+            return path.substring("nested:".length());
+        } else {
+            return path;
+        }
+    }
 }
diff --git a/drools-util/src/test/java/org/drools/util/JarUtilsTest.java 
b/drools-util/src/test/java/org/drools/util/JarUtilsTest.java
index 1992a7faa9..12fb73069c 100644
--- a/drools-util/src/test/java/org/drools/util/JarUtilsTest.java
+++ b/drools-util/src/test/java/org/drools/util/JarUtilsTest.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,28 +18,43 @@
  */
 package org.drools.util;
 
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.junit.jupiter.api.Test;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
-import org.junit.jupiter.api.Test;
+class JarUtilsTest {
 
-public class JarUtilsTest {
+    @Test
+    void normalizeSpringBootResourceUrlPath() {
+        String normalized = 
JarUtils.normalizeSpringBootResourceUrlPath("/path/to/demo.jar!/BOOT-INF/classes!/org/example/MyClass.class");
+        
assertThat(normalized).isEqualTo("/path/to/demo.jar!/BOOT-INF/classes/org/example/MyClass.class");
+    }
 
     @Test
-    public void normalizeSpringBootResourceUrlPath() {
-        String normalized = 
JarUtils.normalizeSpringBootResourceUrlPath("BOOT-INF/classes!/org/example/MyClass.class");
-        
assertThat(normalized).isEqualTo("BOOT-INF/classes/org/example/MyClass.class");
+    void normalizeSpringBootResourceUrlPathSB32() {
+        String normalized = 
JarUtils.normalizeSpringBootResourceUrlPath("/path/to/demo.jar/!BOOT-INF/classes/!/org/example/MyClass.class");
+        
assertThat(normalized).isEqualTo("/path/to/demo.jar!/BOOT-INF/classes/org/example/MyClass.class");
     }
 
     @Test
-    public void replaceNestedPathForSpringBoot32_shouldNotAffectOldPath() {
+    void replaceNestedPathForSpringBoot32_shouldNotAffectOldPath() {
         String result = 
JarUtils.replaceNestedPathForSpringBoot32("/dir/myapp.jar!/BOOT-INF/lib/mykjar.jar");
         
assertThat(result).isEqualTo("/dir/myapp.jar!/BOOT-INF/lib/mykjar.jar");
     }
 
     @Test
-    public void replaceNestedPathForSpringBoot32_shouldReplaceNewPath() {
+    void replaceNestedPathForSpringBoot32_shouldReplaceNewPath() {
         String result = 
JarUtils.replaceNestedPathForSpringBoot32("/dir/myapp.jar/!BOOT-INF/lib/mykjar.jar");
         
assertThat(result).isEqualTo("/dir/myapp.jar!/BOOT-INF/lib/mykjar.jar");
     }
+
+    @Test
+    void getPathWithoutScheme() throws MalformedURLException {
+        URL url = new URL("jar", "", 
"nested:/path/to/demo.jar/!BOOT-INF/classes/!/org/example/MyClass.class");
+        String path = JarUtils.getPathWithoutScheme(url);
+        
assertThat(path).isEqualTo("/path/to/demo.jar/!BOOT-INF/classes/!/org/example/MyClass.class");
+    }
 }
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to