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 e327728d [MRESOLVER-685] Connector pipelining (#679) e327728d is described below commit e327728d54ce85662af95ea1afea762c94fcb1f6 Author: Tamas Cservenak <ta...@cservenak.net> AuthorDate: Tue Apr 8 14:36:08 2025 +0200 [MRESOLVER-685] Connector pipelining (#679) Ability to "pipe" connectors one onto another in controlled and configured fashion. The ide is following: - first (actually connecting to remote) connector is chosen as today (based on priority) - next, new type of factories PipelinedRepositoryConnectorFactory is ordered (by priority) and they can (but does not have to) wrap the delegate in configured order. Factored out existing RRF connector into new factory, and introduced another OfflinePRCF, as so far, "resolver offline" was in fact managed at different spots, and user was still able to circumvent offline setting. This now connector now wraps connector and refuses going remote if session if offline. Vanilla resolver does this: `offline( rrf( basic( repo ) ) )` Ultimate goal, envision this: `offline( mimir( sigcheck( rrf( basic( repo ) ) ) ) )` --- https://issues.apache.org/jira/browse/MRESOLVER-685 --- .../connector/basic/BasicRepositoryConnector.java | 2 +- .../internal/impl/DefaultOfflineController.java | 32 +++++- .../impl/DefaultRepositoryConnectorProvider.java | 34 ++++--- ...ilteringPipelineRepositoryConnectorFactory.java | 76 ++++++++++++++ .../impl/filter/FilteringRepositoryConnector.java | 2 +- .../OfflinePipelineRepositoryConnectorFactory.java | 70 +++++++++++++ .../impl/offline/OfflineRepositoryConnector.java | 109 +++++++++++++++++++++ .../PipelineRepositoryConnectorFactory.java | 54 ++++++++++ .../aether/supplier/RepositorySystemSupplier.java | 26 ++++- .../aether/supplier/RepositorySystemSupplier.java | 26 ++++- src/site/markdown/configuration.md | 5 +- 11 files changed, 416 insertions(+), 20 deletions(-) diff --git a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnector.java b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnector.java index bcc880ad..425e887e 100644 --- a/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnector.java +++ b/maven-resolver-connector-basic/src/main/java/org/eclipse/aether/connector/basic/BasicRepositoryConnector.java @@ -434,7 +434,7 @@ final class BasicRepositoryConnector implements RepositoryConnector { @Override public String toString() { - return String.valueOf(repository); + return BasicRepositoryConnectorFactory.NAME + "( " + repository + " )"; } abstract class TaskRunner implements Runnable { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultOfflineController.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultOfflineController.java index 11d342fe..b639e91e 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultOfflineController.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultOfflineController.java @@ -41,7 +41,7 @@ public class DefaultOfflineController implements OfflineController { private static final String CONFIG_PROPS_PREFIX = ConfigurationProperties.PREFIX_AETHER + "offline."; /** - * Comma-separated list of protocols which are supposed to be resolved offline. + * Comma-separated list of protocols which are supposed to be resolved when session is offline. * * @configurationSource {@link RepositorySystemSession#getConfigProperties()} * @configurationType {@link java.lang.String} @@ -49,13 +49,22 @@ public class DefaultOfflineController implements OfflineController { public static final String CONFIG_PROP_OFFLINE_PROTOCOLS = CONFIG_PROPS_PREFIX + "protocols"; /** - * Comma-separated list of hosts which are supposed to be resolved offline. + * Comma-separated list of hosts which are supposed to be resolved when session is offline. * * @configurationSource {@link RepositorySystemSession#getConfigProperties()} * @configurationType {@link java.lang.String} */ public static final String CONFIG_PROP_OFFLINE_HOSTS = CONFIG_PROPS_PREFIX + "hosts"; + /** + * Comma-separated list of repository IDs which are supposed to be resolved when session is offline. + * + * @configurationSource {@link RepositorySystemSession#getConfigProperties()} + * @configurationType {@link java.lang.String} + * @since TBD + */ + public static final String CONFIG_PROP_OFFLINE_REPOSITORIES = CONFIG_PROPS_PREFIX + "repositories"; + private static final Pattern SEP = Pattern.compile("\\s*,\\s*"); @Override @@ -63,7 +72,9 @@ public class DefaultOfflineController implements OfflineController { throws RepositoryOfflineException { requireNonNull(session, "session cannot be null"); requireNonNull(repository, "repository cannot be null"); - if (isOfflineProtocol(session, repository) || isOfflineHost(session, repository)) { + if (isOfflineProtocol(session, repository) + || isOfflineHost(session, repository) + || isOfflineRepository(session, repository)) { return; } @@ -100,6 +111,21 @@ public class DefaultOfflineController implements OfflineController { return false; } + private boolean isOfflineRepository(RepositorySystemSession session, RemoteRepository repository) { + String[] repositories = getConfig(session, CONFIG_PROP_OFFLINE_REPOSITORIES); + if (repositories != null) { + String repositoryId = repository.getId(); + if (!repositoryId.isEmpty()) { + for (String r : repositories) { + if (r.equals(repositoryId)) { + return true; + } + } + } + } + return false; + } + private String[] getConfig(RepositorySystemSession session, String key) { String value = ConfigUtils.getString(session, "", key).trim(); if (value.isEmpty()) { diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java index b2bc0ace..c655bc50 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultRepositoryConnectorProvider.java @@ -28,13 +28,11 @@ import java.util.List; import java.util.Map; import org.eclipse.aether.RepositorySystemSession; -import org.eclipse.aether.impl.RemoteRepositoryFilterManager; import org.eclipse.aether.impl.RepositoryConnectorProvider; -import org.eclipse.aether.internal.impl.filter.FilteringRepositoryConnector; import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.spi.connector.PipelineRepositoryConnectorFactory; import org.eclipse.aether.spi.connector.RepositoryConnector; import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; -import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter; import org.eclipse.aether.transfer.NoRepositoryConnectorException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,14 +49,14 @@ public class DefaultRepositoryConnectorProvider implements RepositoryConnectorPr private final Map<String, RepositoryConnectorFactory> connectorFactories; - private final RemoteRepositoryFilterManager remoteRepositoryFilterManager; + private final Map<String, PipelineRepositoryConnectorFactory> pipelineConnectorFactories; @Inject public DefaultRepositoryConnectorProvider( Map<String, RepositoryConnectorFactory> connectorFactories, - RemoteRepositoryFilterManager remoteRepositoryFilterManager) { + Map<String, PipelineRepositoryConnectorFactory> pipelineConnectorFactories) { this.connectorFactories = Collections.unmodifiableMap(connectorFactories); - this.remoteRepositoryFilterManager = requireNonNull(remoteRepositoryFilterManager); + this.pipelineConnectorFactories = Collections.unmodifiableMap(pipelineConnectorFactories); } @Override @@ -78,7 +76,6 @@ public class DefaultRepositoryConnectorProvider implements RepositoryConnectorPr PrioritizedComponents<RepositoryConnectorFactory> factories = PrioritizedComponents.reuseOrCreate( session, RepositoryConnectorFactory.class, connectorFactories, RepositoryConnectorFactory::getPriority); - RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session); List<NoRepositoryConnectorException> errors = new ArrayList<>(); for (PrioritizedComponent<RepositoryConnectorFactory> factory : factories.getEnabled()) { try { @@ -94,11 +91,13 @@ public class DefaultRepositoryConnectorProvider implements RepositoryConnectorPr LOGGER.debug(buffer.toString()); } - if (filter != null) { - return new FilteringRepositoryConnector(repository, connector, filter); - } else { - return connector; + connector = pipelineConnector(session, repository, connector); + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Final pipeline: {}", connector); } + + return connector; } catch (NoRepositoryConnectorException e) { // continue and try next factory LOGGER.debug("Could not obtain connector factory for {}", repository, e); @@ -125,4 +124,17 @@ public class DefaultRepositoryConnectorProvider implements RepositoryConnectorPr } throw ex; } + + protected RepositoryConnector pipelineConnector( + RepositorySystemSession session, RemoteRepository repository, RepositoryConnector delegate) { + PrioritizedComponents<PipelineRepositoryConnectorFactory> factories = PrioritizedComponents.reuseOrCreate( + session, + PipelineRepositoryConnectorFactory.class, + pipelineConnectorFactories, + PipelineRepositoryConnectorFactory::getPriority); + for (PrioritizedComponent<PipelineRepositoryConnectorFactory> factory : factories.getEnabled()) { + delegate = factory.getComponent().newInstance(session, repository, delegate); + } + return delegate; + } } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/FilteringPipelineRepositoryConnectorFactory.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/FilteringPipelineRepositoryConnectorFactory.java new file mode 100644 index 00000000..106f7068 --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/FilteringPipelineRepositoryConnectorFactory.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.eclipse.aether.internal.impl.filter; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.impl.RemoteRepositoryFilterManager; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.spi.connector.PipelineRepositoryConnectorFactory; +import org.eclipse.aether.spi.connector.RepositoryConnector; +import org.eclipse.aether.spi.connector.filter.RemoteRepositoryFilter; + +import static java.util.Objects.requireNonNull; + +/** + * A filtering connector factory. + * + * @since TBD + */ +@Singleton +@Named(FilteringPipelineRepositoryConnectorFactory.NAME) +public final class FilteringPipelineRepositoryConnectorFactory implements PipelineRepositoryConnectorFactory { + public static final String NAME = "rrf"; + + private final RemoteRepositoryFilterManager remoteRepositoryFilterManager; + + /** + * This connector should be usually the right-most in pipeline. + */ + private float priority = 10000; + + @Inject + public FilteringPipelineRepositoryConnectorFactory(RemoteRepositoryFilterManager remoteRepositoryFilterManager) { + this.remoteRepositoryFilterManager = requireNonNull(remoteRepositoryFilterManager); + } + + @Override + public RepositoryConnector newInstance( + RepositorySystemSession session, RemoteRepository repository, RepositoryConnector delegate) { + RemoteRepositoryFilter filter = remoteRepositoryFilterManager.getRemoteRepositoryFilter(session); + if (filter != null) { + return new FilteringRepositoryConnector(repository, delegate, filter); + } else { + return delegate; + } + } + + @Override + public float getPriority() { + return priority; + } + + public FilteringPipelineRepositoryConnectorFactory setPriority(float priority) { + this.priority = priority; + return this; + } +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/FilteringRepositoryConnector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/FilteringRepositoryConnector.java index 0ffe4ce9..2102f905 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/FilteringRepositoryConnector.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/filter/FilteringRepositoryConnector.java @@ -104,6 +104,6 @@ public final class FilteringRepositoryConnector implements RepositoryConnector { @Override public String toString() { - return "filtered(" + delegate.toString() + ")"; + return FilteringPipelineRepositoryConnectorFactory.NAME + "( " + delegate.toString() + " )"; } } diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/offline/OfflinePipelineRepositoryConnectorFactory.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/offline/OfflinePipelineRepositoryConnectorFactory.java new file mode 100644 index 00000000..a5ef87e0 --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/offline/OfflinePipelineRepositoryConnectorFactory.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.eclipse.aether.internal.impl.offline; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.impl.OfflineController; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.spi.connector.PipelineRepositoryConnectorFactory; +import org.eclipse.aether.spi.connector.RepositoryConnector; + +import static java.util.Objects.requireNonNull; + +/** + * Offline connector factory. + * + * @since TBD + */ +@Singleton +@Named(OfflinePipelineRepositoryConnectorFactory.NAME) +public final class OfflinePipelineRepositoryConnectorFactory implements PipelineRepositoryConnectorFactory { + public static final String NAME = "offline"; + + private final OfflineController offlineController; + + /** + * This connector should be usually the left-most in pipeline. + */ + private float priority = 0; + + @Inject + public OfflinePipelineRepositoryConnectorFactory(OfflineController offlineController) { + this.offlineController = requireNonNull(offlineController); + } + + @Override + public RepositoryConnector newInstance( + RepositorySystemSession session, RemoteRepository repository, RepositoryConnector delegate) { + return new OfflineRepositoryConnector(session, repository, offlineController, delegate); + } + + @Override + public float getPriority() { + return priority; + } + + public OfflinePipelineRepositoryConnectorFactory setPriority(float priority) { + this.priority = priority; + return this; + } +} diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/offline/OfflineRepositoryConnector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/offline/OfflineRepositoryConnector.java new file mode 100644 index 00000000..6c280306 --- /dev/null +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/offline/OfflineRepositoryConnector.java @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.eclipse.aether.internal.impl.offline; + +import java.util.Collection; + +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.impl.OfflineController; +import org.eclipse.aether.internal.impl.Utils; +import org.eclipse.aether.repository.RemoteRepository; +import org.eclipse.aether.spi.connector.ArtifactDownload; +import org.eclipse.aether.spi.connector.ArtifactUpload; +import org.eclipse.aether.spi.connector.MetadataDownload; +import org.eclipse.aether.spi.connector.MetadataUpload; +import org.eclipse.aether.spi.connector.RepositoryConnector; +import org.eclipse.aether.transfer.ArtifactTransferException; +import org.eclipse.aether.transfer.MetadataTransferException; +import org.eclipse.aether.transfer.RepositoryOfflineException; + +import static java.util.Objects.requireNonNull; + +/** + * Offline connector, that prevents ANY remote access in case session is offline. + * + * @since TBD + */ +public final class OfflineRepositoryConnector implements RepositoryConnector { + private final RepositorySystemSession session; + private final RemoteRepository remoteRepository; + private final OfflineController offlineController; + private final RepositoryConnector delegate; + + public OfflineRepositoryConnector( + RepositorySystemSession session, + RemoteRepository remoteRepository, + OfflineController offlineController, + RepositoryConnector delegate) { + this.session = requireNonNull(session); + this.remoteRepository = requireNonNull(remoteRepository); + this.offlineController = requireNonNull(offlineController); + this.delegate = requireNonNull(delegate); + } + + @Override + public void close() { + delegate.close(); + } + + @Override + public void get( + Collection<? extends ArtifactDownload> artifactDownloads, + Collection<? extends MetadataDownload> metadataDownloads) { + try { + Utils.checkOffline(session, offlineController, remoteRepository); + } catch (RepositoryOfflineException e) { + if (artifactDownloads != null && !artifactDownloads.isEmpty()) { + artifactDownloads.forEach( + d -> d.setException(new ArtifactTransferException(d.getArtifact(), remoteRepository, e))); + } + if (metadataDownloads != null && !metadataDownloads.isEmpty()) { + metadataDownloads.forEach( + d -> d.setException(new MetadataTransferException(d.getMetadata(), remoteRepository, e))); + } + return; + } + delegate.get(artifactDownloads, metadataDownloads); + } + + @Override + public void put( + Collection<? extends ArtifactUpload> artifactUploads, + Collection<? extends MetadataUpload> metadataUploads) { + try { + Utils.checkOffline(session, offlineController, remoteRepository); + } catch (RepositoryOfflineException e) { + if (artifactUploads != null && !artifactUploads.isEmpty()) { + artifactUploads.forEach( + d -> d.setException(new ArtifactTransferException(d.getArtifact(), remoteRepository, e))); + } + if (metadataUploads != null && !metadataUploads.isEmpty()) { + metadataUploads.forEach( + d -> d.setException(new MetadataTransferException(d.getMetadata(), remoteRepository, e))); + } + return; + } + delegate.put(artifactUploads, metadataUploads); + } + + @Override + public String toString() { + return OfflinePipelineRepositoryConnectorFactory.NAME + "( " + delegate.toString() + " )"; + } +} diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/PipelineRepositoryConnectorFactory.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/PipelineRepositoryConnectorFactory.java new file mode 100644 index 00000000..3fcd71b4 --- /dev/null +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/connector/PipelineRepositoryConnectorFactory.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.eclipse.aether.spi.connector; + +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.repository.RemoteRepository; + +/** + * A pipeline factory to create piped repository connectors. + * + * @since TBD + */ +public interface PipelineRepositoryConnectorFactory { + + /** + * Create a piped repository connector for the specified remote repository. Typically, a factory will inspect + * {@link RemoteRepository#getProtocol()} and {@link RemoteRepository#getContentType()} to determine whether it can + * handle a repository. This method never throws or returns {@code null}, least can do is to return the passed in + * delegate connector instance. + * + * @param session The repository system session from which to configure the connector, must not be {@code null}. In + * particular, a connector must notify any {@link RepositorySystemSession#getTransferListener()} set for + * the session and should obey the timeouts configured for the session. + * @param repository The remote repository to create a connector for, must not be {@code null}. + * @param delegate The delegate connector, never {@code null}. The delegate is "right hand" connector in connector + * pipeline. + * @return The connector for the given repository, never {@code null}. If pipeline wants to step aside, it must + * return the passed in delegate connector instance. + */ + RepositoryConnector newInstance( + RepositorySystemSession session, RemoteRepository repository, RepositoryConnector delegate); + + /** + * The priority of this pipeline factory. Higher priority makes connector closer to right end (tail) of pipeline + * (closest to delegate), while lower priority makes it closer to left hand (head) of the pipeline. + */ + float getPriority(); +} diff --git a/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java index 851d3f8a..4b9442e4 100644 --- a/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java +++ b/maven-resolver-supplier-mvn3/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java @@ -99,8 +99,10 @@ import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate; import org.eclipse.aether.internal.impl.collect.bf.BfDependencyCollector; import org.eclipse.aether.internal.impl.collect.df.DfDependencyCollector; import org.eclipse.aether.internal.impl.filter.DefaultRemoteRepositoryFilterManager; +import org.eclipse.aether.internal.impl.filter.FilteringPipelineRepositoryConnectorFactory; import org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource; import org.eclipse.aether.internal.impl.filter.PrefixesRemoteRepositoryFilterSource; +import org.eclipse.aether.internal.impl.offline.OfflinePipelineRepositoryConnectorFactory; import org.eclipse.aether.internal.impl.resolution.TrustedChecksumsArtifactResolverPostProcessor; import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory; import org.eclipse.aether.internal.impl.synccontext.named.NameMapper; @@ -121,6 +123,7 @@ import org.eclipse.aether.spi.artifact.generator.ArtifactGeneratorFactory; import org.eclipse.aether.spi.artifact.transformer.ArtifactTransformer; import org.eclipse.aether.spi.checksums.ProvidedChecksumsSource; import org.eclipse.aether.spi.checksums.TrustedChecksumsSource; +import org.eclipse.aether.spi.connector.PipelineRepositoryConnectorFactory; import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory; import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector; @@ -703,6 +706,27 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> { return result; } + private Map<String, PipelineRepositoryConnectorFactory> pipelineRepositoryConnectorFactories; + + public final Map<String, PipelineRepositoryConnectorFactory> getPipelineRepositoryConnectorFactories() { + checkClosed(); + if (pipelineRepositoryConnectorFactories == null) { + pipelineRepositoryConnectorFactories = createPipelineRepositoryConnectorFactories(); + } + return pipelineRepositoryConnectorFactories; + } + + protected Map<String, PipelineRepositoryConnectorFactory> createPipelineRepositoryConnectorFactories() { + HashMap<String, PipelineRepositoryConnectorFactory> result = new HashMap<>(); + result.put( + FilteringPipelineRepositoryConnectorFactory.NAME, + new FilteringPipelineRepositoryConnectorFactory(getRemoteRepositoryFilterManager())); + result.put( + OfflinePipelineRepositoryConnectorFactory.NAME, + new OfflinePipelineRepositoryConnectorFactory(getOfflineController())); + return result; + } + private RepositoryConnectorProvider repositoryConnectorProvider; public final RepositoryConnectorProvider getRepositoryConnectorProvider() { @@ -715,7 +739,7 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> { protected RepositoryConnectorProvider createRepositoryConnectorProvider() { return new DefaultRepositoryConnectorProvider( - getRepositoryConnectorFactories(), getRemoteRepositoryFilterManager()); + getRepositoryConnectorFactories(), getPipelineRepositoryConnectorFactories()); } private Installer installer; diff --git a/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java index 220ca806..ce194ebe 100644 --- a/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java +++ b/maven-resolver-supplier-mvn4/src/main/java/org/eclipse/aether/supplier/RepositorySystemSupplier.java @@ -103,8 +103,10 @@ import org.eclipse.aether.internal.impl.collect.DependencyCollectorDelegate; import org.eclipse.aether.internal.impl.collect.bf.BfDependencyCollector; import org.eclipse.aether.internal.impl.collect.df.DfDependencyCollector; import org.eclipse.aether.internal.impl.filter.DefaultRemoteRepositoryFilterManager; +import org.eclipse.aether.internal.impl.filter.FilteringPipelineRepositoryConnectorFactory; import org.eclipse.aether.internal.impl.filter.GroupIdRemoteRepositoryFilterSource; import org.eclipse.aether.internal.impl.filter.PrefixesRemoteRepositoryFilterSource; +import org.eclipse.aether.internal.impl.offline.OfflinePipelineRepositoryConnectorFactory; import org.eclipse.aether.internal.impl.resolution.TrustedChecksumsArtifactResolverPostProcessor; import org.eclipse.aether.internal.impl.synccontext.DefaultSyncContextFactory; import org.eclipse.aether.internal.impl.synccontext.named.NameMapper; @@ -125,6 +127,7 @@ import org.eclipse.aether.spi.artifact.generator.ArtifactGeneratorFactory; import org.eclipse.aether.spi.artifact.transformer.ArtifactTransformer; import org.eclipse.aether.spi.checksums.ProvidedChecksumsSource; import org.eclipse.aether.spi.checksums.TrustedChecksumsSource; +import org.eclipse.aether.spi.connector.PipelineRepositoryConnectorFactory; import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactory; import org.eclipse.aether.spi.connector.checksum.ChecksumAlgorithmFactorySelector; @@ -707,6 +710,27 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> { return result; } + private Map<String, PipelineRepositoryConnectorFactory> pipelineRepositoryConnectorFactories; + + public final Map<String, PipelineRepositoryConnectorFactory> getPipelineRepositoryConnectorFactories() { + checkClosed(); + if (pipelineRepositoryConnectorFactories == null) { + pipelineRepositoryConnectorFactories = createPipelineRepositoryConnectorFactories(); + } + return pipelineRepositoryConnectorFactories; + } + + protected Map<String, PipelineRepositoryConnectorFactory> createPipelineRepositoryConnectorFactories() { + HashMap<String, PipelineRepositoryConnectorFactory> result = new HashMap<>(); + result.put( + FilteringPipelineRepositoryConnectorFactory.NAME, + new FilteringPipelineRepositoryConnectorFactory(getRemoteRepositoryFilterManager())); + result.put( + OfflinePipelineRepositoryConnectorFactory.NAME, + new OfflinePipelineRepositoryConnectorFactory(getOfflineController())); + return result; + } + private RepositoryConnectorProvider repositoryConnectorProvider; public final RepositoryConnectorProvider getRepositoryConnectorProvider() { @@ -719,7 +743,7 @@ public class RepositorySystemSupplier implements Supplier<RepositorySystem> { protected RepositoryConnectorProvider createRepositoryConnectorProvider() { return new DefaultRepositoryConnectorProvider( - getRepositoryConnectorFactories(), getRemoteRepositoryFilterManager()); + getRepositoryConnectorFactories(), getPipelineRepositoryConnectorFactories()); } private Installer installer; diff --git a/src/site/markdown/configuration.md b/src/site/markdown/configuration.md index be696288..e015543b 100644 --- a/src/site/markdown/configuration.md +++ b/src/site/markdown/configuration.md @@ -82,8 +82,9 @@ under the License. | `"aether.named.ipc.nativeName"` | `String` | The name if the IPC server native executable (without file extension like ".exe") | `"ipc-sync"` | 2.0.1 | No | Java System Properties | | `"aether.named.ipc.nofork"` | `Boolean` | Should the IPC server not fork? (i.e. for testing purposes) | `false` | 2.0.1 | No | Java System Properties | | `"aether.named.ipc.nonative"` | `Boolean` | Should the IPC server not use native executable? | `true` | 2.0.1 | No | Java System Properties | -| `"aether.offline.hosts"` | `String` | Comma-separated list of hosts which are supposed to be resolved offline. | - | | No | Session Configuration | -| `"aether.offline.protocols"` | `String` | Comma-separated list of protocols which are supposed to be resolved offline. | - | | No | Session Configuration | +| `"aether.offline.hosts"` | `String` | Comma-separated list of hosts which are supposed to be resolved when session is offline. | - | | No | Session Configuration | +| `"aether.offline.protocols"` | `String` | Comma-separated list of protocols which are supposed to be accessed when session is offline. | - | | No | Session Configuration | +| `"aether.offline.repositories"` | `String` | Comma-separated list of repository IDs which are supposed to be resolved when session is offline. | - | TBD | No | Session Configuration | | `"aether.priority.<class>"` | `Float` | The priority to use for a certain extension class. <code><class></code> can either be the fully qualified name or the simple name of a class. If the class name ends with Factory that suffix could optionally be left out. This configuration is used by <code>org.eclipse.aether.internal.impl.PrioritizedComponents</code> internal utility to sort classes by priority. This is reusable utility (so an extension can make use of it), but by default in [...] | `"aether.priority.cached"` | `Boolean` | A flag indicating whether the created ordered components should be cached in session. | `true` | 2.0.0 | No | Session Configuration | | `"aether.priority.implicit"` | `Boolean` | A flag indicating whether the priorities of pluggable extensions are implicitly given by their iteration order such that the first extension has the highest priority. If set, an extension's built-in priority as well as any corresponding <code>aether.priority.*</code> configuration properties are ignored when searching for a suitable implementation among the available extensions. This priority mode is meant for cases where the application will [...]