Skip to content

Commit fb9b924

Browse files
authored
Merge pull request #44 from frengor/gradle-resolver
Move TransitiveDependencyCollector to separate subproject
2 parents 95c5177 + 03f4ff0 commit fb9b924

File tree

10 files changed

+173
-69
lines changed

10 files changed

+173
-69
lines changed

core/build.gradle.kts

+71-4
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,92 @@
1+
import groovy.xml.MarkupBuilder
2+
import java.security.MessageDigest
3+
import java.util.Base64
4+
15
plugins {
26
id("net.kyori.blossom") version "2.0.1"
37
}
48

5-
dependencies {
6-
compileOnly("org.apache.maven.resolver:maven-resolver-supplier:1.9.15")
7-
compileOnly("org.apache.maven:maven-resolver-provider:3.9.4")
9+
val libbyMavenResolverRepo = layout.buildDirectory.dir("libby-maven-resolver-repo").get()
10+
val libbyMavenResolverJar = provider {}.flatMap { // Use a provider to not resolve shadowTask task too early
11+
project(":libby-maven-resolver").tasks.named("shadowJar").flatMap { (it as Jar).archiveFile }
12+
}
13+
14+
val deleteLibbyMavenResolver = tasks.register<Delete>("deleteLibbyMavenResolver") {
15+
delete(libbyMavenResolverRepo)
16+
isFollowSymlinks = false
17+
}
18+
19+
val copyLibbyMavenResolver = tasks.register<Copy>("copyLibbyMavenResolver") {
20+
dependsOn(":libby-maven-resolver:shadowJar")
21+
dependsOn(deleteLibbyMavenResolver)
22+
}
23+
setupCopy()
24+
25+
tasks.test {
26+
dependsOn(copyLibbyMavenResolver)
827
}
928

1029
sourceSets {
1130
main {
1231
blossom {
1332
javaSources {
1433
property("version", project.version.toString())
34+
property("libbyMavenResolverChecksum", provider {
35+
val md = MessageDigest.getInstance("SHA-256")
36+
val sha256 = md.digest(libbyMavenResolverJar.get().asFile.readBytes())
37+
Base64.getEncoder().encodeToString(sha256)
38+
})
1539
}
1640
}
1741
}
1842
test {
1943
blossom {
2044
javaSources {
2145
property("buildDir", layout.buildDirectory.asFile.get().absolutePath.replace("\\", "\\\\"))
46+
property("libbyMavenResolverRepo", libbyMavenResolverRepo.asFile.absolutePath.replace("\\", "\\\\"))
47+
}
48+
}
49+
}
50+
}
51+
52+
tasks.named("generateJavaTemplates") {
53+
dependsOn(":libby-maven-resolver:shadowJar")
54+
}
55+
56+
fun setupCopy() {
57+
val version = project.version.toString()
58+
val partialPath = "${project.group.toString().replace('.', '/')}/libby-maven-resolver/${version}"
59+
val mainFolder = libbyMavenResolverRepo.dir(partialPath)
60+
61+
copyLibbyMavenResolver {
62+
from(libbyMavenResolverJar)
63+
into(mainFolder)
64+
}
65+
66+
if (!version.endsWith("-SNAPSHOT")) {
67+
return
68+
}
69+
70+
// Generate snapshot's maven-metadata-local.xml
71+
copyLibbyMavenResolver {
72+
doFirst {
73+
mainFolder.file("maven-metadata-local.xml").asFile.printWriter(Charsets.UTF_8).use {
74+
val builder = MarkupBuilder(it)
75+
builder.doubleQuotes = true
76+
builder.mkp.xmlDeclaration(mapOf("version" to "1.0", "encoding" to "UTF-8"))
77+
builder.withGroovyBuilder {
78+
"metadata"("modelVersion" to "1.1.0") {
79+
"groupId"(project.group.toString())
80+
"artifactId"("libby-maven-resolver")
81+
"version"(version)
82+
"versioning"() {
83+
"snapshot"() {
84+
"localCopy"(true)
85+
}
86+
}
87+
}
88+
}
2289
}
2390
}
2491
}
25-
}
92+
}

core/src/main/java-templates/com/alessiodp/libby/LibbyProperties.java

