Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.gradle.api.internalconfigurations.DefaultConfiguration Maven / Gradle / Ivy
/*
* 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.configurations;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import groovy.lang.Closure;
import org.gradle.api.Action;
import org.gradle.api.Describable;
import org.gradle.api.DomainObjectSet;
import org.gradle.api.InvalidUserCodeException;
import org.gradle.api.InvalidUserDataException;
import org.gradle.api.artifacts.ArtifactCollection;
import org.gradle.api.artifacts.ArtifactView;
import org.gradle.api.artifacts.ConfigurablePublishArtifact;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.ConfigurationPublications;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.DependencyConstraint;
import org.gradle.api.artifacts.DependencyConstraintSet;
import org.gradle.api.artifacts.DependencyResolutionListener;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.ExcludeRule;
import org.gradle.api.artifacts.ModuleVersionIdentifier;
import org.gradle.api.artifacts.PublishArtifact;
import org.gradle.api.artifacts.PublishArtifactSet;
import org.gradle.api.artifacts.ResolutionStrategy;
import org.gradle.api.artifacts.ResolvableDependencies;
import org.gradle.api.artifacts.ResolveException;
import org.gradle.api.artifacts.ResolvedConfiguration;
import org.gradle.api.artifacts.component.ComponentIdentifier;
import org.gradle.api.artifacts.component.ModuleComponentIdentifier;
import org.gradle.api.artifacts.result.DependencyResult;
import org.gradle.api.artifacts.result.ResolutionResult;
import org.gradle.api.artifacts.result.ResolvedArtifactResult;
import org.gradle.api.artifacts.result.ResolvedComponentResult;
import org.gradle.api.attributes.Attribute;
import org.gradle.api.attributes.AttributeContainer;
import org.gradle.api.capabilities.Capability;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.CompositeDomainObjectSet;
import org.gradle.api.internal.DefaultDomainObjectSet;
import org.gradle.api.internal.DocumentationRegistry;
import org.gradle.api.internal.DomainObjectContext;
import org.gradle.api.internal.artifacts.ConfigurationResolver;
import org.gradle.api.internal.artifacts.DefaultDependencyConstraintSet;
import org.gradle.api.internal.artifacts.DefaultDependencySet;
import org.gradle.api.internal.artifacts.DefaultExcludeRule;
import org.gradle.api.internal.artifacts.DefaultPublishArtifactSet;
import org.gradle.api.internal.artifacts.DefaultResolverResults;
import org.gradle.api.internal.artifacts.ExcludeRuleNotationConverter;
import org.gradle.api.internal.artifacts.Module;
import org.gradle.api.internal.artifacts.ResolverResults;
import org.gradle.api.internal.artifacts.dependencies.DefaultDependencyConstraint;
import org.gradle.api.internal.artifacts.ivyservice.DefaultLenientConfiguration;
import org.gradle.api.internal.artifacts.ivyservice.ResolvedArtifactCollectingVisitor;
import org.gradle.api.internal.artifacts.ivyservice.ResolvedFileCollectionVisitor;
import org.gradle.api.internal.artifacts.ivyservice.moduleconverter.RootComponentMetadataBuilder;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactVisitor;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.SelectedArtifactSet;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.VisitedArtifactSet;
import org.gradle.api.internal.artifacts.ivyservice.resolveengine.projectresult.ResolvedProjectConfiguration;
import org.gradle.api.internal.artifacts.transform.DefaultExtraExecutionGraphDependenciesResolverFactory;
import org.gradle.api.internal.artifacts.transform.ExtraExecutionGraphDependenciesResolverFactory;
import org.gradle.api.internal.attributes.AttributeContainerInternal;
import org.gradle.api.internal.attributes.ImmutableAttributeContainerWithErrorMessage;
import org.gradle.api.internal.attributes.ImmutableAttributes;
import org.gradle.api.internal.attributes.ImmutableAttributesFactory;
import org.gradle.api.internal.collections.DomainObjectCollectionFactory;
import org.gradle.api.internal.file.AbstractFileCollection;
import org.gradle.api.internal.file.FileCollectionFactory;
import org.gradle.api.internal.file.FileCollectionStructureVisitor;
import org.gradle.api.internal.project.ProjectInternal;
import org.gradle.api.internal.project.ProjectStateRegistry;
import org.gradle.api.internal.tasks.FailureCollectingTaskDependencyResolveContext;
import org.gradle.api.internal.tasks.TaskDependencyResolveContext;
import org.gradle.api.specs.Spec;
import org.gradle.api.specs.Specs;
import org.gradle.api.tasks.TaskDependency;
import org.gradle.configuration.internal.UserCodeApplicationContext;
import org.gradle.initialization.ProjectAccessListener;
import org.gradle.internal.Actions;
import org.gradle.internal.Cast;
import org.gradle.internal.Describables;
import org.gradle.internal.DisplayName;
import org.gradle.internal.Factories;
import org.gradle.internal.Factory;
import org.gradle.internal.ImmutableActionSet;
import org.gradle.internal.UncheckedException;
import org.gradle.internal.component.model.ComponentResolveMetadata;
import org.gradle.internal.concurrent.GradleThread;
import org.gradle.internal.deprecation.DeprecatableConfiguration;
import org.gradle.internal.deprecation.DeprecationLogger;
import org.gradle.internal.event.ListenerBroadcast;
import org.gradle.internal.event.ListenerManager;
import org.gradle.internal.lazy.Lazy;
import org.gradle.internal.logging.text.TreeFormatter;
import org.gradle.internal.model.CalculatedModelValue;
import org.gradle.internal.model.CalculatedValueContainer;
import org.gradle.internal.model.CalculatedValueContainerFactory;
import org.gradle.internal.operations.BuildOperationContext;
import org.gradle.internal.operations.BuildOperationDescriptor;
import org.gradle.internal.operations.BuildOperationExecutor;
import org.gradle.internal.operations.CallableBuildOperation;
import org.gradle.internal.reflect.Instantiator;
import org.gradle.internal.typeconversion.NotationParser;
import org.gradle.util.CollectionUtils;
import org.gradle.util.ConfigureUtil;
import org.gradle.util.Path;
import org.gradle.util.WrapUtil;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static org.gradle.api.internal.artifacts.configurations.ConfigurationInternal.InternalState.ARTIFACTS_RESOLVED;
import static org.gradle.api.internal.artifacts.configurations.ConfigurationInternal.InternalState.BUILD_DEPENDENCIES_RESOLVED;
import static org.gradle.api.internal.artifacts.configurations.ConfigurationInternal.InternalState.GRAPH_RESOLVED;
import static org.gradle.api.internal.artifacts.configurations.ConfigurationInternal.InternalState.UNRESOLVED;
import static org.gradle.util.ConfigureUtil.configure;
@SuppressWarnings("rawtypes")
public class DefaultConfiguration extends AbstractFileCollection implements ConfigurationInternal, MutationValidator {
private static final Action DEFAULT_ERROR_HANDLER = throwable -> {
throw UncheckedException.throwAsUncheckedException(throwable);
};
private final ConfigurationResolver resolver;
private final ListenerManager listenerManager;
private final DependencyMetaDataProvider metaDataProvider;
private final DefaultDependencySet dependencies;
private final DefaultDependencyConstraintSet dependencyConstraints;
private final DefaultDomainObjectSet ownDependencies;
private final DefaultDomainObjectSet ownDependencyConstraints;
private final DomainObjectContext owner;
private final CalculatedValueContainerFactory calculatedValueContainerFactory;
private final ProjectStateRegistry projectStateRegistry;
private CompositeDomainObjectSet inheritedDependencies;
private CompositeDomainObjectSet inheritedDependencyConstraints;
private DefaultDependencySet allDependencies;
private DefaultDependencyConstraintSet allDependencyConstraints;
private ImmutableActionSet defaultDependencyActions = ImmutableActionSet.empty();
private ImmutableActionSet withDependencyActions = ImmutableActionSet.empty();
private final DefaultPublishArtifactSet artifacts;
private final DefaultDomainObjectSet ownArtifacts;
private CompositeDomainObjectSet inheritedArtifacts;
private DefaultPublishArtifactSet allArtifacts;
private final ConfigurationResolvableDependencies resolvableDependencies;
private ListenerBroadcast dependencyResolutionListeners;
private final BuildOperationExecutor buildOperationExecutor;
private final Instantiator instantiator;
private final NotationParser artifactNotationParser;
private final NotationParser capabilityNotationParser;
private final ProjectAccessListener projectAccessListener;
private Factory resolutionStrategyFactory;
private ResolutionStrategyInternal resolutionStrategy;
private final FileCollectionFactory fileCollectionFactory;
private final DocumentationRegistry documentationRegistry;
private final Set childMutationValidators = Sets.newHashSet();
private final MutationValidator parentMutationValidator = DefaultConfiguration.this::validateParentMutation;
private final RootComponentMetadataBuilder rootComponentMetadataBuilder;
private final ConfigurationsProvider configurationsProvider;
private final Path identityPath;
private final Path path;
// These fields are not covered by mutation lock
private final String name;
private final DefaultConfigurationPublications outgoing;
private boolean visible = true;
private boolean transitive = true;
private Set extendsFrom = new LinkedHashSet<>();
private String description;
private final Set excludeRules = new LinkedHashSet<>();
private Set parsedExcludeRules;
private final Object observationLock = new Object();
private volatile InternalState observedState = UNRESOLVED;
private boolean insideBeforeResolve;
private boolean dependenciesModified;
private boolean canBeConsumed = true;
private boolean canBeResolved = true;
private boolean canBeMutated = true;
private AttributeContainerInternal configurationAttributes;
private final DomainObjectContext domainObjectContext;
private final ImmutableAttributesFactory attributesFactory;
private final ConfigurationFileCollection intrinsicFiles;
private final DisplayName displayName;
private final UserCodeApplicationContext userCodeApplicationContext;
private final DomainObjectCollectionFactory domainObjectCollectionFactory;
private final Lazy> consistentResolutionConstraints = Lazy.unsafe().of(this::consistentResolutionConstraints);
private final AtomicInteger copyCount = new AtomicInteger(0);
private Action beforeLocking;
private List declarationAlternatives;
private List consumptionAlternatives;
private List resolutionAlternatives;
private final CalculatedModelValue currentResolveState;
private ConfigurationInternal consistentResolutionSource;
private String consistentResolutionReason;
public DefaultConfiguration(DomainObjectContext domainObjectContext,
String name,
ConfigurationsProvider configurationsProvider,
ConfigurationResolver resolver,
ListenerManager listenerManager,
DependencyMetaDataProvider metaDataProvider,
Factory resolutionStrategyFactory,
ProjectAccessListener projectAccessListener,
FileCollectionFactory fileCollectionFactory,
BuildOperationExecutor buildOperationExecutor,
Instantiator instantiator,
NotationParser artifactNotationParser,
NotationParser capabilityNotationParser,
ImmutableAttributesFactory attributesFactory,
RootComponentMetadataBuilder rootComponentMetadataBuilder,
DocumentationRegistry documentationRegistry,
UserCodeApplicationContext userCodeApplicationContext,
DomainObjectContext owner,
ProjectStateRegistry projectStateRegistry,
DomainObjectCollectionFactory domainObjectCollectionFactory,
CalculatedValueContainerFactory calculatedValueContainerFactory
) {
this.userCodeApplicationContext = userCodeApplicationContext;
this.projectStateRegistry = projectStateRegistry;
this.domainObjectCollectionFactory = domainObjectCollectionFactory;
this.calculatedValueContainerFactory = calculatedValueContainerFactory;
this.identityPath = domainObjectContext.identityPath(name);
this.name = name;
this.configurationsProvider = configurationsProvider;
this.resolver = resolver;
this.listenerManager = listenerManager;
this.metaDataProvider = metaDataProvider;
this.resolutionStrategyFactory = resolutionStrategyFactory;
this.projectAccessListener = projectAccessListener;
this.fileCollectionFactory = fileCollectionFactory;
this.dependencyResolutionListeners = listenerManager.createAnonymousBroadcaster(DependencyResolutionListener.class);
this.buildOperationExecutor = buildOperationExecutor;
this.instantiator = instantiator;
this.artifactNotationParser = artifactNotationParser;
this.capabilityNotationParser = capabilityNotationParser;
this.attributesFactory = attributesFactory;
this.configurationAttributes = attributesFactory.mutable();
this.domainObjectContext = domainObjectContext;
this.intrinsicFiles = fileCollectionFromSpec(Specs.satisfyAll());
this.documentationRegistry = documentationRegistry;
this.resolvableDependencies = instantiator.newInstance(ConfigurationResolvableDependencies.class, this);
displayName = Describables.memoize(new ConfigurationDescription(identityPath));
this.ownDependencies = (DefaultDomainObjectSet) domainObjectCollectionFactory.newDomainObjectSet(Dependency.class);
this.ownDependencies.beforeCollectionChanges(validateMutationType(this, MutationType.DEPENDENCIES));
this.ownDependencyConstraints = (DefaultDomainObjectSet) domainObjectCollectionFactory.newDomainObjectSet(DependencyConstraint.class);
this.ownDependencyConstraints.beforeCollectionChanges(validateMutationType(this, MutationType.DEPENDENCIES));
this.dependencies = new DefaultDependencySet(Describables.of(displayName, "dependencies"), this, ownDependencies);
this.dependencyConstraints = new DefaultDependencyConstraintSet(Describables.of(displayName, "dependency constraints"), this, ownDependencyConstraints);
this.ownArtifacts = (DefaultDomainObjectSet) domainObjectCollectionFactory.newDomainObjectSet(PublishArtifact.class);
this.ownArtifacts.beforeCollectionChanges(validateMutationType(this, MutationType.ARTIFACTS));
this.artifacts = new DefaultPublishArtifactSet(Describables.of(displayName, "artifacts"), ownArtifacts, fileCollectionFactory);
this.outgoing = instantiator.newInstance(DefaultConfigurationPublications.class, displayName, artifacts, new AllArtifactsProvider(), configurationAttributes, instantiator, artifactNotationParser, capabilityNotationParser, fileCollectionFactory, attributesFactory, domainObjectCollectionFactory);
this.rootComponentMetadataBuilder = rootComponentMetadataBuilder;
this.owner = owner;
this.currentResolveState = owner.getModel().newCalculatedValue(ResolveState.NOT_RESOLVED);
path = domainObjectContext.projectPath(name);
}
private static Action validateMutationType(final MutationValidator mutationValidator, final MutationType type) {
return arg -> mutationValidator.validateMutation(type);
}
@Override
public String getName() {
return name;
}
@Override
public State getState() {
ResolveState currentState = currentResolveState.get();
InternalState resolvedState = currentState.state;
if (resolvedState == ARTIFACTS_RESOLVED || resolvedState == GRAPH_RESOLVED) {
if (currentState.hasError()) {
return State.RESOLVED_WITH_FAILURES;
} else {
return State.RESOLVED;
}
} else {
return State.UNRESOLVED;
}
}
@VisibleForTesting
public InternalState getResolvedState() {
return currentResolveState.get().state;
}
@Override
public Module getModule() {
return metaDataProvider.getModule();
}
@Override
public boolean isVisible() {
return visible;
}
@Override
public Configuration setVisible(boolean visible) {
validateMutation(MutationType.DEPENDENCIES);
this.visible = visible;
return this;
}
@Override
public Set getExtendsFrom() {
return Collections.unmodifiableSet(extendsFrom);
}
@Override
public Configuration setExtendsFrom(Iterable extendsFrom) {
validateMutation(MutationType.DEPENDENCIES);
for (Configuration configuration : this.extendsFrom) {
if (inheritedArtifacts != null) {
inheritedArtifacts.removeCollection(configuration.getAllArtifacts());
}
if (inheritedDependencies != null) {
inheritedDependencies.removeCollection(configuration.getAllDependencies());
}
if (inheritedDependencyConstraints != null) {
inheritedDependencyConstraints.removeCollection(configuration.getAllDependencyConstraints());
}
((ConfigurationInternal) configuration).removeMutationValidator(parentMutationValidator);
}
this.extendsFrom = new LinkedHashSet<>();
for (Configuration configuration : extendsFrom) {
extendsFrom(configuration);
}
return this;
}
@Override
public Configuration extendsFrom(Configuration... extendsFrom) {
validateMutation(MutationType.DEPENDENCIES);
for (Configuration configuration : extendsFrom) {
if (configuration.getHierarchy().contains(this)) {
throw new InvalidUserDataException(String.format(
"Cyclic extendsFrom from %s and %s is not allowed. See existing hierarchy: %s", this,
configuration, configuration.getHierarchy()));
}
if (this.extendsFrom.add(configuration)) {
if (inheritedArtifacts != null) {
inheritedArtifacts.addCollection(configuration.getAllArtifacts());
}
if (inheritedDependencies != null) {
inheritedDependencies.addCollection(configuration.getAllDependencies());
}
if (inheritedDependencyConstraints != null) {
inheritedDependencyConstraints.addCollection(configuration.getAllDependencyConstraints());
}
((ConfigurationInternal) configuration).addMutationValidator(parentMutationValidator);
}
}
return this;
}
@Override
public boolean isTransitive() {
return transitive;
}
@Override
public Configuration setTransitive(boolean transitive) {
validateMutation(MutationType.DEPENDENCIES);
this.transitive = transitive;
return this;
}
@Override
@Nullable
public String getDescription() {
return description;
}
@Override
public Configuration setDescription(@Nullable String description) {
this.description = description;
return this;
}
@Override
public Set getHierarchy() {
if (extendsFrom.isEmpty()) {
return Collections.singleton(this);
}
Set result = WrapUtil.toLinkedSet(this);
collectSuperConfigs(this, result);
return result;
}
private void collectSuperConfigs(Configuration configuration, Set result) {
for (Configuration superConfig : configuration.getExtendsFrom()) {
// The result is an ordered set - so seeing the same value a second time pushes further down
result.remove(superConfig);
result.add(superConfig);
collectSuperConfigs(superConfig, result);
}
}
@Override
public Configuration defaultDependencies(final Action action) {
validateMutation(MutationType.DEPENDENCIES);
defaultDependencyActions = defaultDependencyActions.add(dependencies -> {
if (dependencies.isEmpty()) {
action.execute(dependencies);
}
});
return this;
}
@Override
public Configuration withDependencies(final Action action) {
validateMutation(MutationType.DEPENDENCIES);
withDependencyActions = withDependencyActions.add(action);
return this;
}
@Override
public void runDependencyActions() {
defaultDependencyActions.execute(dependencies);
withDependencyActions.execute(dependencies);
// Discard actions after execution
defaultDependencyActions = ImmutableActionSet.empty();
withDependencyActions = ImmutableActionSet.empty();
for (Configuration superConfig : extendsFrom) {
((ConfigurationInternal) superConfig).runDependencyActions();
}
}
@Override
public Set getAll() {
return ImmutableSet.copyOf(configurationsProvider.getAll());
}
@Override
public Set resolve() {
return getFiles();
}
@Override
public Iterator iterator() {
return intrinsicFiles.iterator();
}
@Override
protected void visitContents(FileCollectionStructureVisitor visitor) {
intrinsicFiles.visitContents(visitor);
}
@Override
protected void appendContents(TreeFormatter formatter) {
formatter.node("configuration: " + getIdentityPath());
}
@Override
public boolean contains(File file) {
return intrinsicFiles.contains(file);
}
@Override
public boolean isEmpty() {
return intrinsicFiles.isEmpty();
}
@Override
public Set files(Dependency... dependencies) {
return fileCollection(dependencies).getFiles();
}
@Override
public Set files(Closure dependencySpecClosure) {
return fileCollection(dependencySpecClosure).getFiles();
}
@Override
public Set files(Spec dependencySpec) {
return fileCollection(dependencySpec).getFiles();
}
@Override
public FileCollection fileCollection(Spec dependencySpec) {
assertIsResolvable();
return fileCollectionFromSpec(dependencySpec);
}
private ConfigurationFileCollection fileCollectionFromSpec(Spec dependencySpec) {
return new ConfigurationFileCollection(new SelectedArtifactsProvider(), dependencySpec, configurationAttributes, Specs.satisfyAll(), false, false, new DefaultResolutionHost());
}
@Override
public FileCollection fileCollection(Closure dependencySpecClosure) {
return fileCollection(Specs.convertClosureToSpec(dependencySpecClosure));
}
@Override
public FileCollection fileCollection(Dependency... dependencies) {
Set deps = WrapUtil.toLinkedSet(dependencies);
return fileCollection(deps::contains);
}
@Override
public void markAsObserved(InternalState requestedState) {
markThisObserved(requestedState);
markParentsObserved(requestedState);
}
private void markThisObserved(InternalState requestedState) {
synchronized (observationLock) {
if (observedState.compareTo(requestedState) < 0) {
observedState = requestedState;
}
}
}
private void markParentsObserved(InternalState requestedState) {
for (Configuration configuration : extendsFrom) {
((ConfigurationInternal) configuration).markAsObserved(requestedState);
}
}
@Override
public ResolvedConfiguration getResolvedConfiguration() {
return resolveToStateOrLater(ARTIFACTS_RESOLVED).getResolvedConfiguration();
}
private ResolveState resolveToStateOrLater(final InternalState requestedState) {
assertIsResolvable();
warnIfConfigurationIsDeprecatedForResolving();
ResolveState currentState = currentResolveState.get();
if (currentState.state.compareTo(requestedState) >= 0) {
return currentState;
}
if (!owner.getModel().hasMutableState()) {
if (!GradleThread.isManaged()) {
// Error if we are executing in a user-managed thread.
throw new IllegalStateException("The configuration " + identityPath.toString() + " was resolved from a thread not managed by Gradle.");
} else {
// We don't currently have mutable access to the project, so report a deprecation warning and then continue by attempting to acquire mutable access
DeprecationLogger.deprecateBehaviour("The configuration " + identityPath.toString() + " was resolved without accessing the project in a safe manner. This may happen when a configuration is resolved from a different project.")
.willBeRemovedInGradle7()
.withUserManual("viewing_debugging_dependencies", "sub:resolving-unsafe-configuration-resolution-errors")
.nagUser();
return owner.getModel().fromMutableState(p -> resolveExclusively(requestedState));
}
}
return resolveExclusively(requestedState);
}
private void warnIfConfigurationIsDeprecatedForResolving() {
if (resolutionAlternatives != null) {
DeprecationLogger.deprecateConfiguration(this.name).forResolution().replaceWith(resolutionAlternatives)
.willBecomeAnErrorInGradle7()
.withUpgradeGuideSection(5, "dependencies_should_no_longer_be_declared_using_the_compile_and_runtime_configurations")
.nagUser();
}
}
private ResolveState resolveExclusively(InternalState requestedState) {
return currentResolveState.update(initial -> {
ResolveState current = initial;
if (requestedState == GRAPH_RESOLVED || requestedState == ARTIFACTS_RESOLVED) {
current = resolveGraphIfRequired(requestedState, current);
}
if (requestedState == ARTIFACTS_RESOLVED) {
current = resolveArtifactsIfRequired(current);
}
return current;
});
}
/**
* Must be called from {@link #resolveExclusively(InternalState)} only.
*/
private ResolveState resolveGraphIfRequired(final InternalState requestedState, ResolveState currentState) {
if (currentState.state == ARTIFACTS_RESOLVED || currentState.state == GRAPH_RESOLVED) {
if (dependenciesModified) {
throw new InvalidUserDataException(String.format("Attempted to resolve %s that has been resolved previously.", getDisplayName()));
}
return currentState;
}
return buildOperationExecutor.call(new CallableBuildOperation() {
@Override
public ResolveState call(BuildOperationContext context) {
runDependencyActions();
preventFromFurtherMutation();
ResolvableDependenciesInternal incoming = (ResolvableDependenciesInternal) getIncoming();
performPreResolveActions(incoming);
DefaultResolverResults results = new DefaultResolverResults();
resolver.resolveGraph(DefaultConfiguration.this, results);
dependenciesModified = false;
ResolveState newState = new GraphResolved(results);
// Make the new state visible in case a dependency resolution listener queries the result, which requires the new state
currentResolveState.set(newState);
// Mark all affected configurations as observed
markParentsObserved(requestedState);
markReferencedProjectConfigurationsObserved(requestedState, results);
if (!newState.hasError()) {
dependencyResolutionListeners.getSource().afterResolve(incoming);
// Discard listeners
dependencyResolutionListeners.removeAll();
// Use the current state, which may have changed if the listener queried the result
newState = currentResolveState.get();
}
captureBuildOperationResult(context, results);
return newState;
}
private void captureBuildOperationResult(BuildOperationContext context, ResolverResults results) {
Throwable failure = results.getFailure();
if (failure != null) {
context.failed(failure);
}
// When dependency resolution has failed, we don't want the build operation listeners to fail as well
// because:
// 1. the `failed` method will have been called with the user facing error
// 2. such an error may still lead to a valid dependency graph
ResolutionResult resolutionResult = results.getResolutionResult();
context.setResult(ResolveConfigurationResolutionBuildOperationResult.create(resolutionResult, attributesFactory));
}
@Override
public BuildOperationDescriptor.Builder description() {
String displayName = "Resolve dependencies of " + identityPath;
Path projectPath = domainObjectContext.getProjectPath();
String projectPathString = domainObjectContext.isScript() ? null : (projectPath == null ? null : projectPath.getPath());
return BuildOperationDescriptor.displayName(displayName)
.progressDisplayName(displayName)
.details(new ResolveConfigurationResolutionBuildOperationDetails(
getName(),
domainObjectContext.isScript(),
getDescription(),
domainObjectContext.getBuildPath().getPath(),
projectPathString,
isVisible(),
isTransitive(),
resolver.getRepositories()
));
}
});
}
@Override
public ConfigurationInternal getConsistentResolutionSource() {
return consistentResolutionSource;
}
private List consistentResolutionConstraints() {
if (consistentResolutionSource == null) {
return Collections.emptyList();
}
assertThatConsistentResolutionIsPropertyConfigured();
return consistentResolutionSource.getIncoming()
.getResolutionResult()
.getAllComponents()
.stream()
.map(this::registerConsistentResolutionConstraint)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
}
private void assertThatConsistentResolutionIsPropertyConfigured() {
if (!consistentResolutionSource.isCanBeResolved()) {
throw new InvalidUserCodeException("You can't use " + consistentResolutionSource + " as a consistent resolution source for " + this + " because it isn't a resolvable configuration.");
}
assertNoDependencyResolutionConsistencyCycle();
}
@Override
public Supplier> getConsistentResolutionConstraints() {
return consistentResolutionConstraints;
}
@Override
public ResolveException maybeAddContext(ResolveException e) {
if (ignoresSettingsRepositories()) {
return new ResolveExceptionWithHints(getDisplayName(), e.getCauses(),
"The project declares repositories, effectively ignoring the repositories you have declared in the settings.",
"You can figure out how project repositories are declared by configuring your build to fail on project repositories.",
"See " + documentationRegistry.getDocumentationFor("declaring_repositories", "sub:fail_build_on_project_repositories") + " for details.");
}
return e;
}
private boolean ignoresSettingsRepositories() {
if (owner instanceof ProjectInternal) {
ProjectInternal project = (ProjectInternal) this.owner;
return !project.getRepositories().isEmpty() &&
!project.getGradle().getSettings().getDependencyResolutionManagement().getRepositories().isEmpty();
}
return false;
}
private void assertNoDependencyResolutionConsistencyCycle() {
Set sources = Sets.newLinkedHashSet();
ConfigurationInternal src = this;
while (src != null) {
if (!sources.add(src)) {
String cycle = sources.stream().map(Configuration::getName).collect(Collectors.joining(" -> ")) + " -> " + getName();
throw new InvalidUserDataException("Cycle detected in consistent resolution sources: " + cycle);
}
src = src.getConsistentResolutionSource();
}
}
private Optional registerConsistentResolutionConstraint(ResolvedComponentResult result) {
if (result.getId() instanceof ModuleComponentIdentifier) {
ModuleVersionIdentifier moduleVersion = result.getModuleVersion();
DefaultDependencyConstraint constraint = DefaultDependencyConstraint.strictly(
moduleVersion.getGroup(),
moduleVersion.getName(),
moduleVersion.getVersion());
constraint.because(consistentResolutionReason);
return Optional.of(constraint);
}
return Optional.empty();
}
private void performPreResolveActions(ResolvableDependencies incoming) {
DependencyResolutionListener dependencyResolutionListener = dependencyResolutionListeners.getSource();
insideBeforeResolve = true;
try {
dependencyResolutionListener.beforeResolve(incoming);
} finally {
insideBeforeResolve = false;
}
}
private void markReferencedProjectConfigurationsObserved(InternalState requestedState, ResolverResults results) {
for (ResolvedProjectConfiguration projectResult : results.getResolvedLocalComponents().getResolvedProjectConfigurations()) {
ProjectInternal project = projectStateRegistry.stateFor(projectResult.getId()).getMutableModel();
ConfigurationInternal targetConfig = (ConfigurationInternal) project.getConfigurations().getByName(projectResult.getTargetConfiguration());
targetConfig.markAsObserved(requestedState);
}
}
/**
* Must be called from {@link #resolveExclusively(InternalState)} only.
*/
private ResolveState resolveArtifactsIfRequired(ResolveState currentState) {
if (currentState.state == ARTIFACTS_RESOLVED) {
return currentState;
}
if (currentState.state != GRAPH_RESOLVED) {
throw new IllegalStateException("Cannot resolve artifacts before graph has been resolved.");
}
ResolverResults results = currentState.getCachedResolverResults();
resolver.resolveArtifacts(DefaultConfiguration.this, results);
return new ArtifactsResolved(results);
}
@Override
public ExtraExecutionGraphDependenciesResolverFactory getDependenciesResolver() {
return new DefaultExtraExecutionGraphDependenciesResolverFactory(new DefaultResolutionResultProvider(), owner, calculatedValueContainerFactory,
(attributes, filter) -> new ConfigurationFileCollection(new SelectedArtifactsProvider(), Specs.satisfyAll(), attributes, filter, false, false, new DefaultResolutionHost()));
}
private ResolverResults getResultsForBuildDependencies() {
ResolveState currentState = currentResolveState.get();
if (currentState.state == UNRESOLVED) {
throw new IllegalStateException("Cannot query results until resolution has happened.");
}
return currentState.getCachedResolverResults();
}
private ResolverResults resolveGraphForBuildDependenciesIfRequired() {
if (getResolutionStrategy().resolveGraphToDetermineTaskDependencies()) {
// Force graph resolution as this is required to calculate build dependencies
return resolveToStateOrLater(GRAPH_RESOLVED).getCachedResolverResults();
}
ResolveState currentState = currentResolveState.update(initial -> {
if (initial.state == UNRESOLVED) {
// Traverse graph
ResolverResults results = new DefaultResolverResults();
resolver.resolveBuildDependencies(DefaultConfiguration.this, results);
return new BuildDependenciesResolved(results);
} // Otherwise, already have a result, so reuse it
return initial;
});
// Otherwise, already have a result, so reuse it
return currentState.getCachedResolverResults();
}
private ResolverResults getResultsForArtifacts() {
ResolveState currentState = currentResolveState.get();
if (currentState.state != ARTIFACTS_RESOLVED) {
// Do not validate that the current thread holds the project lock
// Should instead assert that the results are available and fail if not
currentState = resolveExclusively(ARTIFACTS_RESOLVED);
}
return currentState.getCachedResolverResults();
}
@Override
public void visitDependencies(TaskDependencyResolveContext context) {
assertIsResolvable();
context.add(intrinsicFiles);
}
/**
* {@inheritDoc}
*/
@Override
public TaskDependency getTaskDependencyFromProjectDependency(final boolean useDependedOn, final String taskName) {
if (useDependedOn) {
return new TasksFromProjectDependencies(taskName, getAllDependencies(), projectAccessListener);
} else {
return new TasksFromDependentProjects(taskName, getName());
}
}
@Override
public DependencySet getDependencies() {
return dependencies;
}
@Override
public DependencySet getAllDependencies() {
if (allDependencies == null) {
initAllDependencies();
}
return allDependencies;
}
@SuppressWarnings("unchecked")
private synchronized void initAllDependencies() {
if (allDependencies != null) {
return;
}
inheritedDependencies = domainObjectCollectionFactory.newDomainObjectSet(Dependency.class, ownDependencies);
for (Configuration configuration : this.extendsFrom) {
inheritedDependencies.addCollection(configuration.getAllDependencies());
}
allDependencies = new DefaultDependencySet(Describables.of(displayName, "all dependencies"), this, inheritedDependencies);
}
@Override
public DependencyConstraintSet getDependencyConstraints() {
return dependencyConstraints;
}
@Override
public DependencyConstraintSet getAllDependencyConstraints() {
if (allDependencyConstraints == null) {
initAllDependencyConstraints();
}
return allDependencyConstraints;
}
@SuppressWarnings("unchecked")
private synchronized void initAllDependencyConstraints() {
if (allDependencyConstraints != null) {
return;
}
inheritedDependencyConstraints = domainObjectCollectionFactory.newDomainObjectSet(DependencyConstraint.class, ownDependencyConstraints);
for (Configuration configuration : this.extendsFrom) {
inheritedDependencyConstraints.addCollection(configuration.getAllDependencyConstraints());
}
allDependencyConstraints = new DefaultDependencyConstraintSet(Describables.of(displayName, "all dependency constraints"), this, inheritedDependencyConstraints);
}
@Override
public PublishArtifactSet getArtifacts() {
return artifacts;
}
@Override
public PublishArtifactSet getAllArtifacts() {
initAllArtifacts();
return allArtifacts;
}
@SuppressWarnings("unchecked")
private synchronized void initAllArtifacts() {
if (allArtifacts != null) {
return;
}
DisplayName displayName = Describables.of(this.displayName, "all artifacts");
if (!canBeMutated && extendsFrom.isEmpty()) {
// No further mutation is allowed and there's no parent: the artifact set corresponds to this configuration own artifacts
this.allArtifacts = new DefaultPublishArtifactSet(displayName, ownArtifacts, fileCollectionFactory);
return;
}
if (canBeMutated) {
// If the configuration can still be mutated, we need to create a composite
inheritedArtifacts = domainObjectCollectionFactory.newDomainObjectSet(PublishArtifact.class, ownArtifacts);
}
for (Configuration configuration : this.extendsFrom) {
PublishArtifactSet allArtifacts = configuration.getAllArtifacts();
if (inheritedArtifacts != null || !allArtifacts.isEmpty()) {
if (inheritedArtifacts == null) {
// This configuration cannot be mutated, but some parent configurations provide artifacts
inheritedArtifacts = domainObjectCollectionFactory.newDomainObjectSet(PublishArtifact.class, ownArtifacts);
}
inheritedArtifacts.addCollection(allArtifacts);
}
}
if (inheritedArtifacts != null) {
this.allArtifacts = new DefaultPublishArtifactSet(displayName, inheritedArtifacts, fileCollectionFactory);
} else {
this.allArtifacts = new DefaultPublishArtifactSet(displayName, ownArtifacts, fileCollectionFactory);
}
}
@Override
public Set getExcludeRules() {
initExcludeRules();
return Collections.unmodifiableSet(parsedExcludeRules);
}
@Override
public Set getAllExcludeRules() {
Set result = Sets.newLinkedHashSet();
result.addAll(getExcludeRules());
for (Configuration config : extendsFrom) {
result.addAll(((ConfigurationInternal) config).getAllExcludeRules());
}
return result;
}
/**
* Synchronize read access to excludes. Mutation does not need to be thread-safe.
*/
private synchronized void initExcludeRules() {
if (parsedExcludeRules == null) {
NotationParser parser = ExcludeRuleNotationConverter.parser();
parsedExcludeRules = Sets.newLinkedHashSet();
for (Object excludeRule : excludeRules) {
parsedExcludeRules.add(parser.parseNotation(excludeRule));
}
}
}
public void setExcludeRules(Set excludeRules) {
validateMutation(MutationType.DEPENDENCIES);
parsedExcludeRules = null;
this.excludeRules.clear();
this.excludeRules.addAll(excludeRules);
}
@Override
public DefaultConfiguration exclude(Map excludeRuleArgs) {
validateMutation(MutationType.DEPENDENCIES);
parsedExcludeRules = null;
excludeRules.add(excludeRuleArgs);
return this;
}
@Override
public String getUploadTaskName() {
return Configurations.uploadTaskName(getName());
}
@Override
public String getDisplayName() {
return displayName.getDisplayName();
}
@Override
public ResolvableDependencies getIncoming() {
return resolvableDependencies;
}
@Override
public ConfigurationPublications getOutgoing() {
return outgoing;
}
@Override
public OutgoingVariant convertToOutgoingVariant() {
return outgoing.convertToOutgoingVariant();
}
@Override
public void collectVariants(VariantVisitor visitor) {
outgoing.collectVariants(visitor);
}
@Override
public void beforeLocking(Action action) {
if (canBeMutated) {
if (beforeLocking != null) {
beforeLocking = Actions.composite(beforeLocking, action);
} else {
beforeLocking = action;
}
}
}
@Override
public void preventFromFurtherMutation() {
// TODO This should use the same `MutationValidator` infrastructure that we use for other mutation types
if (canBeMutated) {
if (beforeLocking != null) {
beforeLocking.execute(this);
beforeLocking = null;
}
AttributeContainerInternal delegatee = configurationAttributes.asImmutable();
configurationAttributes = new ImmutableAttributeContainerWithErrorMessage(delegatee, this.displayName);
outgoing.preventFromFurtherMutation();
canBeMutated = false;
}
}
@Override
public void outgoing(Action action) {
action.execute(outgoing);
}
@Override
public ConfigurationInternal copy() {
return createCopy(getDependencies(), getDependencyConstraints());
}
@Override
public Configuration copyRecursive() {
return createCopy(getAllDependencies(), getAllDependencyConstraints());
}
@Override
public Configuration copy(Spec dependencySpec) {
return createCopy(CollectionUtils.filter(getDependencies(), dependencySpec), getDependencyConstraints());
}
@Override
public Configuration copyRecursive(Spec dependencySpec) {
return createCopy(CollectionUtils.filter(getAllDependencies(), dependencySpec), getAllDependencyConstraints());
}
private DefaultConfiguration createCopy(Set dependencies, Set dependencyConstraints) {
DefaultConfiguration copiedConfiguration = newConfiguration();
// state, cachedResolvedConfiguration, and extendsFrom intentionally not copied - must re-resolve copy
// copying extendsFrom could mess up dependencies when copy was re-resolved
copiedConfiguration.visible = visible;
copiedConfiguration.transitive = transitive;
copiedConfiguration.description = description;
copiedConfiguration.defaultDependencyActions = defaultDependencyActions;
copiedConfiguration.withDependencyActions = withDependencyActions;
copiedConfiguration.dependencyResolutionListeners = dependencyResolutionListeners.copy();
copiedConfiguration.canBeConsumed = canBeConsumed;
copiedConfiguration.canBeResolved = canBeResolved;
copiedConfiguration.getArtifacts().addAll(getAllArtifacts());
if (!configurationAttributes.isEmpty()) {
for (Attribute attribute : configurationAttributes.keySet()) {
Object value = configurationAttributes.getAttribute(attribute);
copiedConfiguration.getAttributes().attribute(Cast.uncheckedNonnullCast(attribute), value);
}
}
// todo An ExcludeRule is a value object but we don't enforce immutability for DefaultExcludeRule as strong as we
// should (we expose the Map). We should provide a better API for ExcludeRule (I don't want to use unmodifiable Map).
// As soon as DefaultExcludeRule is truly immutable, we don't need to create a new instance of DefaultExcludeRule.
for (ExcludeRule excludeRule : getAllExcludeRules()) {
copiedConfiguration.excludeRules.add(new DefaultExcludeRule(excludeRule.getGroup(), excludeRule.getModule()));
}
DomainObjectSet copiedDependencies = copiedConfiguration.getDependencies();
for (Dependency dependency : dependencies) {
copiedDependencies.add(dependency.copy());
}
DomainObjectSet copiedDependencyConstraints = copiedConfiguration.getDependencyConstraints();
for (DependencyConstraint dependencyConstraint : dependencyConstraints) {
copiedDependencyConstraints.add(((DefaultDependencyConstraint) dependencyConstraint).copy());
}
return copiedConfiguration;
}
private DefaultConfiguration newConfiguration() {
DetachedConfigurationsProvider configurationsProvider = new DetachedConfigurationsProvider();
RootComponentMetadataBuilder rootComponentMetadataBuilder = this.rootComponentMetadataBuilder.withConfigurationsProvider(configurationsProvider);
String newName = getNameWithCopySuffix();
Factory childResolutionStrategy = resolutionStrategy != null ? Factories.constant(resolutionStrategy.copy()) : resolutionStrategyFactory;
DefaultConfiguration copiedConfiguration = instantiator.newInstance(DefaultConfiguration.class, domainObjectContext, newName, configurationsProvider, resolver, listenerManager,
metaDataProvider, childResolutionStrategy, projectAccessListener, fileCollectionFactory, buildOperationExecutor, instantiator, artifactNotationParser, capabilityNotationParser,
attributesFactory, rootComponentMetadataBuilder, documentationRegistry, userCodeApplicationContext, owner, projectStateRegistry, domainObjectCollectionFactory,
calculatedValueContainerFactory);
configurationsProvider.setTheOnlyConfiguration(copiedConfiguration);
return copiedConfiguration;
}
private String getNameWithCopySuffix() {
int count = copyCount.incrementAndGet();
String copyName = name + "Copy";
return count == 1
? copyName
: copyName + count;
}
@Override
public Configuration copy(Closure dependencySpec) {
return copy(Specs.convertClosureToSpec(dependencySpec));
}
@Override
public Configuration copyRecursive(Closure dependencySpec) {
return copyRecursive(Specs.convertClosureToSpec(dependencySpec));
}
@Override
public ResolutionStrategyInternal getResolutionStrategy() {
if (resolutionStrategy == null) {
resolutionStrategy = resolutionStrategyFactory.create();
resolutionStrategy.setMutationValidator(this);
resolutionStrategyFactory = null;
}
return resolutionStrategy;
}
@Override
public ComponentResolveMetadata toRootComponentMetaData() {
return rootComponentMetadataBuilder.toRootComponentMetaData();
}
@Override
public String getPath() {
return path.getPath();
}
@Override
public Path getIdentityPath() {
return identityPath;
}
@Override
public Configuration resolutionStrategy(Closure closure) {
configure(closure, getResolutionStrategy());
return this;
}
@Override
public Configuration resolutionStrategy(Action action) {
action.execute(getResolutionStrategy());
return this;
}
@Override
public void addMutationValidator(MutationValidator validator) {
childMutationValidators.add(validator);
}
@Override
public void removeMutationValidator(MutationValidator validator) {
childMutationValidators.remove(validator);
}
private void validateParentMutation(MutationType type) {
// Strategy changes in a parent configuration do not affect this configuration, or any of its children, in any way
if (type == MutationType.STRATEGY) {
return;
}
preventIllegalParentMutation(type);
markAsModified(type);
notifyChildren(type);
}
@Override
public void validateMutation(MutationType type) {
preventIllegalMutation(type);
markAsModified(type);
notifyChildren(type);
}
private void preventIllegalParentMutation(MutationType type) {
// TODO Deprecate and eventually prevent these mutations in parent when already resolved
if (type == MutationType.DEPENDENCY_ATTRIBUTES) {
return;
}
InternalState resolvedState = currentResolveState.get().state;
if (resolvedState == ARTIFACTS_RESOLVED) {
throw new InvalidUserDataException(String.format("Cannot change %s of parent of %s after it has been resolved", type, getDisplayName()));
} else if (resolvedState == GRAPH_RESOLVED) {
if (type == MutationType.DEPENDENCIES) {
throw new InvalidUserDataException(String.format("Cannot change %s of parent of %s after task dependencies have been resolved", type, getDisplayName()));
}
}
}
private void preventIllegalMutation(MutationType type) {
// TODO: Deprecate and eventually prevent these mutations when already resolved
if (type == MutationType.DEPENDENCY_ATTRIBUTES) {
return;
}
InternalState resolvedState = currentResolveState.get().state;
if (resolvedState == ARTIFACTS_RESOLVED) {
// The public result for the configuration has been calculated.
// It is an error to change anything that would change the dependencies or artifacts
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after it has been resolved.", type, getDisplayName()));
} else if (resolvedState == GRAPH_RESOLVED) {
// The task dependencies for the configuration have been calculated using Configuration.getBuildDependencies().
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after task dependencies have been resolved", type, getDisplayName()));
} else if (observedState == GRAPH_RESOLVED || observedState == ARTIFACTS_RESOLVED) {
// The configuration has been used in a resolution, and it is an error for build logic to change any dependencies,
// exclude rules or parent configurations (values that will affect the resolved graph).
if (type != MutationType.STRATEGY) {
String extraMessage = insideBeforeResolve ? " Use 'defaultDependencies' instead of 'beforeResolve' to specify default dependencies for a configuration." : "";
throw new InvalidUserDataException(String.format("Cannot change %s of dependency %s after it has been included in dependency resolution.%s", type, getDisplayName(), extraMessage));
}
}
}
private void markAsModified(MutationType type) {
// TODO: Should not be ignoring DEPENDENCY_ATTRIBUTE modifications after resolve
if (type == MutationType.DEPENDENCY_ATTRIBUTES) {
return;
}
// Strategy mutations will not require a re-resolve
if (type == MutationType.STRATEGY) {
return;
}
dependenciesModified = true;
}
private void notifyChildren(MutationType type) {
// Notify child configurations
for (MutationValidator validator : childMutationValidators) {
validator.validateMutation(type);
}
}
private static class ConfigurationDescription implements Describable {
private final Path identityPath;
ConfigurationDescription(Path identityPath) {
this.identityPath = identityPath;
}
@Override
public String getDisplayName() {
return "configuration '" + identityPath + "'";
}
}
private class DefaultResolutionResultProvider implements ResolutionResultProvider {
@Override
public ResolutionResult getTaskDependencyValue() {
return getResultsForBuildDependencies().getResolutionResult();
}
@Override
public ResolutionResult getValue() {
return getResultsForArtifacts().getResolutionResult();
}
}
private class SelectedArtifactsProvider implements ResolutionResultProvider {
@Override
public VisitedArtifactSet getTaskDependencyValue() {
assertIsResolvable();
return resolveGraphForBuildDependenciesIfRequired().getVisitedArtifacts();
}
@Override
public VisitedArtifactSet getValue() {
assertIsResolvable();
ResolveState currentState = resolveToStateOrLater(ARTIFACTS_RESOLVED);
return currentState.getCachedResolverResults().getVisitedArtifacts();
}
}
private static class ConfigurationFileCollection extends AbstractFileCollection {
private final Spec dependencySpec;
private final AttributeContainerInternal viewAttributes;
private final Spec componentSpec;
private final boolean lenient;
private final boolean allowNoMatchingVariants;
private final ResolutionResultProvider resultProvider;
private final ResolutionHost resolutionHost;
private SelectedArtifactSet selectedArtifacts;
private ConfigurationFileCollection(ResolutionResultProvider resultProvider,
Spec dependencySpec,
AttributeContainerInternal viewAttributes,
Spec componentSpec,
boolean lenient,
boolean allowNoMatchingVariants,
ResolutionHost resolutionHost) {
this.resultProvider = resultProvider;
this.dependencySpec = dependencySpec;
this.viewAttributes = viewAttributes;
this.componentSpec = componentSpec;
this.lenient = lenient;
this.allowNoMatchingVariants = allowNoMatchingVariants;
this.resolutionHost = resolutionHost;
}
@Override
public void visitDependencies(TaskDependencyResolveContext context) {
SelectedArtifactSet selected = resultProvider.getTaskDependencyValue().select(dependencySpec, viewAttributes, componentSpec, allowNoMatchingVariants);
FailureCollectingTaskDependencyResolveContext collectingContext = new FailureCollectingTaskDependencyResolveContext(context);
selected.visitDependencies(collectingContext);
if (!lenient) {
resolutionHost.rethrowFailure("task dependencies", collectingContext.getFailures());
}
}
@Override
public String getDisplayName() {
return resolutionHost.displayName("files").getDisplayName();
}
@Override
protected void visitContents(FileCollectionStructureVisitor visitor) {
ResolvedFileCollectionVisitor collectingVisitor = new ResolvedFileCollectionVisitor(visitor);
getSelectedArtifacts().visitArtifacts(collectingVisitor, lenient);
if (!lenient) {
resolutionHost.rethrowFailure("files", collectingVisitor.getFailures());
}
}
@Override
protected void appendContents(TreeFormatter formatter) {
formatter.node("contains: " + getDisplayName());
}
private SelectedArtifactSet getSelectedArtifacts() {
if (selectedArtifacts == null) {
selectedArtifacts = resultProvider.getValue().select(dependencySpec, viewAttributes, componentSpec, allowNoMatchingVariants);
}
return selectedArtifacts;
}
}
private void rethrowFailure(String type, Collection failures) {
if (failures.isEmpty()) {
return;
}
if (failures.size() == 1) {
Throwable failure = failures.iterator().next();
if (failure instanceof ResolveException) {
throw UncheckedException.throwAsUncheckedException(failure);
}
}
throw new DefaultLenientConfiguration.ArtifactResolveException(type, getIdentityPath().toString(), getDisplayName(), failures);
}
private void assertIsResolvable() {
if (!canBeResolved) {
throw new IllegalStateException("Resolving dependency configuration '" + name + "' is not allowed as it is defined as 'canBeResolved=false'.\nInstead, a resolvable ('canBeResolved=true') dependency configuration that extends '" + name + "' should be resolved.");
}
}
@Override
public AttributeContainerInternal getAttributes() {
return configurationAttributes;
}
@Override
public Configuration attributes(Action action) {
action.execute(configurationAttributes);
return this;
}
@Override
public boolean isCanBeConsumed() {
return canBeConsumed;
}
@Override
public void setCanBeConsumed(boolean allowed) {
validateMutation(MutationType.ROLE);
canBeConsumed = allowed;
}
@Override
public boolean isCanBeResolved() {
return canBeResolved;
}
@Override
public void setCanBeResolved(boolean allowed) {
validateMutation(MutationType.ROLE);
canBeResolved = allowed;
}
@VisibleForTesting
ListenerBroadcast getDependencyResolutionListeners() {
return dependencyResolutionListeners;
}
@Override
@Nullable
public List getDeclarationAlternatives() {
return declarationAlternatives;
}
@Nullable
@Override
public List getConsumptionAlternatives() {
return consumptionAlternatives;
}
@Nullable
@Override
public List getResolutionAlternatives() {
return resolutionAlternatives;
}
@Override
public boolean isFullyDeprecated() {
return declarationAlternatives != null &&
(!canBeConsumed || consumptionAlternatives != null) &&
(!canBeResolved || resolutionAlternatives != null);
}
@Override
public DeprecatableConfiguration deprecateForDeclaration(String... alternativesForDeclaring) {
this.declarationAlternatives = ImmutableList.copyOf(alternativesForDeclaring);
return this;
}
@Override
public DeprecatableConfiguration deprecateForConsumption(String... alternativesForConsumption) {
this.consumptionAlternatives = ImmutableList.copyOf(alternativesForConsumption);
return this;
}
@Override
public DeprecatableConfiguration deprecateForResolution(String... alternativesForResolving) {
this.resolutionAlternatives = ImmutableList.copyOf(alternativesForResolving);
return this;
}
@Override
public Configuration shouldResolveConsistentlyWith(Configuration versionsSource) {
this.consistentResolutionSource = (ConfigurationInternal) versionsSource;
this.consistentResolutionReason = "version resolved in " + versionsSource + " by consistent resolution";
return this;
}
@Override
public Configuration disableConsistentResolution() {
this.consistentResolutionSource = null;
this.consistentResolutionReason = null;
return this;
}
/**
* Print a formatted representation of a Configuration
*/
public String dump() {
StringBuilder reply = new StringBuilder();
reply.append("\nConfiguration:");
reply.append(" class='").append(this.getClass()).append("'");
reply.append(" name='").append(this.getName()).append("'");
reply.append(" hashcode='").append(this.hashCode()).append("'");
reply.append("\nLocal Dependencies:");
if (getDependencies().size() > 0) {
for (Dependency d : getDependencies()) {
reply.append("\n ").append(d);
}
} else {
reply.append("\n none");
}
reply.append("\nLocal Artifacts:");
if (getArtifacts().size() > 0) {
for (PublishArtifact a : getArtifacts()) {
reply.append("\n ").append(a);
}
} else {
reply.append("\n none");
}
reply.append("\nAll Dependencies:");
if (getAllDependencies().size() > 0) {
for (Dependency d : getAllDependencies()) {
reply.append("\n ").append(d);
}
} else {
reply.append("\n none");
}
reply.append("\nAll Artifacts:");
if (getAllArtifacts().size() > 0) {
for (PublishArtifact a : getAllArtifacts()) {
reply.append("\n ").append(a);
}
} else {
reply.append("\n none");
}
return reply.toString();
}
private abstract static class ResolveState {
static final ResolveState NOT_RESOLVED = new ResolveState(UNRESOLVED) {
@Override
public ResolvedConfiguration getResolvedConfiguration() {
throw new IllegalStateException();
}
@Override
public ResolverResults getCachedResolverResults() {
throw new IllegalStateException();
}
@Override
public boolean hasError() {
return false;
}
};
final InternalState state;
ResolveState(InternalState state) {
this.state = state;
}
abstract boolean hasError();
public abstract ResolvedConfiguration getResolvedConfiguration();
public abstract ResolverResults getCachedResolverResults();
}
private static class WithResults extends ResolveState {
final ResolverResults cachedResolverResults;
WithResults(InternalState state, ResolverResults cachedResolverResults) {
super(state);
this.cachedResolverResults = cachedResolverResults;
}
@Override
boolean hasError() {
return cachedResolverResults.hasError();
}
@Override
public ResolverResults getCachedResolverResults() {
return cachedResolverResults;
}
@Override
public ResolvedConfiguration getResolvedConfiguration() {
return cachedResolverResults.getResolvedConfiguration();
}
}
private static class BuildDependenciesResolved extends WithResults {
public BuildDependenciesResolved(ResolverResults results) {
super(BUILD_DEPENDENCIES_RESOLVED, results);
}
}
private static class GraphResolved extends WithResults {
public GraphResolved(ResolverResults cachedResolverResults) {
super(GRAPH_RESOLVED, cachedResolverResults);
}
}
private static class ArtifactsResolved extends WithResults {
public ArtifactsResolved(ResolverResults results) {
super(ARTIFACTS_RESOLVED, results);
}
}
private ConfigurationArtifactCollection artifactCollection(AttributeContainerInternal attributes, Spec componentFilter, boolean lenient, boolean allowNoMatchingVariants) {
ImmutableAttributes viewAttributes = attributes.asImmutable();
DefaultResolutionHost failureHandler = new DefaultResolutionHost();
ConfigurationFileCollection files = new ConfigurationFileCollection(new SelectedArtifactsProvider(), Specs.satisfyAll(), viewAttributes, componentFilter, lenient, allowNoMatchingVariants, failureHandler);
return new ConfigurationArtifactCollection(files, lenient, failureHandler, calculatedValueContainerFactory);
}
public class ConfigurationResolvableDependencies implements ResolvableDependenciesInternal {
@Override
public String getName() {
return name;
}
@Override
public String getPath() {
return path.getPath();
}
@Override
public String toString() {
return "dependencies '" + getIdentityPath() + "'";
}
@Override
public FileCollection getFiles() {
return intrinsicFiles;
}
@Override
public DependencySet getDependencies() {
runDependencyActions();
return getAllDependencies();
}
@Override
public DependencyConstraintSet getDependencyConstraints() {
runDependencyActions();
return getAllDependencyConstraints();
}
@Override
public void beforeResolve(Action action) {
dependencyResolutionListeners.add("beforeResolve", userCodeApplicationContext.reapplyCurrentLater(action));
}
@Override
public void beforeResolve(Closure action) {
beforeResolve(ConfigureUtil.configureUsing(action));
}
@Override
public void afterResolve(Action action) {
dependencyResolutionListeners.add("afterResolve", userCodeApplicationContext.reapplyCurrentLater(action));
}
@Override
public void afterResolve(Closure action) {
afterResolve(ConfigureUtil.configureUsing(action));
}
@Override
public ResolutionResult getResolutionResult() {
return new LenientResolutionResult(DEFAULT_ERROR_HANDLER);
}
@Override
public ArtifactCollection getArtifacts() {
return artifactCollection(configurationAttributes, Specs.satisfyAll(), false, false);
}
@Override
public ArtifactView artifactView(Action configAction) {
ArtifactViewConfiguration config = createArtifactViewConfiguration();
configAction.execute(config);
return createArtifactView(config);
}
private ArtifactView createArtifactView(ArtifactViewConfiguration config) {
ImmutableAttributes viewAttributes = config.lockViewAttributes();
// This is a little coincidental: if view attributes have not been accessed, don't allow no matching variants
boolean allowNoMatchingVariants = config.attributesUsed;
return new ConfigurationArtifactView(viewAttributes, config.lockComponentFilter(), config.lenient, allowNoMatchingVariants);
}
private DefaultConfiguration.ArtifactViewConfiguration createArtifactViewConfiguration() {
return instantiator.newInstance(ArtifactViewConfiguration.class, attributesFactory, configurationAttributes);
}
@Override
public AttributeContainer getAttributes() {
return configurationAttributes;
}
@Override
public ResolutionResult getResolutionResult(Action errorHandler) {
return new LenientResolutionResult(errorHandler);
}
private class ConfigurationArtifactView implements ArtifactView {
private final ImmutableAttributes viewAttributes;
private final Spec componentFilter;
private final boolean lenient;
private final boolean allowNoMatchingVariants;
ConfigurationArtifactView(ImmutableAttributes viewAttributes, Spec componentFilter, boolean lenient, boolean allowNoMatchingVariants) {
this.viewAttributes = viewAttributes;
this.componentFilter = componentFilter;
this.lenient = lenient;
this.allowNoMatchingVariants = allowNoMatchingVariants;
}
@Override
public AttributeContainer getAttributes() {
return viewAttributes;
}
@Override
public ArtifactCollection getArtifacts() {
return artifactCollection(viewAttributes, componentFilter, lenient, allowNoMatchingVariants);
}
@Override
public FileCollection getFiles() {
return new ConfigurationFileCollection(new SelectedArtifactsProvider(), Specs.satisfyAll(), viewAttributes, componentFilter, lenient, allowNoMatchingVariants, new DefaultResolutionHost());
}
}
private class LenientResolutionResult implements ResolutionResult {
private final Action errorHandler;
private volatile ResolutionResult delegate;
private LenientResolutionResult(Action errorHandler) {
this.errorHandler = errorHandler;
}
private void resolve() {
if (delegate == null) {
synchronized (this) {
if (delegate == null) {
ResolveState currentState = resolveToStateOrLater(ARTIFACTS_RESOLVED);
delegate = currentState.getCachedResolverResults().getResolutionResult();
Throwable failure = currentState.getCachedResolverResults().consumeNonFatalFailure();
if (failure != null) {
errorHandler.execute(failure);
}
}
}
}
}
@Override
public ResolvedComponentResult getRoot() {
resolve();
return delegate.getRoot();
}
@Override
public Set getAllDependencies() {
resolve();
return delegate.getAllDependencies();
}
@Override
public void allDependencies(Action action) {
resolve();
delegate.allDependencies(action);
}
@Override
public void allDependencies(Closure closure) {
resolve();
delegate.allDependencies(closure);
}
@Override
public Set getAllComponents() {
resolve();
return delegate.getAllComponents();
}
@Override
public void allComponents(Action action) {
resolve();
delegate.allComponents(action);
}
@Override
public void allComponents(Closure closure) {
resolve();
delegate.allComponents(closure);
}
@Override
public AttributeContainer getRequestedAttributes() {
return delegate.getRequestedAttributes();
}
@Override
public int hashCode() {
resolve();
return delegate.hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof LenientResolutionResult) {
resolve();
return delegate.equals(((LenientResolutionResult) obj).delegate);
}
return false;
}
@Override
public String toString() {
return "lenient resolution result for " + delegate;
}
}
}
public static class ArtifactViewConfiguration implements ArtifactView.ViewConfiguration {
private final ImmutableAttributesFactory attributesFactory;
private final AttributeContainerInternal configurationAttributes;
private AttributeContainerInternal viewAttributes;
private Spec componentFilter;
private boolean lenient;
private boolean attributesUsed;
public ArtifactViewConfiguration(ImmutableAttributesFactory attributesFactory, AttributeContainerInternal configurationAttributes) {
this.attributesFactory = attributesFactory;
this.configurationAttributes = configurationAttributes;
}
@Override
public AttributeContainer getAttributes() {
if (viewAttributes == null) {
viewAttributes = attributesFactory.mutable(configurationAttributes);
attributesUsed = true;
}
return viewAttributes;
}
@Override
public ArtifactViewConfiguration attributes(Action action) {
action.execute(getAttributes());
return this;
}
@Override
public ArtifactViewConfiguration componentFilter(Spec componentFilter) {
assertComponentFilterUnset();
this.componentFilter = componentFilter;
return this;
}
@Override
public boolean isLenient() {
return lenient;
}
@Override
public void setLenient(boolean lenient) {
this.lenient = lenient;
}
@Override
public ArtifactViewConfiguration lenient(boolean lenient) {
this.lenient = lenient;
return this;
}
private void assertComponentFilterUnset() {
if (componentFilter != null) {
throw new IllegalStateException("The component filter can only be set once before the view was computed");
}
}
private Spec lockComponentFilter() {
if (componentFilter == null) {
componentFilter = Specs.satisfyAll();
}
return componentFilter;
}
private ImmutableAttributes lockViewAttributes() {
if (viewAttributes == null) {
viewAttributes = configurationAttributes.asImmutable();
} else {
viewAttributes = viewAttributes.asImmutable();
}
return viewAttributes.asImmutable();
}
}
private static class ArtifactSetResult {
private final Set artifactResults;
private final Set failures;
ArtifactSetResult(Set artifactResults, Set failures) {
this.artifactResults = artifactResults;
this.failures = failures;
}
}
private static class ConfigurationArtifactCollection implements ArtifactCollectionInternal {
private final ConfigurationFileCollection fileCollection;
private final boolean lenient;
private final CalculatedValueContainer result;
ConfigurationArtifactCollection(ConfigurationFileCollection files, boolean lenient, ResolutionHost resolutionHost, CalculatedValueContainerFactory calculatedValueContainerFactory) {
this.fileCollection = files;
this.lenient = lenient;
this.result = calculatedValueContainerFactory.create(resolutionHost.displayName("files"), (Supplier) () -> {
ResolvedArtifactCollectingVisitor visitor = new ResolvedArtifactCollectingVisitor();
fileCollection.getSelectedArtifacts().visitArtifacts(visitor, lenient);
Set artifactResults = visitor.getArtifacts();
Set failures = visitor.getFailures();
if (!lenient) {
resolutionHost.rethrowFailure("artifacts", failures);
}
return new ArtifactSetResult(artifactResults, failures);
});
}
@Override
public FileCollection getArtifactFiles() {
return fileCollection;
}
@Override
public Set getArtifacts() {
ensureResolved();
return result.get().artifactResults;
}
@Override
public Iterator iterator() {
ensureResolved();
return result.get().artifactResults.iterator();
}
@Override
public Collection getFailures() {
ensureResolved();
return result.get().failures;
}
@Override
public void visitArtifacts(ArtifactVisitor visitor) {
// TODO - if already resolved, use the results
fileCollection.getSelectedArtifacts().visitArtifacts(visitor, lenient);
}
private void ensureResolved() {
result.finalizeIfNotAlready();
}
}
private class AllArtifactsProvider implements PublishArtifactSetProvider {
@Override
public PublishArtifactSet getPublishArtifactSet() {
return getAllArtifacts();
}
}
private class DefaultResolutionHost implements ResolutionHost {
@Override
public DisplayName displayName(String type) {
return Describables.of(DefaultConfiguration.this, type);
}
@Override
public void rethrowFailure(String type, Collection failures) {
DefaultConfiguration.this.rethrowFailure(type, failures);
}
}
}