From 6abf5f0b747db2d9d098d5d35f4859f68f20c867 Mon Sep 17 00:00:00 2001 From: Jason Penilla <11360596+jpenilla@users.noreply.github.com> Date: Mon, 23 Jun 2025 22:34:01 -0700 Subject: [PATCH] Avoid and discourage use of Maven Central as a CDN (#12692) * Default LibraryLoader to Google's Maven Central mirror, add MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR, and warn on use of Maven Central with MavenLibraryResolver * Account for both Maven Central URLs * Update Javadoc (cherry picked from commit 62b7f86dae659deb2fc450285452d7c1439f92dc) --- .../library/impl/MavenLibraryResolver.java | 34 ++++++++++++++++++- .../org/bukkit/plugin/java/LibraryLoader.java | 8 +++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java b/paper-api/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java index 107705db2d..c1fccd64b1 100644 --- a/paper-api/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java +++ b/paper-api/src/main/java/io/papermc/paper/plugin/loader/library/impl/MavenLibraryResolver.java @@ -41,7 +41,7 @@ import org.slf4j.LoggerFactory; * MavenLibraryResolver resolver = new MavenLibraryResolver(); * resolver.addDependency(new Dependency(new DefaultArtifact("org.jooq:jooq:3.17.7"), null)); * resolver.addRepository(new RemoteRepository.Builder( - * "central", "default", "https://repo1.maven.org/maven2/" + * "central", "default", MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR * ).build()); * } *

@@ -50,6 +50,21 @@ import org.slf4j.LoggerFactory; @NullMarked public class MavenLibraryResolver implements ClassPathLibrary { + /** + * The default Maven Central mirror, configurable through the {@code PAPER_DEFAULT_CENTRAL_REPOSITORY} environment + * variable. Use this instead of Maven Central directly when you do not have your own mirror, as using + * Maven Central as a CDN is against the Maven Central Terms of Service, and you will cause users to hit + * rate limits. + * + *

This repository is also used by the legacy {@link org.bukkit.plugin.java.LibraryLoader}.

+ */ + public static final String MAVEN_CENTRAL_DEFAULT_MIRROR = getDefaultMavenCentralMirror(); + private static final List MAVEN_CENTRAL_URLS = List.of( + "https://repo1.maven.org/maven2", + "http://repo1.maven.org/maven2", + "https://repo.maven.apache.org/maven2", + "http://repo.maven.apache.org/maven2" + ); private static final Logger LOGGER = LoggerFactory.getLogger("MavenLibraryResolver"); private final RepositorySystem repository; @@ -105,6 +120,12 @@ public class MavenLibraryResolver implements ClassPathLibrary { * dependencies from */ public void addRepository(final RemoteRepository remoteRepository) { + if (MAVEN_CENTRAL_URLS.stream().anyMatch(remoteRepository.getUrl()::startsWith)) { + LOGGER.warn( + "Use of Maven Central as a CDN is against the Maven Central Terms of Service. Use MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR instead.", + new RuntimeException("Plugin used Maven Central for library resolution") + ); + } this.repositories.add(remoteRepository); } @@ -130,4 +151,15 @@ public class MavenLibraryResolver implements ClassPathLibrary { store.addLibrary(file.toPath()); } } + + private static String getDefaultMavenCentralMirror() { + String central = System.getenv("PAPER_DEFAULT_CENTRAL_REPOSITORY"); + if (central == null) { + central = System.getProperty("org.bukkit.plugin.java.LibraryLoader.centralURL"); + } + if (central == null) { + central = "https://maven-central.storage-download.googleapis.com/maven2"; + } + return central; + } } diff --git a/paper-api/src/main/java/org/bukkit/plugin/java/LibraryLoader.java b/paper-api/src/main/java/org/bukkit/plugin/java/LibraryLoader.java index c66252802c..c43cc85bb2 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/java/LibraryLoader.java +++ b/paper-api/src/main/java/org/bukkit/plugin/java/LibraryLoader.java @@ -1,12 +1,12 @@ // CHECKSTYLE:OFF package org.bukkit.plugin.java; +import io.papermc.paper.plugin.loader.library.impl.MavenLibraryResolver; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; @@ -49,6 +49,10 @@ public class LibraryLoader public static java.util.function.BiFunction LIBRARY_LOADER_FACTORY; // Paper - rewrite reflection in libraries public static java.util.function.Function, List> REMAPPER; // Paper - remap libraries + private static List getRepositories() { + return List.of(new RemoteRepository.Builder("central", "default", MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR).build()); + } + public LibraryLoader(@NotNull Logger logger) { this.logger = logger; @@ -78,7 +82,7 @@ public class LibraryLoader session.setSystemProperties( System.getProperties() ); session.setReadOnly(); - this.repositories = repository.newResolutionRepositories( session, Arrays.asList( new RemoteRepository.Builder( "central", "default", "https://repo.maven.apache.org/maven2" ).build() ) ); + this.repositories = repository.newResolutionRepositories( session, getRepositories() ); } @Nullable