Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,15 @@
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;

import java.io.File;
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;

Expand All @@ -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<String, Optional<String>> artifactIdCacheMap = new ConcurrentHashMap<>();

static File searchPomProperties(File dirOrFile) {
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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
Loading