org.gradle.api.internalrepositories.transport.RepositoryTransportFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-api Show documentation
Show all versions of gradle-api Show documentation
Gradle 6.5 API redistribution.
/*
* Copyright 2011 the original author or authors.
*
* Licensed 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.gradle.api.internal.artifacts.repositories.transport;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.credentials.Credentials;
import org.gradle.api.internal.artifacts.ivyservice.ArtifactCacheLockingManager;
import org.gradle.api.internal.artifacts.ivyservice.ivyresolve.StartParameterResolutionOverride;
import org.gradle.api.internal.artifacts.ivyservice.resolutionstrategy.DefaultExternalResourceCachePolicy;
import org.gradle.api.internal.artifacts.ivyservice.resolutionstrategy.ExternalResourceCachePolicy;
import org.gradle.api.internal.file.TemporaryFileProvider;
import org.gradle.authentication.Authentication;
import org.gradle.cache.internal.ProducerGuard;
import org.gradle.internal.authentication.AuthenticationInternal;
import org.gradle.internal.hash.ChecksumService;
import org.gradle.internal.logging.progress.ProgressLoggerFactory;
import org.gradle.internal.operations.BuildOperationExecutor;
import org.gradle.internal.resource.ExternalResourceName;
import org.gradle.internal.resource.cached.CachedExternalResourceIndex;
import org.gradle.internal.resource.connector.ResourceConnectorFactory;
import org.gradle.internal.resource.connector.ResourceConnectorSpecification;
import org.gradle.internal.resource.local.FileResourceRepository;
import org.gradle.internal.resource.transfer.ExternalResourceConnector;
import org.gradle.internal.resource.transport.ResourceConnectorRepositoryTransport;
import org.gradle.internal.resource.transport.file.FileTransport;
import org.gradle.internal.verifier.HttpRedirectVerifier;
import org.gradle.util.BuildCommencedTimeProvider;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
public class RepositoryTransportFactory {
private final List registeredProtocols = Lists.newArrayList();
private final TemporaryFileProvider temporaryFileProvider;
private final CachedExternalResourceIndex cachedExternalResourceIndex;
private final ProgressLoggerFactory progressLoggerFactory;
private final BuildCommencedTimeProvider timeProvider;
private final ArtifactCacheLockingManager artifactCacheLockingManager;
private final BuildOperationExecutor buildOperationExecutor;
private final StartParameterResolutionOverride startParameterResolutionOverride;
private final ProducerGuard producerGuard;
private final FileResourceRepository fileRepository;
private final ChecksumService checksumService;
public RepositoryTransportFactory(Collection resourceConnectorFactory,
ProgressLoggerFactory progressLoggerFactory,
TemporaryFileProvider temporaryFileProvider,
CachedExternalResourceIndex cachedExternalResourceIndex,
BuildCommencedTimeProvider timeProvider,
ArtifactCacheLockingManager artifactCacheLockingManager,
BuildOperationExecutor buildOperationExecutor,
StartParameterResolutionOverride startParameterResolutionOverride,
ProducerGuard producerGuard,
FileResourceRepository fileRepository,
ChecksumService checksumService) {
this.progressLoggerFactory = progressLoggerFactory;
this.temporaryFileProvider = temporaryFileProvider;
this.cachedExternalResourceIndex = cachedExternalResourceIndex;
this.timeProvider = timeProvider;
this.artifactCacheLockingManager = artifactCacheLockingManager;
this.buildOperationExecutor = buildOperationExecutor;
this.startParameterResolutionOverride = startParameterResolutionOverride;
this.producerGuard = producerGuard;
this.fileRepository = fileRepository;
this.checksumService = checksumService;
for (ResourceConnectorFactory connectorFactory : resourceConnectorFactory) {
register(connectorFactory);
}
}
public void register(ResourceConnectorFactory resourceConnectorFactory) {
registeredProtocols.add(resourceConnectorFactory);
}
public Set getRegisteredProtocols() {
Set validSchemes = Sets.newLinkedHashSet();
for (ResourceConnectorFactory registeredProtocol : registeredProtocols) {
validSchemes.addAll(registeredProtocol.getSupportedProtocols());
}
return validSchemes;
}
public RepositoryTransport createFileTransport(String name) {
return new FileTransport(name, fileRepository, cachedExternalResourceIndex, temporaryFileProvider, timeProvider, artifactCacheLockingManager, producerGuard, checksumService);
}
public RepositoryTransport createTransport(String scheme, String name, Collection authentications, HttpRedirectVerifier redirectVerifier) {
return createTransport(Collections.singleton(scheme), name, authentications, redirectVerifier);
}
public RepositoryTransport createTransport(Set schemes, String name, Collection authentications, HttpRedirectVerifier redirectVerifier) {
validateSchemes(schemes);
ResourceConnectorFactory connectorFactory = findConnectorFactory(schemes);
// Ensure resource transport protocol, authentication types and credentials are all compatible
validateConnectorFactoryCredentials(schemes, connectorFactory, authentications);
// File resources are handled slightly differently at present.
// file:// repos are treated differently
// 1) we don't cache their files
// 2) we don't do progress logging for "downloading"
if (schemes.equals(Collections.singleton("file"))) {
return createFileTransport(name);
}
ResourceConnectorSpecification connectionDetails = new DefaultResourceConnectorSpecification(authentications, redirectVerifier);
ExternalResourceConnector resourceConnector = connectorFactory.createResourceConnector(connectionDetails);
resourceConnector = startParameterResolutionOverride.overrideExternalResourceConnector(resourceConnector);
ExternalResourceCachePolicy cachePolicy = new DefaultExternalResourceCachePolicy();
cachePolicy = startParameterResolutionOverride.overrideExternalResourceCachePolicy(cachePolicy);
return new ResourceConnectorRepositoryTransport(name, progressLoggerFactory, temporaryFileProvider, cachedExternalResourceIndex, timeProvider, artifactCacheLockingManager, resourceConnector, buildOperationExecutor, cachePolicy, producerGuard, fileRepository, checksumService);
}
private void validateSchemes(Set schemes) {
Set validSchemes = getRegisteredProtocols();
for (String scheme : schemes) {
if (!validSchemes.contains(scheme)) {
throw new InvalidUserDataException(String.format("Not a supported repository protocol '%s': valid protocols are %s", scheme, validSchemes));
}
}
}
private void validateConnectorFactoryCredentials(Set schemes, ResourceConnectorFactory factory, Collection authentications) {
Set> configuredAuthenticationTypes = Sets.newHashSet();
for (Authentication authentication : authentications) {
AuthenticationInternal authenticationInternal = (AuthenticationInternal) authentication;
boolean isAuthenticationSupported = false;
Credentials credentials = authenticationInternal.getCredentials();
boolean needCredentials = authenticationInternal.requiresCredentials();
for (Class authenticationType : factory.getSupportedAuthentication()) {
if (authenticationType.isAssignableFrom(authentication.getClass())) {
isAuthenticationSupported = true;
break;
}
}
if (!isAuthenticationSupported) {
throw new InvalidUserDataException(String.format("Authentication scheme %s is not supported by protocol '%s'",
authentication, schemes.iterator().next()));
}
if (credentials != null) {
if (!((AuthenticationInternal) authentication).supports(credentials)) {
throw new InvalidUserDataException(String.format("Credentials type of '%s' is not supported by authentication scheme %s",
credentials.getClass().getSimpleName(), authentication));
}
} else {
if (needCredentials) {
throw new InvalidUserDataException("You cannot configure authentication schemes for this repository type if no credentials are provided.");
}
}
if (!configuredAuthenticationTypes.add(authenticationInternal.getType())) {
throw new InvalidUserDataException(String.format("You cannot configure multiple authentication schemes of the same type. The duplicate one is %s.", authentication));
}
}
}
private ResourceConnectorFactory findConnectorFactory(Set schemes) {
for (ResourceConnectorFactory protocolRegistration : registeredProtocols) {
if (protocolRegistration.getSupportedProtocols().containsAll(schemes)) {
return protocolRegistration;
}
}
throw new InvalidUserDataException("You cannot mix different URL schemes for a single repository. Please declare separate repositories.");
}
private static class DefaultResourceConnectorSpecification implements ResourceConnectorSpecification {
private final Collection authentications;
private final HttpRedirectVerifier redirectVerifier;
private DefaultResourceConnectorSpecification(Collection authentications, HttpRedirectVerifier redirectVerifier) {
this.authentications = authentications;
this.redirectVerifier = redirectVerifier;
}
@Override
public T getCredentials(Class type) {
if (authentications == null || authentications.size() < 1) {
return null;
}
Credentials credentials = ((AuthenticationInternal)authentications.iterator().next()).getCredentials();
if(credentials == null) {
return null;
}
if (type.isAssignableFrom(credentials.getClass())) {
return type.cast(credentials);
} else {
throw new IllegalArgumentException(String.format("Credentials must be an instance of '%s'.", type.getCanonicalName()));
}
}
@Override
public Collection getAuthentications() {
return authentications;
}
@Override
public HttpRedirectVerifier getRedirectVerifier() {
return redirectVerifier;
}
}
}