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]