diff --git a/sofa-ark-parent/core-impl/archive/src/main/java/com/alipay/sofa/ark/loader/jar/JarUtils.java b/sofa-ark-parent/core-impl/archive/src/main/java/com/alipay/sofa/ark/loader/jar/JarUtils.java index 1eadfcf01..e37a93a3b 100644 --- a/sofa-ark-parent/core-impl/archive/src/main/java/com/alipay/sofa/ark/loader/jar/JarUtils.java +++ b/sofa-ark-parent/core-impl/archive/src/main/java/com/alipay/sofa/ark/loader/jar/JarUtils.java @@ -20,8 +20,6 @@ import com.alipay.sofa.ark.common.util.StringUtils; import com.alipay.sofa.ark.loader.archive.JarFileArchive; import com.alipay.sofa.ark.loader.util.ModifyPathUtils; -import com.alipay.sofa.ark.spi.archive.Archive; -import com.alipay.sofa.common.utils.StringUtil; import org.apache.maven.model.Model; import org.apache.maven.model.io.xpp3.MavenXpp3Reader; @@ -29,13 +27,8 @@ import java.io.FileReader; import java.io.IOException; import java.io.InputStream; -import java.net.URL; import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Properties; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarEntry; @@ -60,6 +53,8 @@ public class JarUtils { public static final String JAR_SUFFIX = ".jar"; + public static final String JAR_UNPACK = ".jar-unpack"; + private static final Map> artifactIdCacheMap = new ConcurrentHashMap<>(); static File searchPomProperties(File dirOrFile) { @@ -150,8 +145,20 @@ public static String parseArtifactId(String jarLocation) { // 7. /xxx/xxx/target/test-classes/yyy/yyy/ // 8. /xxx/xxx/xxx-starter-1.0.0-SNAPSHOT.jar!/BOOT-INF/lib/xxx2-starter-1.1.4-SNAPSHOT-ark-biz.jar!/lib/xxx3-230605-sofa.jar!/ // 9. if is ark plugin, then return null to set declared default + //10. use unpack model, file /xxx/xxx/xxx-0.0.1-ark-biz.jar-unpack/ - // clean the jar location prefix and suffix + // Check if it's an unpacked directory + if (jarLocation.contains(JAR_UNPACK)) { + // Try to extract artifactId from the unpacked directory + String artifactId = parseArtifactIdFromUnpackedDir(jarLocation); + if (artifactId != null) { + return artifactId; + } + // If failed, fallback to extracting from directory name + return doGetArtifactIdFromFileName(jarLocation); + } + + // For non-unpacked paths, clean the jar location prefix and suffix if (jarLocation.contains(JAR_SUFFIX)) { jarLocation = jarLocation.substring(0, jarLocation.lastIndexOf(JAR_SUFFIX) + JAR_SUFFIX.length()); } @@ -244,4 +251,29 @@ public static com.alipay.sofa.ark.loader.jar.JarFile getNestedRootJarFromJarLoca } return rJarFile; } + + static String parseArtifactIdFromUnpackedDir(String unpackDirPath) { + File unpackDir = new File(unpackDirPath); + if (!unpackDir.exists() || !unpackDir.isDirectory()) { + return null; + } + + // Look for pom.properties in maven-archiver directory + File pomPropsFile = searchPomProperties(unpackDir); + if (pomPropsFile != null && pomPropsFile.exists()) { + try (InputStream inputStream = Files.newInputStream(pomPropsFile.toPath())) { + Properties properties = new Properties(); + properties.load(inputStream); + String artifactId = properties.getProperty(JAR_ARTIFACT_ID); + if (artifactId != null && !artifactId.isEmpty()) { + return artifactId; + } + } catch (IOException e) { + throw new RuntimeException(String.format( + "Failed to parse artifact id from path %s.", unpackDirPath), e); + } + } + + return null; + } } diff --git a/sofa-ark-parent/core-impl/archive/src/test/java/com/alipay/sofa/ark/loader/jar/JarUtilsParseArtifactIdFromUnpackedDirTest.java b/sofa-ark-parent/core-impl/archive/src/test/java/com/alipay/sofa/ark/loader/jar/JarUtilsParseArtifactIdFromUnpackedDirTest.java new file mode 100644 index 000000000..af41f9484 --- /dev/null +++ b/sofa-ark-parent/core-impl/archive/src/test/java/com/alipay/sofa/ark/loader/jar/JarUtilsParseArtifactIdFromUnpackedDirTest.java @@ -0,0 +1,158 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file 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 + * + * 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 KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alipay.sofa.ark.loader.jar; + +import com.alipay.sofa.ark.common.util.FileUtils; +import org.junit.Test; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Properties; + +import static org.junit.Assert.*; + +public class JarUtilsParseArtifactIdFromUnpackedDirTest { + + @Test + public void testParseArtifactIdFromUnpackedDir_StandardLocation() throws IOException { + File tempDir = FileUtils.createTempDir("test-unpack"); + try { + File mavenArchiverDir = new File(tempDir, "META-INF/maven-archiver"); + mavenArchiverDir.mkdirs(); + + File pomPropertiesFile = new File(mavenArchiverDir, "pom.properties"); + try (FileWriter writer = new FileWriter(pomPropertiesFile)) { + Properties props = new Properties(); + props.setProperty("artifactId", "test-artifact"); + props.store(writer, "Test pom.properties file"); + } + + String result = JarUtils.parseArtifactIdFromUnpackedDir(tempDir.getAbsolutePath()); + assertEquals("test-artifact", result); + } finally { + org.apache.commons.io.FileUtils.deleteQuietly(tempDir); + } + } + + @Test + public void testParseArtifactIdFromUnpackedDir_NonStandardLocation() throws IOException { + File tempDir = FileUtils.createTempDir("test-unpack-nonstandard"); + try { + File nestedDir = new File(tempDir, "some/nested/path"); + nestedDir.mkdirs(); + + File pomPropertiesFile = new File(nestedDir, "pom.properties"); + try (FileWriter writer = new FileWriter(pomPropertiesFile)) { + Properties props = new Properties(); + props.setProperty("artifactId", "test-artifact-nested"); + props.store(writer, "Test pom.properties file in nested location"); + } + + String result = JarUtils.parseArtifactIdFromUnpackedDir(tempDir.getAbsolutePath()); + assertEquals("test-artifact-nested", result); + } finally { + org.apache.commons.io.FileUtils.deleteQuietly(tempDir); + } + } + + @Test + public void testParseArtifactIdFromUnpackedDir_DirectoryDoesNotExist() { + String result = JarUtils.parseArtifactIdFromUnpackedDir("/non/existent/directory"); + assertNull(result); + } + + @Test + public void testParseArtifactIdFromUnpackedDir_EmptyPomProperties() throws IOException { + File tempDir = FileUtils.createTempDir("test-unpack-empty"); + try { + File mavenArchiverDir = new File(tempDir, "META-INF/maven-archiver"); + mavenArchiverDir.mkdirs(); + + File pomPropertiesFile = new File(mavenArchiverDir, "pom.properties"); + try (FileWriter writer = new FileWriter(pomPropertiesFile)) { + Properties props = new Properties(); + props.setProperty("artifactId", ""); + props.store(writer, "Test pom.properties file with empty artifactId"); + } + + String result = JarUtils.parseArtifactIdFromUnpackedDir(tempDir.getAbsolutePath()); + assertNull(result); + } finally { + org.apache.commons.io.FileUtils.deleteQuietly(tempDir); + } + } + + @Test + public void testParseArtifactIdFromUnpackedDir_MissingArtifactIdProperty() throws IOException { + File tempDir = FileUtils.createTempDir("test-unpack-missing-key"); + try { + File mavenArchiverDir = new File(tempDir, "META-INF/maven-archiver"); + mavenArchiverDir.mkdirs(); + + File pomPropertiesFile = new File(mavenArchiverDir, "pom.properties"); + try (FileWriter writer = new FileWriter(pomPropertiesFile)) { + Properties props = new Properties(); + props.setProperty("groupId", "com.test"); + props.setProperty("version", "1.0.0"); + props.store(writer, "Test pom.properties file without artifactId"); + } + + String result = JarUtils.parseArtifactIdFromUnpackedDir(tempDir.getAbsolutePath()); + assertNull(result); + } finally { + org.apache.commons.io.FileUtils.deleteQuietly(tempDir); + } + } + + @Test + public void testParseArtifactIdFromUnpackedDir_NoPomProperties() throws IOException { + File tempDir = FileUtils.createTempDir("test-unpack-nopom"); + try { + // Directory exists but has no pom.properties at all + String result = JarUtils.parseArtifactIdFromUnpackedDir(tempDir.getAbsolutePath()); + assertNull(result); + } finally { + org.apache.commons.io.FileUtils.deleteQuietly(tempDir); + } + } + + @Test + public void testParseArtifactId_UnpackPathFallbackToFileName() throws IOException { + // When pom.properties is not found, should fallback to parsing from directory name + String unpackPath = "/tmp/non-existent-dir/my-app-1.0.0-SNAPSHOT.jar-unpack/"; + String artifactId = JarUtils.parseArtifactId(unpackPath); + assertEquals("my-app", artifactId); + } + + @Test + public void testParseArtifactId_UnpackPathWithResourceUrl() { + // Test with actual test resource + java.net.URL url = this.getClass().getClassLoader().getResource("xxxxx.jar-unpack"); + assertNotNull(url); + String artifactId = JarUtils.parseArtifactId(url.getPath()); + assertEquals("xxxx-test", artifactId); + } + + @Test + public void testParseArtifactId_UnpackPathNoVersion() { + // When directory name has no version pattern, should return null from fallback + String unpackPath = "/tmp/non-existent-dir/some-lib.jar-unpack/"; + String artifactId = JarUtils.parseArtifactId(unpackPath); + assertNull(artifactId); + } +} diff --git a/sofa-ark-parent/core-impl/archive/src/test/java/com/alipay/sofa/ark/loader/jar/JarUtilsTest.java b/sofa-ark-parent/core-impl/archive/src/test/java/com/alipay/sofa/ark/loader/jar/JarUtilsTest.java index 96cccb463..b797363dd 100644 --- a/sofa-ark-parent/core-impl/archive/src/test/java/com/alipay/sofa/ark/loader/jar/JarUtilsTest.java +++ b/sofa-ark-parent/core-impl/archive/src/test/java/com/alipay/sofa/ark/loader/jar/JarUtilsTest.java @@ -55,4 +55,11 @@ public void testParseArtifactId() { String artifactId = JarUtils.parseArtifactId(url.getPath()); assertEquals("sofa-ark-sample-springboot-ark", artifactId); } + + @Test + public void testParseArtifactIdFromUnpackDir() { + URL url = this.getClass().getClassLoader().getResource("xxxxx.jar-unpack"); + String artifactId = JarUtils.parseArtifactId(url.getPath()); + assertEquals("xxxx-test", artifactId); + } } diff --git a/sofa-ark-parent/core-impl/archive/src/test/resources/xxxxx.jar-unpack/pom.properties b/sofa-ark-parent/core-impl/archive/src/test/resources/xxxxx.jar-unpack/pom.properties new file mode 100644 index 000000000..53e25a96c --- /dev/null +++ b/sofa-ark-parent/core-impl/archive/src/test/resources/xxxxx.jar-unpack/pom.properties @@ -0,0 +1,5 @@ +#Generated by Maven +#Wed Jan 28 11:40:04 CST 2026 +artifactId=xxxx-test +groupId=com.xxxx.base +version=0.0.1 \ No newline at end of file