Avoid and discourage use of Maven Central as a CDN (#12689)

* 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
This commit is contained in:
Jason Penilla 2025-06-18 10:47:21 -07:00 committed by GitHub
parent 5613ed6dfb
commit 62b7f86dae
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 35 additions and 14 deletions

View file

@ -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());
* }</pre>
* <p>
@ -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.
*
* <p>This repository is also used by the legacy {@link org.bukkit.plugin.java.LibraryLoader}.</p>
*/
public static final String MAVEN_CENTRAL_DEFAULT_MIRROR = getDefaultMavenCentralMirror();
private static final List<String> 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;
}
}

View file

@ -1,11 +1,11 @@
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;
@ -29,7 +29,6 @@ import org.eclipse.aether.resolution.DependencyResult;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
import org.eclipse.aether.transfer.AbstractTransferListener;
import org.eclipse.aether.transfer.TransferCancelledException;
import org.eclipse.aether.transfer.TransferEvent;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
import org.jetbrains.annotations.NotNull;
@ -47,18 +46,8 @@ public class LibraryLoader {
public static java.util.function.BiFunction<URL[], ClassLoader, URLClassLoader> LIBRARY_LOADER_FACTORY; // Paper - rewrite reflection in libraries
public static java.util.function.Function<List<java.nio.file.Path>, List<java.nio.file.Path>> REMAPPER; // Paper - remap libraries
// TODO: Consider moving this and adding per plugin support for defining repositories
private static List<RemoteRepository> getRepositories() {
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://repo.maven.apache.org/maven2";
}
return Arrays.asList(new RemoteRepository.Builder("central", "default", central).build());
return List.of(new RemoteRepository.Builder("central", "default", MavenLibraryResolver.MAVEN_CENTRAL_DEFAULT_MIRROR).build());
}
public LibraryLoader(@NotNull Logger logger) {