/* * Copyright 2014 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.plugins.ide.internal.resolver; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.ModuleVersionIdentifier; import org.gradle.api.artifacts.ProjectDependency; import org.gradle.api.artifacts.ResolvedArtifact; import org.gradle.api.artifacts.SelfResolvingDependency; import org.gradle.api.artifacts.component.ComponentSelector; import org.gradle.api.artifacts.component.ModuleComponentIdentifier; import org.gradle.api.artifacts.component.ProjectComponentIdentifier; import org.gradle.api.artifacts.result.DependencyResult; import org.gradle.api.artifacts.result.ResolutionResult; import org.gradle.api.artifacts.result.ResolvedComponentResult; import org.gradle.api.artifacts.result.UnresolvedDependencyResult; import org.gradle.api.specs.Spec; import org.gradle.api.specs.Specs; import org.gradle.internal.component.local.model.DefaultProjectComponentIdentifier; import org.gradle.plugins.ide.internal.resolver.model.IdeExtendedRepoFileDependency; import org.gradle.plugins.ide.internal.resolver.model.IdeLocalFileDependency; import org.gradle.plugins.ide.internal.resolver.model.IdeProjectDependency; import org.gradle.plugins.ide.internal.resolver.model.UnresolvedIdeRepoFileDependency; import org.gradle.util.CollectionUtils; import java.io.File; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Set; public class DefaultIdeDependencyResolver implements IdeDependencyResolver { /** * Gets IDE project dependencies. * * @param configuration Configuration * @param project Project * @return IDE project dependencies */ public List<IdeProjectDependency> getIdeProjectDependencies(Configuration configuration, Project project) { ResolutionResult result = getIncomingResolutionResult(configuration); final Set<ResolvedComponentResult> projectComponents = CollectionUtils.filter(result.getAllComponents(), new Spec<ResolvedComponentResult>() { @Override public boolean isSatisfiedBy(ResolvedComponentResult element) { return element.getId() instanceof ProjectComponentIdentifier; } }); List<IdeProjectDependency> ideProjectDependencies = new ArrayList<IdeProjectDependency>(); ProjectComponentIdentifier thisProjectId = DefaultProjectComponentIdentifier.newProjectId(project); for (ResolvedComponentResult projectComponent : projectComponents) { ProjectComponentIdentifier projectId = (ProjectComponentIdentifier) projectComponent.getId(); if (thisProjectId.equals(projectId)) { continue; } ideProjectDependencies.add(new IdeProjectDependency(projectId)); } return ideProjectDependencies; } /** * Gets unresolved IDE repository file dependencies. * * @param configuration Configuration * @return Unresolved IDE repository file dependencies */ public List<UnresolvedIdeRepoFileDependency> getUnresolvedIdeRepoFileDependencies(Configuration configuration) { ResolutionResult result = getIncomingResolutionResult(configuration); List<UnresolvedDependencyResult> unresolvedDependencies = findAllUnresolvedDependencyResults(result.getRoot().getDependencies()); List<UnresolvedIdeRepoFileDependency> unresolvedIdeRepoFileDependencies = new ArrayList<UnresolvedIdeRepoFileDependency>(); for (UnresolvedDependencyResult unresolvedDependencyResult : unresolvedDependencies) { Throwable failure = unresolvedDependencyResult.getFailure(); ComponentSelector componentSelector = unresolvedDependencyResult.getAttempted(); String displayName = componentSelector.getDisplayName(); File file = new File(unresolvedFileName(componentSelector)); unresolvedIdeRepoFileDependencies.add(new UnresolvedIdeRepoFileDependency(file, failure, displayName)); } return unresolvedIdeRepoFileDependencies; } /** * Creates unresolved file name. * * @param componentSelector Component selector * @return Unresolved file name */ private String unresolvedFileName(ComponentSelector componentSelector) { return "unresolved dependency - " + componentSelector.getDisplayName().replaceAll(":", " "); } /** * Gets IDE repository file dependencies. * * @param configuration Configuration * @return IDE repository file dependencies */ public List<IdeExtendedRepoFileDependency> getIdeRepoFileDependencies(Configuration configuration) { ResolutionResult result = getIncomingResolutionResult(configuration); final Set<ResolvedComponentResult> resolvedRepoFileComponents = CollectionUtils.filter(result.getAllComponents(), new Spec<ResolvedComponentResult>() { @Override public boolean isSatisfiedBy(ResolvedComponentResult element) { return element.getId() instanceof ModuleComponentIdentifier; } }); Set<ModuleVersionIdentifier> mappedResolvedDependencies = mapResolvedDependencies(resolvedRepoFileComponents); Set<ResolvedArtifact> artifacts = getExternalArtifacts(configuration); List<IdeExtendedRepoFileDependency> externalDependencies = new ArrayList<IdeExtendedRepoFileDependency>(); for (ResolvedArtifact artifact : artifacts) { if (mappedResolvedDependencies.contains(artifact.getModuleVersion().getId())) { IdeExtendedRepoFileDependency ideRepoFileDependency = new IdeExtendedRepoFileDependency(artifact.getFile()); ideRepoFileDependency.setId(artifact.getModuleVersion().getId()); externalDependencies.add(ideRepoFileDependency); } } return externalDependencies; } /** * Maps resolved dependencies by module version identifier. * * @param components Resolved dependencies * @return Mapped, resolved dependencies */ private Set<ModuleVersionIdentifier> mapResolvedDependencies(Set<ResolvedComponentResult> components) { Set<ModuleVersionIdentifier> mappedResolvedDependencies = new LinkedHashSet<ModuleVersionIdentifier>(); for (ResolvedComponentResult component : components) { mappedResolvedDependencies.add(component.getModuleVersion()); } return mappedResolvedDependencies; } /** * Gets IDE local file dependencies. * * @param configuration Configuration * @return IDE local file dependencies */ public List<IdeLocalFileDependency> getIdeLocalFileDependencies(Configuration configuration) { List<SelfResolvingDependency> externalDependencies = new ArrayList<SelfResolvingDependency>(); findAllExternalDependencies(externalDependencies, new ArrayList<Dependency>(), configuration); List<IdeLocalFileDependency> ideLocalFileDependencies = new ArrayList<IdeLocalFileDependency>(); for (SelfResolvingDependency externalDependency : externalDependencies) { Set<File> resolvedFiles = externalDependency.resolve(configuration.isTransitive()); for (File resolvedFile : resolvedFiles) { IdeLocalFileDependency ideLocalFileDependency = new IdeLocalFileDependency(resolvedFile); ideLocalFileDependencies.add(ideLocalFileDependency); } } return ideLocalFileDependencies; } /** * Finds all external dependencies. * * @param configuration Configuration * @return External dependencies */ private List<SelfResolvingDependency> findAllExternalDependencies(List<SelfResolvingDependency> externalDependencies, List<Dependency> visited, Configuration configuration) { for (Dependency dependency : configuration.getAllDependencies()) { if(!visited.contains(dependency)){ visited.add(dependency); if(dependency instanceof ProjectDependency && configuration.isTransitive()) { findAllExternalDependencies(externalDependencies, visited, getTargetConfiguration((ProjectDependency) dependency)); } else if (dependency instanceof SelfResolvingDependency) { externalDependencies.add((SelfResolvingDependency) dependency); } } } return externalDependencies; } private Configuration getTargetConfiguration(ProjectDependency dependency) { String targetConfiguration = dependency.getTargetConfiguration(); if (targetConfiguration == null) { targetConfiguration = Dependency.DEFAULT_CONFIGURATION; } return dependency.getDependencyProject().getConfigurations().getByName(targetConfiguration); } /** * Gets incoming resolution result for a given configuration. * * @param configuration Configuration * @return Incoming resolution result */ private ResolutionResult getIncomingResolutionResult(Configuration configuration) { return configuration.getIncoming().getResolutionResult(); } /** * Finds all unresolved dependency results. * * @param dependencies Unfiltered dependencies * @return Unresolved dependency results. */ private List<UnresolvedDependencyResult> findAllUnresolvedDependencyResults(Set<? extends DependencyResult> dependencies) { List<UnresolvedDependencyResult> unresolvedDependencyResults = new ArrayList<UnresolvedDependencyResult>(); for (DependencyResult dependencyResult : dependencies) { if (dependencyResult instanceof UnresolvedDependencyResult) { unresolvedDependencyResults.add((UnresolvedDependencyResult) dependencyResult); } } return unresolvedDependencyResults; } /** * Gets all external artifacts. * * @param configuration Configuration * @return External artifacts */ private Set<ResolvedArtifact> getExternalArtifacts(Configuration configuration) { return configuration.getResolvedConfiguration().getLenientConfiguration().getArtifacts(Specs.SATISFIES_ALL); } }