Skip to content

Commit

Permalink
optimize unique url for scanning resources from both base and module (#…
Browse files Browse the repository at this point in the history
…623)

* add maven tree for parsing deps of multi module project

* reuse maven session for multi module lib parse

* fix unique urls from dir

* remove unused code

* optimize jar artifact id parse

* update to 2.1.3-SNAPSHOT

* set all default to delegate to base

* rollback to set not declared for not jars

---------

Co-authored-by: youji.zzl <youji.zzl@antfin.com>
  • Loading branch information
lvjing2 and youji.zzl authored Mar 23, 2023
1 parent ab0501f commit 3b7b664
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
Expand All @@ -50,24 +51,53 @@ public class JarUtils {

private static final Map<String, Optional<String>> artifactIdCacheMap = new ConcurrentHashMap<>();

public static String getArtifactIdFromLocalClassPath(String fileClassPath) {
private static File searchPomProperties(File dirOrFile) {
if (dirOrFile == null || !dirOrFile.exists()) {
return null;
}
if (dirOrFile.isFile() && JAR_POM_PROPERTIES.equals(dirOrFile.getName())) {
return dirOrFile;
}
if (dirOrFile.isDirectory()) {
File[] files = dirOrFile.listFiles();

if (files != null) {
for (File file : files) {
File result = searchPomProperties(file);
if (result != null) {
return result;
}
}
}
}
return null;
}

private static String getArtifactIdFromLocalClassPath(String fileClassPath) {
// file:/Users/youji.zzl/Documents/workspace/iexpprodbase/app/bootstrap/target/classes/spring/
String libraryFile = fileClassPath.replace("file:", "");
// 1. search pom.properties
int classesRootIndex = libraryFile.indexOf(CLASSPATH_ROOT_IDENTITY);
int testClassesRootIndex = libraryFile.indexOf(TEST_CLASSPATH_ROOT_IDENTITY);
int rootIndex = -1;
String pomPropertiesPath;
if (classesRootIndex != -1) {
rootIndex = classesRootIndex;
libraryFile.substring(0, classesRootIndex + TARGET_ROOT_IDENTITY.length());
pomPropertiesPath = libraryFile.substring(0,
classesRootIndex + TARGET_ROOT_IDENTITY.length())
+ JAR_POM_PROPERTIES_RELATIVE_PATH;
} else if (testClassesRootIndex != -1) {
rootIndex = testClassesRootIndex;
pomPropertiesPath = libraryFile.substring(0, testClassesRootIndex
+ TARGET_ROOT_IDENTITY.length())
+ JAR_POM_PROPERTIES_RELATIVE_PATH;
} else {
return null;
// is not from test classpath, for example install uncompressed modules, just return null
// search for pom.properties
File pomPropertiesFile = searchPomProperties(new File(libraryFile));
if (pomPropertiesFile != null && pomPropertiesFile.exists()) {
pomPropertiesPath = pomPropertiesFile.getAbsolutePath();
} else {
return null;
}
}
String classPathRootPath = libraryFile.substring(0,
rootIndex + TARGET_ROOT_IDENTITY.length());
String pomPropertiesPath = classPathRootPath + JAR_POM_PROPERTIES_RELATIVE_PATH;

try (InputStream inputStream = Files.newInputStream(Paths.get(pomPropertiesPath))) {
Properties properties = new Properties();
Expand All @@ -78,13 +108,53 @@ public static String getArtifactIdFromLocalClassPath(String fileClassPath) {
}
}

public static String getJarArtifactId(String jarLocation) {
public static String parseArtifactId(String jarLocation) {
// 1. /xxx/xxx/xx.jar!/
// 2. /xxx/xxx/xx.jar!/xxxx.class
// 3. /xxx/xxx/xx.jar
// 4. /xxx/xxx/xxx-bootstrap-1.0.0-ark-biz.jar!/BOOT-INF/lib/spring-boot-2.4.13.jar!/
// 5. /xxx/xxx-bootstrap-1.0.0-ark-biz.jar!/BOOT-INF/lib/sofa-ark-springboot-starter-2.1.1.jar!/META-INF/spring.factories
// 6. /xxx/xxx/target/classes/xxxx.jar
// 7. /xxx/xxx/target/test-classes/yyy/yyy/


artifactIdCacheMap.computeIfAbsent(jarLocation, a -> {
String artifactId = doGetArtifactIdFromFileName(a);
if (StringUtils.isEmpty(artifactId)) {
artifactId = doGetArtifactIdFromJarPom(a);
try {
String artifactId;
String[] as = a.split("!/", -1);
if (as.length == 1) {
// no '!/'
String filePath = as[0];
if (a.endsWith(".jar")) {
artifactId = doGetArtifactIdFromFileName(filePath);
if (StringUtils.isEmpty(artifactId)) {
artifactId = parseArtifactIdFromJar(filePath);
}
} else {
artifactId = getArtifactIdFromLocalClassPath(filePath);
}
} else if (as.length == 2) {
// one '!/'
String filePath = as[0];
artifactId = doGetArtifactIdFromFileName(filePath);
if (StringUtils.isEmpty(artifactId)) {
artifactId = parseArtifactIdFromJar(filePath);
}
} else {
// two '!/'
String[] jarPathInfo= Arrays.copyOf(as, as.length-1);
String filePath = String.join("!/", jarPathInfo);
artifactId = doGetArtifactIdFromFileName(filePath);
if (StringUtils.isEmpty(artifactId)) {
artifactId = parseArtifactIdFromJarInJar(filePath);
}
}
return Optional.ofNullable(artifactId);
} catch (IOException e) {
throw new RuntimeException(String.format("Failed to parse artifact id from jar %s.",
jarLocation), e);
}
return Optional.ofNullable(artifactId);

});
return artifactIdCacheMap.get(jarLocation).orElse(null);
}
Expand Down Expand Up @@ -112,22 +182,6 @@ private static String doGetArtifactIdFromFileName(String jarLocation) {
return null;
}

private static String doGetArtifactIdFromJarPom(String jarLocation) {
try {
if (jarLocation.contains("!/")) {
// in nested jar
return parseArtifactIdFromJarInJar(jarLocation);
} else {
try (JarFile jarFile = new JarFile(jarLocation)) {
return parseArtifactIdFromJar(jarFile);
}
}
} catch (IOException e) {
throw new RuntimeException(String.format("Failed to parse artifact id from jar %s.",
jarLocation), e);
}
}

private static String parseArtifactIdFromJarInJar(String jarLocation) throws IOException {
String rootPath = jarLocation.substring(0, jarLocation.lastIndexOf("!/"));
String subNestedPath = jarLocation.substring(jarLocation.lastIndexOf("!/") + 2);
Expand All @@ -143,18 +197,20 @@ private static String parseArtifactIdFromJarInJar(String jarLocation) throws IOE
return properties.getProperty(JAR_ARTIFACT_ID);
}

private static String parseArtifactIdFromJar(JarFile jarFile) throws IOException {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
java.util.jar.JarEntry entry = entries.nextElement();
if (entry.getName().endsWith(JAR_POM_PROPERTIES)) {
try (InputStream is = jarFile.getInputStream(entry)) {
Properties p = new Properties();
p.load(is);
return p.getProperty(JAR_ARTIFACT_ID);
private static String parseArtifactIdFromJar(String jarLocation) throws IOException {
try (JarFile jarFile = new JarFile(jarLocation)) {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
java.util.jar.JarEntry entry = entries.nextElement();
if (entry.getName().endsWith(JAR_POM_PROPERTIES)) {
try (InputStream is = jarFile.getInputStream(entry)) {
Properties p = new Properties();
p.load(is);
return p.getProperty(JAR_ARTIFACT_ID);
}
}
}
return null;
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,23 @@
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.nio.file.Paths;

import static java.io.File.separator;

public class JarUtilsTest {

@Test
public void getArtifactIdFromTestClassPath() throws IOException {
URL url = this.getClass().getClassLoader().getResource("sample-biz-withjar.jar");
String artifactId = JarUtils.getArtifactIdFromLocalClassPath(url.getPath());
String artifactId = JarUtils.parseArtifactId(url.getPath());
Assert.assertEquals("sofa-ark-sample-springboot-ark", artifactId);
}

@Test
public void getArtifactIdFromTestClassPath1() throws IOException {
URL url = this.getClass().getClassLoader().getResource("SampleClass.class");
String artifactId = JarUtils.parseArtifactId(url.getPath());
Assert.assertEquals("sofa-ark-archive", artifactId);
}

Expand All @@ -38,8 +48,13 @@ public void getArtifactIdFromClassPath() throws IOException {
URL clazzURL = this.getClass().getClassLoader()
.getResource("com/alipay/sofa/ark/loader/jar/JarUtils.class");

String artifactId = JarUtils.getArtifactIdFromLocalClassPath(clazzURL.getPath());
String artifactId = JarUtils.parseArtifactId(clazzURL.getPath());
Assert.assertEquals("sofa-ark-archive", artifactId);

String classPathRoot = this.getClass().getClassLoader().getResource("").getPath();
String classPath = Paths.get(classPathRoot).getParent().toFile().getAbsolutePath();
String artifactId1 = JarUtils.parseArtifactId(classPath);
Assert.assertNotNull(artifactId1);
}

@Test
Expand Down Expand Up @@ -97,34 +112,20 @@ public void testParseArtifactIdFromJarInJarName() throws Exception {
}

@Test
public void testParseArtifactIdFromJarPom() {
public void testParseArtifactIdFromJarInJar() throws Exception {
URL jar = JarUtilsTest.class.getResource("/sample-biz-withjar.jar");
String artifactId0 = JarUtils.getJarArtifactId(jar.getFile());
Assert.assertEquals("sofa-ark-sample-springboot-ark", artifactId0);
Method method = JarUtils.class.getDeclaredMethod("parseArtifactIdFromJarInJar",
String.class);
method.setAccessible(Boolean.TRUE);
Assert.assertEquals("slf4j-api",
method.invoke(JarUtils.class, jar.getFile() + "!/lib/slf4j-api-1.7.30.jar"));
}

@Test
public void testParseArtifactIdFromJarInJarPom() {
URL jar = JarUtilsTest.class.getResource("/sample-biz-withjar.jar");
String artifactId0 = JarUtils
.getJarArtifactId(jar.getFile() + "!/lib/slf4j-api-1.7.30.jar");
String artifactId0 = JarUtils.parseArtifactId(jar.getFile()
+ "!/lib/slf4j-api-1.7.30.jar!/");
Assert.assertEquals("slf4j-api", artifactId0);
}

@Test
public void testParseArtifactIdFromJarPoms() throws Exception {
Method method = JarUtils.class.getDeclaredMethod("doGetArtifactIdFromJarPom", String.class);
method.setAccessible(Boolean.TRUE);

URL jar = JarUtilsTest.class.getResource("/sample-biz-withjar.jar");

String jarPath = jar.getFile();
String nestedJarPath = jar.getFile() + "!/lib/slf4j-api-1.7.30.jar";

String artifactId0 = (String) method.invoke(JarUtils.class, jarPath);
Assert.assertEquals("sofa-ark-sample-springboot-ark", artifactId0);

String artifactId1 = (String) method.invoke(JarUtils.class, nestedJarPath);
Assert.assertEquals("slf4j-api", artifactId1);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,13 @@
import com.alipay.sofa.ark.spi.service.event.EventAdminService;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static com.alipay.sofa.ark.loader.jar.JarUtils.getArtifactIdFromLocalClassPath;
import static org.apache.commons.io.FileUtils.deleteQuietly;

/**
Expand Down Expand Up @@ -414,38 +412,21 @@ public BizModel setDeclaredLibraries(String declaredLibraries) {
return this;
}

/**
* check if the class is defined in classloader
* @param classLocation
* @return
*/
public boolean isDeclared(String classLocation) {
// compatibility with no-declaredMode
if (!isDeclaredMode()) {
return true;
}
if (!StringUtils.isEmpty(classLocation)) {
if (classLocation.contains(".jar")) {
return checkDeclaredWithCache(classLocation);
}
return true;
}

return false;
}

/**
* check if the resource is defined in classloader, ignore jar version
* @param url
* @return
*/
public boolean isDeclared(URL url) {
public boolean isDeclared(URL url, String resourceName) {
// compatibility with no-declaredMode
if (!isDeclaredMode()) {
return true;
}
if (url != null) {
String libraryFile = url.getFile().replace("file:", "");
if (!StringUtils.isEmpty(resourceName) && libraryFile.endsWith(resourceName)) {
libraryFile = libraryFile.substring(0, libraryFile.lastIndexOf(resourceName));
}
return checkDeclaredWithCache(libraryFile);
}

Expand All @@ -460,29 +441,20 @@ public boolean isDeclaredMode() {
}

private boolean checkDeclaredWithCache(String libraryFile) {
// remove specific file real name, extract jar file path
int index = libraryFile.lastIndexOf("!/");
String jarFilePath = libraryFile;
if (index != -1) {
jarFilePath = libraryFile.substring(0, index);
}
return declaredCacheMap.computeIfAbsent(jarFilePath, this::doCheckDeclared);
// set key as jar, but need to checkDeclared by specific file.
return declaredCacheMap.computeIfAbsent(libraryFile, this::doCheckDeclared);
}

private boolean doCheckDeclared(String jarFilePath) {
String artifactId = "";
if (jarFilePath.contains(".jar")) {
artifactId = JarUtils.getJarArtifactId(jarFilePath);
// if in jar, and can't get artifactId from jar file, then just rollback to all delegate.
if (artifactId == null) {
String artifactId = JarUtils.parseArtifactId(jarFilePath);
if (artifactId == null) {
if (jarFilePath.contains(".jar!") || jarFilePath.endsWith(".jar")) {
// if in jar, and can't get artifactId from jar file, then just rollback to all delegate.
LOGGER.info(String.format("Can't find artifact id for %s, default as declared.",
jarFilePath));
return true;
}
} else {
artifactId = getArtifactIdFromLocalClassPath(jarFilePath);
// for not in jar, then default not delegate.
if (artifactId == null) {
} else {
// for not in jar, then default not delegate.
LOGGER.info(String.format(
"Can't find artifact id for %s, default as not declared.", jarFilePath));
return false;
Expand Down
Loading

0 comments on commit 3b7b664

Please sign in to comment.