You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by cs...@apache.org on 2025/11/20 16:41:22 UTC
(maven-resolver) branch master updated: Make filters daemon friendly (#1681)
This is an automated email from the ASF dual-hosted git repository.
cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git
The following commit(s) were added to refs/heads/master by this push:
new 425fb0b36 Make filters daemon friendly (#1681)
425fb0b36 is described below
commit 425fb0b36d88eb41b2a5ca549edaa249aa6dde9e
Author: Tamas Cservenak <ta...@cservenak.net>
AuthorDate: Thu Nov 20 17:41:16 2025 +0100
Make filters daemon friendly (#1681)
Filters are not daemon friendly; move everything under session. Components are singletons, and use of `RemoteRepository` as key across sessions is something not recommended. For that GURK is needed.
---
.../GroupIdRemoteRepositoryFilterSource.java | 58 +++++++++------
.../PrefixesRemoteRepositoryFilterSource.java | 86 ++++++++++++++++------
2 files changed, 100 insertions(+), 44 deletions(-)
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/GroupIdRemoteRepositoryFilterSource.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/GroupIdRemoteRepositoryFilterSource.java
index 844616bcf..3d6643876 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/GroupIdRemoteRepositoryFilterSource.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/GroupIdRemoteRepositoryFilterSource.java
@@ -33,6 +33,7 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -154,23 +155,34 @@ public final class GroupIdRemoteRepositoryFilterSource extends RemoteRepositoryF
private final PathProcessor pathProcessor;
- private final ConcurrentHashMap<RemoteRepository, GroupTree> rules;
-
- private final ConcurrentHashMap<RemoteRepository, Path> ruleFiles;
-
- private final ConcurrentHashMap<RemoteRepository, Set<String>> recordedRules;
-
- private final AtomicBoolean onShutdownHandlerRegistered;
-
@Inject
public GroupIdRemoteRepositoryFilterSource(
RepositorySystemLifecycle repositorySystemLifecycle, PathProcessor pathProcessor) {
this.repositorySystemLifecycle = requireNonNull(repositorySystemLifecycle);
this.pathProcessor = requireNonNull(pathProcessor);
- this.rules = new ConcurrentHashMap<>();
- this.ruleFiles = new ConcurrentHashMap<>();
- this.recordedRules = new ConcurrentHashMap<>();
- this.onShutdownHandlerRegistered = new AtomicBoolean(false);
+ }
+
+ @SuppressWarnings("unchecked")
+ private ConcurrentMap<RemoteRepository, GroupTree> rules(RepositorySystemSession session) {
+ return (ConcurrentMap<RemoteRepository, GroupTree>)
+ session.getData().computeIfAbsent(getClass().getName() + ".rules", ConcurrentHashMap::new);
+ }
+
+ @SuppressWarnings("unchecked")
+ private ConcurrentMap<RemoteRepository, Path> ruleFiles(RepositorySystemSession session) {
+ return (ConcurrentMap<RemoteRepository, Path>)
+ session.getData().computeIfAbsent(getClass().getName() + ".ruleFiles", ConcurrentHashMap::new);
+ }
+
+ @SuppressWarnings("unchecked")
+ private ConcurrentMap<RemoteRepository, Set<String>> recordedRules(RepositorySystemSession session) {
+ return (ConcurrentMap<RemoteRepository, Set<String>>)
+ session.getData().computeIfAbsent(getClass().getName() + ".recordedRules", ConcurrentHashMap::new);
+ }
+
+ private AtomicBoolean onShutdownHandlerRegistered(RepositorySystemSession session) {
+ return (AtomicBoolean) session.getData()
+ .computeIfAbsent(getClass().getName() + ".onShutdownHandlerRegistered", AtomicBoolean::new);
}
@Override
@@ -206,8 +218,8 @@ public final class GroupIdRemoteRepositoryFilterSource extends RemoteRepositoryF
@Override
public void postProcess(RepositorySystemSession session, List<ArtifactResult> artifactResults) {
if (isEnabled(session) && isRecord(session)) {
- if (onShutdownHandlerRegistered.compareAndSet(false, true)) {
- repositorySystemLifecycle.addOnSystemEndedHandler(this::saveRecordedLines);
+ if (onShutdownHandlerRegistered(session).compareAndSet(false, true)) {
+ repositorySystemLifecycle.addOnSystemEndedHandler(() -> saveRecordedLines(session));
}
for (ArtifactResult artifactResult : artifactResults) {
if (artifactResult.isResolved() && artifactResult.getRepository() instanceof RemoteRepository) {
@@ -216,10 +228,11 @@ public final class GroupIdRemoteRepositoryFilterSource extends RemoteRepositoryF
ruleFile(session, remoteRepository); // populate it; needed for save
String line = "=" + artifactResult.getArtifact().getGroupId();
RemoteRepository normalized = normalizeRemoteRepository(session, remoteRepository);
- recordedRules
+ recordedRules(session)
.computeIfAbsent(normalized, k -> new TreeSet<>())
.add(line);
- rules.compute(normalized, (k, v) -> {
+ rules(session)
+ .compute(normalized, (k, v) -> {
if (v == null || v == GroupTree.SENTINEL) {
v = new GroupTree("");
}
@@ -233,7 +246,7 @@ public final class GroupIdRemoteRepositoryFilterSource extends RemoteRepositoryF
}
private Path ruleFile(RepositorySystemSession session, RemoteRepository remoteRepository) {
- return ruleFiles.computeIfAbsent(normalizeRemoteRepository(session, remoteRepository), r -> getBasedir(
+ return ruleFiles(session).computeIfAbsent(normalizeRemoteRepository(session, remoteRepository), r -> getBasedir(
session, LOCAL_REPO_PREFIX_DIR, CONFIG_PROP_BASEDIR, false)
.resolve(GROUP_ID_FILE_PREFIX
+ RepositoryIdHelper.cachedIdToPathSegment(session).apply(remoteRepository)
@@ -241,8 +254,9 @@ public final class GroupIdRemoteRepositoryFilterSource extends RemoteRepositoryF
}
private GroupTree cacheRules(RepositorySystemSession session, RemoteRepository remoteRepository) {
- return rules.computeIfAbsent(
- normalizeRemoteRepository(session, remoteRepository), r -> loadRepositoryRules(session, r));
+ return rules(session)
+ .computeIfAbsent(
+ normalizeRemoteRepository(session, remoteRepository), r -> loadRepositoryRules(session, r));
}
private GroupTree loadRepositoryRules(RepositorySystemSession session, RemoteRepository remoteRepository) {
@@ -315,10 +329,10 @@ public final class GroupIdRemoteRepositoryFilterSource extends RemoteRepositoryF
/**
* On-close handler that saves recorded rules, if any.
*/
- private void saveRecordedLines() {
+ private void saveRecordedLines(RepositorySystemSession session) {
ArrayList<Exception> exceptions = new ArrayList<>();
- for (Map.Entry<RemoteRepository, Path> entry : ruleFiles.entrySet()) {
- Set<String> recorded = recordedRules.get(entry.getKey());
+ for (Map.Entry<RemoteRepository, Path> entry : ruleFiles(session).entrySet()) {
+ Set<String> recorded = recordedRules(session).get(entry.getKey());
if (recorded != null && !recorded.isEmpty()) {
try {
ArrayList<String> result = new ArrayList<>();
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesRemoteRepositoryFilterSource.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesRemoteRepositoryFilterSource.java
index 854560a59..9a4b2c301 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesRemoteRepositoryFilterSource.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/PrefixesRemoteRepositoryFilterSource.java
@@ -22,10 +22,13 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
+import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collections;
+import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import java.util.function.Supplier;
import org.eclipse.aether.DefaultRepositorySystemSession;
@@ -40,6 +43,7 @@ import org.eclipse.aether.metadata.Metadata;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.MetadataRequest;
import org.eclipse.aether.resolution.MetadataResult;
+import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory;
import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter;
import org.eclipse.aether.spi.connector.layout.RepositoryLayout;
import org.eclipse.aether.spi.connector.layout.RepositoryLayoutProvider;
@@ -191,10 +195,6 @@ public final class PrefixesRemoteRepositoryFilterSource extends RemoteRepository
private final RepositoryLayoutProvider repositoryLayoutProvider;
- private final ConcurrentHashMap<RemoteRepository, PrefixTree> prefixes;
-
- private final ConcurrentHashMap<RemoteRepository, RepositoryLayout> layouts;
-
@Inject
public PrefixesRemoteRepositoryFilterSource(
Supplier<MetadataResolver> metadataResolver,
@@ -203,8 +203,18 @@ public final class PrefixesRemoteRepositoryFilterSource extends RemoteRepository
this.metadataResolver = requireNonNull(metadataResolver);
this.remoteRepositoryManager = requireNonNull(remoteRepositoryManager);
this.repositoryLayoutProvider = requireNonNull(repositoryLayoutProvider);
- this.prefixes = new ConcurrentHashMap<>();
- this.layouts = new ConcurrentHashMap<>();
+ }
+
+ @SuppressWarnings("unchecked")
+ private ConcurrentMap<RemoteRepository, PrefixTree> prefixes(RepositorySystemSession session) {
+ return (ConcurrentMap<RemoteRepository, PrefixTree>)
+ session.getData().computeIfAbsent(getClass().getName() + ".prefixes", ConcurrentHashMap::new);
+ }
+
+ @SuppressWarnings("unchecked")
+ private ConcurrentMap<RemoteRepository, RepositoryLayout> layouts(RepositorySystemSession session) {
+ return (ConcurrentMap<RemoteRepository, RepositoryLayout>)
+ session.getData().computeIfAbsent(getClass().getName() + ".layouts", ConcurrentHashMap::new);
}
@Override
@@ -238,25 +248,26 @@ public final class PrefixesRemoteRepositoryFilterSource extends RemoteRepository
}
/**
- * Caches layout instances for remote repository. In case of unknown layout it returns {@code null}.
+ * Caches layout instances for remote repository. In case of unknown layout it returns {@link #NOT_SUPPORTED}.
*
- * @return the layout instance of {@code null} if layout not supported.
+ * @return the layout instance or {@link #NOT_SUPPORTED} if layout not supported.
*/
private RepositoryLayout cacheLayout(RepositorySystemSession session, RemoteRepository remoteRepository) {
- return layouts.computeIfAbsent(normalizeRemoteRepository(session, remoteRepository), r -> {
+ return layouts(session).computeIfAbsent(normalizeRemoteRepository(session, remoteRepository), r -> {
try {
return repositoryLayoutProvider.newRepositoryLayout(session, remoteRepository);
} catch (NoRepositoryLayoutException e) {
- return null;
+ return NOT_SUPPORTED;
}
});
}
private PrefixTree cachePrefixTree(
RepositorySystemSession session, Path basedir, RemoteRepository remoteRepository) {
- return prefixes.computeIfAbsent(
- normalizeRemoteRepository(session, remoteRepository),
- r -> loadPrefixTree(session, basedir, remoteRepository));
+ return prefixes(session)
+ .computeIfAbsent(
+ normalizeRemoteRepository(session, remoteRepository),
+ r -> loadPrefixTree(session, basedir, remoteRepository));
}
private PrefixTree loadPrefixTree(
@@ -339,16 +350,15 @@ public final class PrefixesRemoteRepositoryFilterSource extends RemoteRepository
session, Collections.emptyList(), Collections.singletonList(remoteRepository), true)
.get(0);
// retrieve prefix as metadata from repository
- MetadataRequest request =
- new MetadataRequest(new DefaultMetadata(PREFIX_FILE_TYPE, Metadata.Nature.RELEASE_OR_SNAPSHOT));
- request.setRepository(prepared);
- request.setDeleteLocalCopyIfMissing(true);
- request.setFavorLocalRepository(true);
MetadataResult result = mr.resolveMetadata(
new DefaultRepositorySystemSession(session)
.setTransferListener(null)
.setConfigProperty(CONFIG_PROP_SKIPPED, Boolean.TRUE.toString()),
- Collections.singleton(request))
+ Collections.singleton(new MetadataRequest(
+ new DefaultMetadata(PREFIX_FILE_TYPE, Metadata.Nature.RELEASE_OR_SNAPSHOT))
+ .setRepository(prepared)
+ .setDeleteLocalCopyIfMissing(true)
+ .setFavorLocalRepository(true)))
.get(0);
if (result.isResolved()) {
return result.getMetadata().getPath();
@@ -371,7 +381,7 @@ public final class PrefixesRemoteRepositoryFilterSource extends RemoteRepository
@Override
public Result acceptArtifact(RemoteRepository remoteRepository, Artifact artifact) {
RepositoryLayout repositoryLayout = cacheLayout(session, remoteRepository);
- if (repositoryLayout == null) {
+ if (repositoryLayout == NOT_SUPPORTED) {
return new SimpleResult(true, "Unsupported layout: " + remoteRepository);
}
return acceptPrefix(
@@ -382,7 +392,7 @@ public final class PrefixesRemoteRepositoryFilterSource extends RemoteRepository
@Override
public Result acceptMetadata(RemoteRepository remoteRepository, Metadata metadata) {
RepositoryLayout repositoryLayout = cacheLayout(session, remoteRepository);
- if (repositoryLayout == null) {
+ if (repositoryLayout == NOT_SUPPORTED) {
return new SimpleResult(true, "Unsupported layout: " + remoteRepository);
}
return acceptPrefix(
@@ -392,7 +402,7 @@ public final class PrefixesRemoteRepositoryFilterSource extends RemoteRepository
private Result acceptPrefix(RemoteRepository repository, String path) {
PrefixTree prefixTree = cachePrefixTree(session, basedir, repository);
- if (PrefixTree.SENTINEL == prefixTree) {
+ if (prefixTree == PrefixTree.SENTINEL) {
return NOT_PRESENT_RESULT;
}
if (prefixTree.acceptedPath(path)) {
@@ -405,4 +415,36 @@ public final class PrefixesRemoteRepositoryFilterSource extends RemoteRepository
private static final RemoteRepositoryFilter.Result NOT_PRESENT_RESULT =
new SimpleResult(true, "Prefix file not present");
+
+ private static final RepositoryLayout NOT_SUPPORTED = new RepositoryLayout() {
+ @Override
+ public List<ChecksumAlgorithmFactory> getChecksumAlgorithmFactories() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean hasChecksums(Artifact artifact) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public URI getLocation(Artifact artifact, boolean upload) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public URI getLocation(Metadata metadata, boolean upload) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<ChecksumLocation> getChecksumLocations(Artifact artifact, boolean upload, URI location) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public List<ChecksumLocation> getChecksumLocations(Metadata metadata, boolean upload, URI location) {
+ throw new UnsupportedOperationException();
+ }
+ };
}