Skip to content

Instantly share code, notes, and snippets.

@thomasdarimont
Last active July 1, 2024 08:18
Show Gist options
  • Save thomasdarimont/f387a8352ad76cb00223476b0c74a03b to your computer and use it in GitHub Desktop.
Save thomasdarimont/f387a8352ad76cb00223476b0c74a03b to your computer and use it in GitHub Desktop.
PoC for fetching the Java source code of an artifact from a maven repository
package demo;
import com.github.javaparser.JavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.MethodDeclaration;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.aether.supplier.RepositorySystemSupplier;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.Optional;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class GetMethodSourceDemo {
static class MavenResolver {
private static RepositorySystem newRepositorySystem() {
return new RepositorySystemSupplier().get();
}
public static RepositorySystemSession newRepositorySystemSession(RepositorySystem system) {
DefaultRepositorySystemSession session = new DefaultRepositorySystemSession();
session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, new LocalRepository("target/local-repo")));
return session;
}
public static File resolveArtifact(String groupId, String artifactId, String version) throws ArtifactResolutionException {
RepositorySystem system = newRepositorySystem();
RepositorySystemSession session = newRepositorySystemSession(system);
Artifact artifact = new DefaultArtifact(groupId, artifactId, "sources", "jar", version);
ArtifactRequest request = new ArtifactRequest();
request.setArtifact(artifact);
request.setRepositories(Collections.singletonList(new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2/").build()));
ArtifactResult result = system.resolveArtifact(session, request);
return result.getArtifact().getFile();
}
}
static class SourceExtractor {
public static String readSourceFile(File jarFile, String className) throws IOException {
try (JarFile jar = new JarFile(jarFile)) {
String entryName = className.replace('.', '/') + ".java";
JarEntry entry = jar.getJarEntry(entryName);
if (entry != null) {
try (InputStream input = jar.getInputStream(entry)) {
Path tempFile = Files.createTempFile("source-", ".java");
Files.copy(input, tempFile, StandardCopyOption.REPLACE_EXISTING);
return new String(Files.readAllBytes(tempFile), StandardCharsets.UTF_8);
}
} else {
throw new IOException("Source file for class " + className + " not found in JAR");
}
}
}
}
static class MethodExtractor {
public static String getMethodSource(String sourceCode, String methodName) {
CompilationUnit cu = new JavaParser().parse(sourceCode).getResult().orElseThrow();
Optional<MethodDeclaration> method = cu.findAll(MethodDeclaration.class).stream().filter(m -> m.getNameAsString().equals(methodName)).findFirst();
return method.map(MethodDeclaration::toString).orElse(null);
}
}
public static void main(String[] args) throws Exception {
File sourceFile = MavenResolver.resolveArtifact("org.springframework", "spring-core", "6.1.10");
String sourceCode = SourceExtractor.readSourceFile(sourceFile, "org.springframework.util.Assert");
String methodSource = MethodExtractor.getMethodSource(sourceCode, "assignableCheckFailed");
System.out.println("Method source: \n" + methodSource);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.thomasdarimont.training</groupId>
<artifactId>java-workbench</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>org.example</groupId>
<artifactId>lib-maven-aether</artifactId>
<properties>
<java.version>22</java.version>
<java.release>22</java.release>
<maven-aether.version>1.1.0</maven-aether.version>
<javaparser.version>3.26.0</javaparser.version>
<maven-resolver.version>1.9.20</maven-resolver.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId>
<version>${maven-resolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-spi</artifactId>
<version>${maven-resolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-supplier</artifactId>
<version>${maven-resolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-util</artifactId>
<version>${maven-resolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-impl</artifactId>
<version>${maven-resolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-connector-basic</artifactId>
<version>${maven-resolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-http</artifactId>
<version>${maven-resolver.version}</version>
</dependency>
<dependency>
<groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-transport-file</artifactId>
<version>1.9.13</version>
</dependency>
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>${javaparser.version}</version>
</dependency>
</dependencies>
</project>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment