Java tutorial
/* * Copyright 2018 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.internal.locking; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.gradle.api.artifacts.ModuleIdentifier; import org.gradle.api.artifacts.UnresolvedDependency; import org.gradle.api.artifacts.component.ComponentIdentifier; import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.internal.artifacts.DefaultModuleVersionSelector; import org.gradle.api.internal.artifacts.dsl.dependencies.DependencyLockingProvider; import org.gradle.api.internal.artifacts.dsl.dependencies.DependencyLockingState; import org.gradle.api.internal.artifacts.ivyservice.DefaultUnresolvedDependency; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ArtifactSet; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.artifact.ValidatingArtifactsVisitor; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.DependencyGraphNode; import org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.RootGraphNode; import org.gradle.api.internal.artifacts.repositories.resolver.MavenUniqueSnapshotComponentIdentifier; import org.gradle.internal.component.local.model.LocalFileDependencyMetadata; import org.gradle.internal.component.local.model.RootConfigurationMetadata; import org.gradle.internal.component.model.ComponentResolveMetadata; import java.util.Collections; import java.util.HashSet; import java.util.Map; import java.util.Set; public class DependencyLockingArtifactVisitor implements ValidatingArtifactsVisitor { private final DependencyLockingProvider dependencyLockingProvider; private final String configurationName; private Set<ModuleComponentIdentifier> allResolvedModules; private Set<ModuleComponentIdentifier> changingResolvedModules; private Set<ModuleComponentIdentifier> extraModules; private Map<ModuleIdentifier, ModuleComponentIdentifier> modulesToBeLocked; private DependencyLockingState dependencyLockingState; private boolean lockOutOfDate = false; public DependencyLockingArtifactVisitor(String configurationName, DependencyLockingProvider dependencyLockingProvider) { this.configurationName = configurationName; this.dependencyLockingProvider = dependencyLockingProvider; } @Override public void startArtifacts(RootGraphNode root) { RootConfigurationMetadata metadata = root.getMetadata(); dependencyLockingState = metadata.getDependencyLockingState(); if (dependencyLockingState.mustValidateLockState()) { Set<ModuleComponentIdentifier> lockedModules = dependencyLockingState.getLockedDependencies(); modulesToBeLocked = Maps.newHashMapWithExpectedSize(lockedModules.size()); for (ModuleComponentIdentifier lockedModule : lockedModules) { modulesToBeLocked.put(lockedModule.getModuleIdentifier(), lockedModule); } allResolvedModules = Sets.newHashSetWithExpectedSize(this.modulesToBeLocked.size()); extraModules = Sets.newHashSet(); } else { modulesToBeLocked = Collections.emptyMap(); allResolvedModules = Sets.newHashSet(); } } @Override public void visitNode(DependencyGraphNode node) { boolean changing = false; ComponentIdentifier identifier = node.getOwner().getComponentId(); ComponentResolveMetadata metadata = node.getOwner().getMetadata(); if (metadata != null && metadata.isChanging()) { changing = true; } if (identifier instanceof ModuleComponentIdentifier) { ModuleComponentIdentifier id = (ModuleComponentIdentifier) identifier; if (identifier instanceof MavenUniqueSnapshotComponentIdentifier) { id = ((MavenUniqueSnapshotComponentIdentifier) id).getSnapshotComponent(); } if (!id.getVersion().isEmpty()) { if (allResolvedModules.add(id)) { if (changing) { addChangingModule(id); } if (dependencyLockingState.mustValidateLockState()) { ModuleComponentIdentifier lockedId = modulesToBeLocked.remove(id.getModuleIdentifier()); if (lockedId == null) { extraModules.add(id); } } } } } } private void addChangingModule(ModuleComponentIdentifier id) { if (changingResolvedModules == null) { changingResolvedModules = new HashSet<ModuleComponentIdentifier>(); } changingResolvedModules.add(id); } @Override public void visitArtifacts(DependencyGraphNode from, DependencyGraphNode to, int artifactSetId, ArtifactSet artifacts) { // No-op } @Override public void visitArtifacts(DependencyGraphNode from, LocalFileDependencyMetadata fileDependency, int artifactSetId, ArtifactSet artifactSet) { // No-op } @Override public void finishArtifacts() { } public void complete() { if (!lockOutOfDate) { Set<ModuleComponentIdentifier> changingModules = this.changingResolvedModules == null ? Collections.<ModuleComponentIdentifier>emptySet() : this.changingResolvedModules; dependencyLockingProvider.persistResolvedDependencies(configurationName, allResolvedModules, changingModules); } } /** * This will transform any lock out of date result into an {@link UnresolvedDependency} in order to plug into lenient resolution. * This happens only if there are no previous failures as otherwise lock state can't be asserted. * * @return the existing failures augmented with any locking related one */ public Set<UnresolvedDependency> collectLockingFailures() { if (dependencyLockingState.mustValidateLockState()) { if (!modulesToBeLocked.isEmpty() || !extraModules.isEmpty()) { lockOutOfDate = true; return createLockingFailures(modulesToBeLocked, extraModules); } } return Collections.emptySet(); } private static Set<UnresolvedDependency> createLockingFailures( Map<ModuleIdentifier, ModuleComponentIdentifier> modulesToBeLocked, Set<ModuleComponentIdentifier> extraModules) { Set<UnresolvedDependency> completedFailures = Sets .newHashSetWithExpectedSize(modulesToBeLocked.values().size() + extraModules.size()); for (ModuleComponentIdentifier presentInLock : modulesToBeLocked.values()) { completedFailures.add(new DefaultUnresolvedDependency( DefaultModuleVersionSelector.newSelector(presentInLock.getModuleIdentifier(), presentInLock.getVersion()), new LockOutOfDateException("Did not resolve '" + presentInLock.getDisplayName() + "' which is part of the dependency lock state"))); } for (ModuleComponentIdentifier extraModule : extraModules) { completedFailures.add(new DefaultUnresolvedDependency( DefaultModuleVersionSelector.newSelector(extraModule.getModuleIdentifier(), extraModule.getVersion()), new LockOutOfDateException("Resolved '" + extraModule.getDisplayName() + "' which is not part of the dependency lock state"))); } return completedFailures; } }