+5
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,9 @@ public class LibbyProperties {
1313
* User agent string to use when downloading libraries
1414
*/
1515
public static final String HTTP_USER_AGENT = "libby/" + VERSION;
16+
17+
/**
18+
* Checksum of libby-maven-resolver jar
19+
*/
20+
public static final String LIBBY_MAVEN_RESOLVER_CHECKSUM = "{{ libbyMavenResolverChecksum }}";
1621
}

core/src/main/java/com/alessiodp/libby/LibraryManager.java

+34-28
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,8 @@ public Collection<String> resolveLibrary(@NotNull Library library) {
329329
*/
330330
@Nullable
331331
protected String resolveSnapshot(@NotNull String repository, @NotNull Library library) {
332-
String url = requireNonNull(repository, "repository") + requireNonNull(library, "library").getPartialPath() + "maven-metadata.xml";
332+
String mavenMetadata = repository.startsWith("file") ? "maven-metadata-local.xml" : "maven-metadata.xml";
333+
String url = requireNonNull(repository, "repository") + requireNonNull(library, "library").getPartialPath() + mavenMetadata;
333334
try {
334335
URLConnection connection = new URL(requireNonNull(url, "url")).openConnection();
335336

@@ -372,7 +373,7 @@ protected String getURLFromMetadata(@NotNull InputStream inputStream, @NotNull L
372373
requireNonNull(inputStream, "inputStream");
373374
requireNonNull(library, "library");
374375

375-
String timestamp, buildNumber;
376+
String version = library.getVersion();
376377
try {
377378
// This reads the maven-metadata.xml file and gets the snapshot info from the <snapshot> tag.
378379
// Example tag:
@@ -394,37 +395,42 @@ protected String getURLFromMetadata(@NotNull InputStream inputStream, @NotNull L
394395
if (snapshot.getNodeType() != Node.ELEMENT_NODE) {
395396
return null;
396397
}
397-
Node timestampNode = ((Element) snapshot).getElementsByTagName("timestamp").item(0);
398-
if (timestampNode == null || timestampNode.getNodeType() != Node.ELEMENT_NODE) {
399-
return null;
400-
}
401-
Node buildNumberNode = ((Element) snapshot).getElementsByTagName("buildNumber").item(0);
402-
if (buildNumberNode == null || buildNumberNode.getNodeType() != Node.ELEMENT_NODE) {
403-
return null;
404-
}
405-
Node timestampChild = timestampNode.getFirstChild();
406-
if (timestampChild == null || timestampChild.getNodeType() != Node.TEXT_NODE) {
407-
return null;
408-
}
409-
Node buildNumberChild = buildNumberNode.getFirstChild();
410-
if (buildNumberChild == null || buildNumberChild.getNodeType() != Node.TEXT_NODE) {
411-
return null;
398+
Node localCopyNode = ((Element) snapshot).getElementsByTagName("localCopy").item(0);
399+
if (localCopyNode == null || localCopyNode.getNodeType() != Node.ELEMENT_NODE) {
400+
// Resolve with snapshot number instead of base name
401+
Node timestampNode = ((Element) snapshot).getElementsByTagName("timestamp").item(0);
402+
if (timestampNode == null || timestampNode.getNodeType() != Node.ELEMENT_NODE) {
403+
return null;
404+
}
405+
Node buildNumberNode = ((Element) snapshot).getElementsByTagName("buildNumber").item(0);
406+
if (buildNumberNode == null || buildNumberNode.getNodeType() != Node.ELEMENT_NODE) {
407+
return null;
408+
}
409+
Node timestampChild = timestampNode.getFirstChild();
410+
if (timestampChild == null || timestampChild.getNodeType() != Node.TEXT_NODE) {
411+
return null;
412+
}
413+
Node buildNumberChild = buildNumberNode.getFirstChild();
414+
if (buildNumberChild == null || buildNumberChild.getNodeType() != Node.TEXT_NODE) {
415+
return null;
416+
}
417+
String timestamp = timestampChild.getNodeValue();
418+
String buildNumber = buildNumberChild.getNodeValue();
419+
420+
version = library.getVersion();
421+
// Call .substring(...) only on versions ending in "-SNAPSHOT".
422+
// It should never happen that a snapshot version doesn't end in "-SNAPSHOT", but better be sure
423+
if (version.endsWith("-SNAPSHOT")) {
424+
version = version.substring(0, version.length() - "-SNAPSHOT".length());
425+
}
426+
427+
version = version + '-' + timestamp + '-' + buildNumber;
412428
}
413-
timestamp = timestampChild.getNodeValue();
414-
buildNumber = buildNumberChild.getNodeValue();
415429
} catch (ParserConfigurationException | SAXException e) {
416430
logger.debug("Invalid maven-metadata.xml", e);
417431
return null;
418432
}
419-
420-
String version = library.getVersion();
421-
// Call .substring(...) only on versions ending in "-SNAPSHOT".
422-
// It should never happen that a snapshot version doesn't end in "-SNAPSHOT", but better be sure
423-
if (version.endsWith("-SNAPSHOT")) {
424-
version = version.substring(0, version.length() - "-SNAPSHOT".length());
425-
}
426-
427-
return Util.craftPath(library.getPartialPath(), library.getArtifactId(), version + '-' + timestamp + '-' + buildNumber, library.getClassifier());
433+
return Util.craftPath(library.getPartialPath(), library.getArtifactId(), version, library.getClassifier());
428434
}
429435

430436
/**

core/src/main/java/com/alessiodp/libby/transitive/TransitiveDependencyHelper.java

+15-14
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
package com.alessiodp.libby.transitive;
22

3+
import com.alessiodp.libby.LibbyProperties;
34
import com.alessiodp.libby.Library;
45
import com.alessiodp.libby.LibraryManager;
56
import com.alessiodp.libby.Util;
67
import com.alessiodp.libby.classloader.IsolatedClassLoader;
78
import org.jetbrains.annotations.NotNull;
89
import org.jetbrains.annotations.Nullable;
910

10-
import java.io.IOException;
1111
import java.lang.reflect.Constructor;
1212
import java.lang.reflect.Method;
1313
import java.nio.file.Path;
@@ -31,10 +31,15 @@
3131
*/
3232
public class TransitiveDependencyHelper {
3333

34+
/**
35+
* com.alessiodp.libby.transitive.TransitiveDependencyCollector class name for reflections
36+
*/
37+
private static final String TRANSITIVE_DEPENDENCY_COLLECTOR_CLASS = replaceWithDots("com{}alessiodp{}libby{}transitive{}TransitiveDependencyCollector");
38+
3439
/**
3540
* org.eclipse.aether.artifact.Artifact class name for reflections
3641
*/
37-
private static final String ARTIFACT_CLASS = replaceWithDots("org.eclipse.aether.artifact.Artifact");
42+
private static final String ARTIFACT_CLASS = replaceWithDots("org{}eclipse{}aether{}artifact{}Artifact");
3843

3944
/**
4045
* TransitiveDependencyCollector class instance, used in {@link #findTransitiveLibraries(Library)}
@@ -68,21 +73,17 @@ public TransitiveDependencyHelper(@NotNull LibraryManager libraryManager, @NotNu
6873
this.libraryManager = libraryManager;
6974

7075
IsolatedClassLoader classLoader = new IsolatedClassLoader();
71-
String collectorClassName = "com.alessiodp.libby.transitive.TransitiveDependencyCollector";
72-
String collectorClassPath = '/' + collectorClassName.replace('.', '/') + ".class";
73-
74-
for (TransitiveLibraryResolutionDependency dependency : TransitiveLibraryResolutionDependency.values()) {
75-
classLoader.addPath(libraryManager.downloadLibrary(dependency.toLibrary()));
76-
}
7776

78-
final Class<?> transitiveDependencyCollectorClass;
79-
try {
80-
transitiveDependencyCollectorClass = classLoader.defineClass(collectorClassName, requireNonNull(getClass().getResourceAsStream(collectorClassPath), "resourceCollectorClass"));
81-
} catch (IOException e) {
82-
throw new RuntimeException(e);
83-
}
77+
classLoader.addPath(libraryManager.downloadLibrary(Library.builder()
78+
.groupId("com{}alessiodp{}libby")
79+
.artifactId("libby-maven-resolver")
80+
.version(LibbyProperties.VERSION)
81+
.checksumFromBase64(LibbyProperties.LIBBY_MAVEN_RESOLVER_CHECKSUM)
82+
.build()
83+
));
8484

8585
try {
86+
Class<?> transitiveDependencyCollectorClass = classLoader.loadClass(TRANSITIVE_DEPENDENCY_COLLECTOR_CLASS);
8687
Class<?> artifactClass = classLoader.loadClass(ARTIFACT_CLASS);
8788

8889
// com.alessiodp.libby.TransitiveDependencyCollector(Path)

core/src/test/java-templates/com/alessiodp/libby/LibbyTestProperties.java

+5
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,9 @@ public class LibbyTestProperties {
88
* Build dir path
99
*/
1010
public static final String BUILD_DIR = "{{ buildDir }}";
11+
12+
/**
13+
* Local repo set up by gradle for libby-maven-resolver
14+
*/
15+
public static final String LIBBY_MAVEN_RESOLVER_REPO = "{{ libbyMavenResolverRepo }}";
1116
}

core/src/main/java/com/alessiodp/libby/transitive/TransitiveLibraryResolutionDependency.java core/src/test/java/com/alessiodp/libby/transitive/MavenResolverDependencies.java

+2-12
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,7 @@
44
import com.alessiodp.libby.Repositories;
55
import org.jetbrains.annotations.NotNull;
66

7-
/**
8-
* Represents the libraries required for Maven transitive dependency resolution and related operations.
9-
* <p>
10-
* This class bundles Maven Resolver Supplier, Maven Resolver Provider and their transitive dependencies.
11-
*/
12-
enum TransitiveLibraryResolutionDependency {
7+
enum MavenResolverDependencies {
138
MAVEN_RESOLVER_SUPPLIER("org{}apache{}maven{}resolver", "maven-resolver-supplier", "1.9.15", "BNncFRDRqBBHWixE0DYfFydh7h9bc3mhC/MBr5WD448"),
149
MAVEN_RESOLVER_API("org{}apache{}maven{}resolver", "maven-resolver-api", "1.9.15", "1Ugp1gooJ7uXYxK9u/YnlR5hMpJ2LuFGFAxRqn3OYL4"),
1510
MAVEN_RESOLVER_UTIL("org{}apache{}maven{}resolver", "maven-resolver-util", "1.9.15", "z9Gnzg0gpWHtZrI18lpvwa5A/f8Zr6k1GrCpZNTlVm8"),
@@ -38,7 +33,7 @@ enum TransitiveLibraryResolutionDependency {
3833

3934
private final String groupId, artifactId, version, checksum;
4035

41-
TransitiveLibraryResolutionDependency(@NotNull String groupId, @NotNull String artifactId, @NotNull String version, @NotNull String checksum) {
36+
MavenResolverDependencies(@NotNull String groupId, @NotNull String artifactId, @NotNull String version, @NotNull String checksum) {
4237
this.groupId = groupId;
4338
this.artifactId = artifactId;
4439
this.version = version;
@@ -53,11 +48,6 @@ public Library toLibrary() {
5348
.version(version)
5449
.checksumFromBase64(checksum)
5550
.repository(Repositories.MAVEN_CENTRAL)
56-
// Relocate all packages used in Libby to avoid conflicts
57-
.relocate("org{}eclipse{}aether{}util", "org.eclipse.aether.util") // maven-resolver-util
58-
.relocate("org{}eclipse{}aether", "org.eclipse.aether") // maven-resolver-api
59-
.relocate("org{}apache{}maven{}repository{}internal", "org.apache.maven.repository.internal") // maven-resolver-provider
60-
6151
.build();
6252
}
6353
}

core/src/test/java/com/alessiodp/libby/transitive/TransitiveDownloadingTest.java

+15-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.alessiodp.libby.transitive;
22

3+
import com.alessiodp.libby.LibbyTestProperties;
34
import com.alessiodp.libby.Library;
45
import com.alessiodp.libby.LibraryManagerMock;
56
import com.alessiodp.libby.TestUtils;
@@ -8,6 +9,7 @@
89
import org.junit.jupiter.api.Test;
910

1011
import java.nio.file.Path;
12+
import java.nio.file.Paths;
1113
import java.util.*;
1214

1315
import static org.junit.jupiter.api.Assertions.*;
@@ -20,7 +22,7 @@ public class TransitiveDownloadingTest {
2022
.version("1.9.15")
2123
.resolveTransitiveDependencies(true)
2224
.build();
23-
private static final Library EXCLUDED_LIBRARY = TransitiveLibraryResolutionDependency.MAVEN_RESOLVER_API.toLibrary();
25+
private static final Library EXCLUDED_LIBRARY = MavenResolverDependencies.MAVEN_RESOLVER_API.toLibrary();
2426
private static final Library MAVEN_RESOLVER_SUPPLIER_WITH_EXCLUDED = Library.builder()
2527
.groupId(MAVEN_RESOLVER_SUPPLIER.getGroupId())
2628
.artifactId(MAVEN_RESOLVER_SUPPLIER.getArtifactId())
@@ -33,6 +35,7 @@ public class TransitiveDownloadingTest {
3335
.artifactId("bungeecord-api")
3436
.version("1.20-R0.2-SNAPSHOT")
3537
.repository("https://oss.sonatype.org/content/repositories/snapshots")
38+
.repository("https://hub.spigotmc.org/nexus/content/groups/public/")
3639
.isolatedLoad(true)
3740
.loaderId("bungeecord")
3841
.resolveTransitiveDependencies(true)
@@ -43,6 +46,8 @@ public class TransitiveDownloadingTest {
4346
@BeforeEach
4447
public void setUp() throws Exception {
4548
libraryManager = new LibraryManagerMock();
49+
// Local repo set up by gradle for libby-maven-resolver
50+
libraryManager.addRepository(Paths.get(LibbyTestProperties.LIBBY_MAVEN_RESOLVER_REPO).toUri().toString());
4651
libraryManager.addMavenCentral();
4752
}
4853

@@ -69,29 +74,29 @@ public void snapshotLibraryTransitiveLoad() throws Exception {
6974
public void transitiveWithExcludedLoad() {
7075
libraryManager.loadLibrary(MAVEN_RESOLVER_SUPPLIER_WITH_EXCLUDED);
7176

72-
checkDownloadedDependencies(TransitiveLibraryResolutionDependency.MAVEN_RESOLVER_API);
77+
checkDownloadedDependencies(MavenResolverDependencies.MAVEN_RESOLVER_API);
7378
}
7479

7580
/**
76-
* Compares the libraries required by maven-resolver-supplier with the ones declared in {@link TransitiveLibraryResolutionDependency}.
81+
* Compares the libraries required by maven-resolver-supplier with the ones declared in {@link MavenResolverDependencies}.
7782
*
7883
* @param excludedDependencies Optionally excluded more dependencies
7984
*/
80-
private void checkDownloadedDependencies(TransitiveLibraryResolutionDependency... excludedDependencies) {
81-
Set<TransitiveLibraryResolutionDependency> excluded = new HashSet<>();
85+
private void checkDownloadedDependencies(MavenResolverDependencies... excludedDependencies) {
86+
Set<MavenResolverDependencies> excluded = new HashSet<>();
8287
// Always exclude javax.inject since it is excluded by maven-resolver-supplier
83-
excluded.add(TransitiveLibraryResolutionDependency.JAVAX_INJECT);
88+
excluded.add(MavenResolverDependencies.JAVAX_INJECT);
8489
// Always exclude slf4j-nop since it is not included in maven-resolver-supplier
85-
excluded.add(TransitiveLibraryResolutionDependency.SLF4J_NOP);
90+
excluded.add(MavenResolverDependencies.SLF4J_NOP);
8691
excluded.addAll(Arrays.asList(excludedDependencies));
8792

8893
List<String> loaded = libraryManager.getLoaded();
8994
// Assert that the correct amount of libraries has been loaded
90-
assertEquals(TransitiveLibraryResolutionDependency.values().length - excluded.size(), loaded.size());
95+
assertEquals(MavenResolverDependencies.values().length - excluded.size(), loaded.size());
9196

92-
Arrays.stream(TransitiveLibraryResolutionDependency.values())
97+
Arrays.stream(MavenResolverDependencies.values())
9398
.filter(dep -> !excluded.contains(dep))
94-
.map(TransitiveLibraryResolutionDependency::toLibrary)
99+
.map(MavenResolverDependencies::toLibrary)
95100
.forEach(dep -> {
96101
Path path = libraryManager.getSaveDirectory().resolve(dep.getPath()).toAbsolutePath();
97102
assertTrue(loaded.contains(path.toString()));

0 commit comments

Comments
 (0)