diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/EarModelBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/EarModelBuilderImpl.groovy index 7a303ddc328b..b6a9cb706e14 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/EarModelBuilderImpl.groovy +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/EarModelBuilderImpl.groovy @@ -33,8 +33,8 @@ import org.jetbrains.plugins.gradle.tooling.internal.ear.EarModelImpl import org.jetbrains.plugins.gradle.tooling.internal.ear.EarResourceImpl import org.jetbrains.plugins.gradle.tooling.util.ArtifactsCollectionResolver import org.jetbrains.plugins.gradle.tooling.util.DependencyResolver -import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder +import org.jetbrains.plugins.gradle.tooling.util.resolve.DependencyResolverImpl /** * @author Vladislav.Soroka diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ModelBuildScriptClasspathBuilderImpl.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ModelBuildScriptClasspathBuilderImpl.java index c6927345ea1a..42f70d1d078c 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ModelBuildScriptClasspathBuilderImpl.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/ModelBuildScriptClasspathBuilderImpl.java @@ -28,9 +28,9 @@ import org.jetbrains.plugins.gradle.tooling.ModelBuilderService; import org.jetbrains.plugins.gradle.tooling.internal.BuildScriptClasspathModelImpl; import org.jetbrains.plugins.gradle.tooling.internal.ClasspathEntryModelImpl; import org.jetbrains.plugins.gradle.tooling.util.ArtifactsCollectionResolver; -import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl; import org.jetbrains.plugins.gradle.tooling.util.DependencyTraverser; import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder; +import org.jetbrains.plugins.gradle.tooling.util.resolve.DependencyResolverImpl; import java.io.File; import java.util.*; diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/ArtifactsCollectionResolver.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/ArtifactsCollectionResolver.java index 6299a648e665..a96f2342afc7 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/ArtifactsCollectionResolver.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/ArtifactsCollectionResolver.java @@ -18,6 +18,8 @@ import org.gradle.language.java.artifact.JavadocArtifact; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.ExternalDependency; +import org.jetbrains.plugins.gradle.tooling.util.resolve.DependencyResolverImpl; +import org.jetbrains.plugins.gradle.tooling.util.resolve.ExternalDepsResolutionResult; import java.util.*; @@ -49,7 +51,7 @@ public class ArtifactsCollectionResolver extends DependencyResolverImpl implemen } @Override - Collection resolveDependencies(@Nullable String configurationName, @Nullable String scope) { + public Collection resolveDependencies(@Nullable String configurationName, @Nullable String scope) { if (configurationName == null) { return EMPTY; } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/DependencyResolverImpl.java similarity index 68% rename from plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.java rename to plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/DependencyResolverImpl.java index a2a87e187456..a96649e7f527 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/DependencyResolverImpl.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/DependencyResolverImpl.java @@ -1,40 +1,23 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * 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. - */ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. -package org.jetbrains.plugins.gradle.tooling.util; +package org.jetbrains.plugins.gradle.tooling.util.resolve; -import groovy.lang.MetaMethod; -import groovy.lang.MetaProperty; -import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.artifacts.*; -import org.gradle.api.artifacts.component.*; +import org.gradle.api.artifacts.component.ComponentIdentifier; +import org.gradle.api.artifacts.component.ModuleComponentIdentifier; +import org.gradle.api.artifacts.component.ProjectComponentIdentifier; import org.gradle.api.artifacts.dsl.DependencyHandler; -import org.gradle.api.artifacts.result.*; +import org.gradle.api.artifacts.result.ComponentArtifactsResult; +import org.gradle.api.artifacts.result.ResolutionResult; import org.gradle.api.component.Artifact; import org.gradle.api.component.Component; import org.gradle.api.plugins.WarPlugin; import org.gradle.api.specs.Specs; -import org.gradle.api.tasks.AbstractCopyTask; import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSetContainer; -import org.gradle.api.tasks.SourceSetOutput; -import org.gradle.api.tasks.bundling.AbstractArchiveTask; import org.gradle.api.tasks.compile.AbstractCompile; import org.gradle.internal.impldep.com.google.common.base.Function; import org.gradle.internal.impldep.com.google.common.base.Predicate; @@ -42,7 +25,6 @@ import org.gradle.internal.impldep.com.google.common.collect.ArrayListMultimap; import org.gradle.internal.impldep.com.google.common.collect.Lists; import org.gradle.internal.impldep.com.google.common.collect.Multimap; import org.gradle.internal.impldep.com.google.common.collect.Sets; -import org.gradle.internal.impldep.com.google.common.io.Files; import org.gradle.language.base.artifact.SourcesArtifact; import org.gradle.language.java.artifact.JavadocArtifact; import org.gradle.plugins.ide.idea.IdeaPlugin; @@ -53,11 +35,14 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.gradle.model.*; import org.jetbrains.plugins.gradle.model.ExternalDependency; import org.jetbrains.plugins.gradle.model.FileCollectionDependency; +import org.jetbrains.plugins.gradle.tooling.util.DependencyResolver; +import org.jetbrains.plugins.gradle.tooling.util.DependencyTraverser; +import org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierImpl; +import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; -import java.lang.reflect.Method; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -115,7 +100,7 @@ public class DependencyResolverImpl implements DependencyResolver { return resolveDependencies(configurationName, null); } - Collection resolveDependencies(@Nullable String configurationName, @Nullable String scope) { + public Collection resolveDependencies(@Nullable String configurationName, @Nullable String scope) { if (configurationName == null) return Collections.emptyList(); return resolveDependencies(myProject.getConfigurations().findByName(configurationName), scope).getExternalDeps(); } @@ -125,27 +110,7 @@ public class DependencyResolverImpl implements DependencyResolver { return resolveDependencies(configuration, null).getExternalDeps(); } - protected static class ExternalDepsResolutionResult { - public static ExternalDepsResolutionResult - EMPTY = new ExternalDepsResolutionResult(Collections.emptySet(), Collections.emptySet()); - private final Collection externalDeps; - private final Collection resolvedFiles; - - public ExternalDepsResolutionResult(Collection deps, Collection files) { - externalDeps = deps; - resolvedFiles = files; - } - - public Collection getResolvedFiles() { - return resolvedFiles; - } - - public Collection getExternalDeps() { - return externalDeps; - } - } - - ExternalDepsResolutionResult resolveDependencies(@Nullable Configuration configuration, @Nullable String scope) { + public ExternalDepsResolutionResult resolveDependencies(@Nullable Configuration configuration, @Nullable String scope) { if (configuration == null) { return ExternalDepsResolutionResult.EMPTY; } @@ -245,7 +210,7 @@ public class DependencyResolverImpl implements DependencyResolver { } DependencyResultsTransformer dependencyResultsTransformer = - new DependencyResultsTransformer(artifactMap, componentResultsMap, configurationProjectDependencies, scope); + new DependencyResultsTransformer(myProject, mySourceSetFinder, artifactMap, componentResultsMap, configurationProjectDependencies, scope); result.addAll(dependencyResultsTransformer.transform(resolutionResult.getRoot().getDependencies())); resolvedFileDependencies.addAll(dependencyResultsTransformer.resolvedDepsFiles); @@ -846,11 +811,11 @@ public class DependencyResolverImpl implements DependencyResolver { return name; } - public ModuleComponentIdentifier toComponentIdentifier(ModuleVersionIdentifier id) { + public static ModuleComponentIdentifier toComponentIdentifier(ModuleVersionIdentifier id) { return new ModuleComponentIdentifierImpl(id.getGroup(), id.getName(), id.getVersion()); } - public ModuleComponentIdentifier toComponentIdentifier(@NotNull String group, @NotNull String module, @NotNull String version) { + public static ModuleComponentIdentifier toComponentIdentifier(@NotNull String group, @NotNull String module, @NotNull String version) { return new ModuleComponentIdentifierImpl(group, module, version); } @@ -950,7 +915,7 @@ public class DependencyResolverImpl implements DependencyResolver { return result; } - private static Configuration getTargetConfiguration(ProjectDependency projectDependency) { + public static Configuration getTargetConfiguration(ProjectDependency projectDependency) { try { return !is4OrBetter ? (Configuration)projectDependency.getClass().getMethod("getProjectConfiguration").invoke(projectDependency) : @@ -964,277 +929,7 @@ public class DependencyResolverImpl implements DependencyResolver { } - class DependencyResultsTransformer { - Collection handledDependencyResults; - Multimap artifactMap; - Map componentResultsMap; - Multimap configurationProjectDependencies; - String scope; - Set resolvedDepsFiles = new HashSet(); - - DependencyResultsTransformer( - Multimap artifactMap, - Map componentResultsMap, - Multimap configurationProjectDependencies, - String scope) { - this.handledDependencyResults = Lists.newArrayList(); - this.artifactMap = artifactMap; - this.componentResultsMap = componentResultsMap; - this.configurationProjectDependencies = configurationProjectDependencies; - this.scope = scope; - } - - Set transform(Collection dependencyResults) { - - Set dependencies = new LinkedHashSet(); - for (DependencyResult dependencyResult : dependencyResults) { - - // dependency cycles check - if (!handledDependencyResults.contains(dependencyResult)) { - handledDependencyResults.add(dependencyResult); - - if (dependencyResult instanceof ResolvedDependencyResult) { - ResolvedComponentResult componentResult = ((ResolvedDependencyResult)dependencyResult).getSelected(); - ComponentSelector componentSelector = dependencyResult.getRequested(); - ModuleComponentIdentifier componentIdentifier = toComponentIdentifier(componentResult.getModuleVersion()); - - String name = componentResult.getModuleVersion().getName(); - String group = componentResult.getModuleVersion().getGroup(); - String version = componentResult.getModuleVersion().getVersion(); - String selectionReason = componentResult.getSelectionReason().getDescription(); - - boolean resolveFromArtifacts = componentSelector instanceof ModuleComponentSelector; - - if (componentSelector instanceof ProjectComponentSelector) { - Collection projectDependencies = configurationProjectDependencies.get(componentIdentifier); - Collection dependencyConfigurations; - if (projectDependencies.isEmpty()) { - Project dependencyProject = myProject.findProject(((ProjectComponentSelector)componentSelector).getProjectPath()); - if (dependencyProject != null) { - Configuration dependencyProjectConfiguration = - dependencyProject.getConfigurations().getByName(Dependency.DEFAULT_CONFIGURATION); - dependencyConfigurations = Collections.singleton(dependencyProjectConfiguration); - } else { - dependencyConfigurations = Collections.emptySet(); - resolveFromArtifacts = true; - selectionReason = "composite build substitution"; - } - } else { - dependencyConfigurations = new ArrayList(); - for (ProjectDependency dependency : projectDependencies) { - dependencyConfigurations.add(getTargetConfiguration(dependency)); - } - } - - for (Configuration it : dependencyConfigurations) { - if (it.getName().equals(Dependency.DEFAULT_CONFIGURATION)) { - DefaultExternalProjectDependency dependency = new DefaultExternalProjectDependency(); - dependency.setName( name); - dependency.setGroup(group); - dependency.setVersion(version); - dependency.setScope(scope); - dependency.setSelectionReason(selectionReason); - dependency.setProjectPath(((ProjectComponentSelector)componentSelector).getProjectPath()); - dependency.setConfigurationName(it.getName()); - Set artifacts = it.getAllArtifacts().getFiles().getFiles(); - dependency.setProjectDependencyArtifacts(artifacts); - setProjectDependencyArtifactsSources(dependency, artifacts, mySourceSetFinder); - - resolvedDepsFiles.addAll(dependency.getProjectDependencyArtifacts()); - - if (it.getArtifacts().size() == 1) { - PublishArtifact publishArtifact = it.getAllArtifacts().iterator().next(); - dependency.setClassifier(publishArtifact.getClassifier()); - dependency.setPackaging(publishArtifact.getExtension() != null ? publishArtifact.getExtension() : "jar"); - } - - if (!componentResult.equals(dependencyResult.getFrom())) { - dependency.getDependencies().addAll( - transform(componentResult.getDependencies()) - ); - } - dependencies.add(dependency); - } - else { - DefaultExternalProjectDependency dependency = new DefaultExternalProjectDependency(); - dependency.setName(name); - dependency.setGroup(group); - dependency.setVersion(version); - dependency.setScope(scope); - dependency.setSelectionReason(selectionReason); - dependency.setProjectPath(((ProjectComponentSelector)componentSelector).getProjectPath()); - dependency.setConfigurationName(it.getName()); - Set artifactsFiles = it.getAllArtifacts().getFiles().getFiles(); - dependency.setProjectDependencyArtifacts(artifactsFiles); - setProjectDependencyArtifactsSources(dependency, artifactsFiles, mySourceSetFinder); - - resolvedDepsFiles.addAll(dependency.getProjectDependencyArtifacts()); - - if (it.getArtifacts().size() == 1) { - PublishArtifact publishArtifact = it.getAllArtifacts().iterator().next(); - dependency.setClassifier(publishArtifact.getClassifier()); - dependency.setPackaging(publishArtifact.getExtension() != null ? publishArtifact.getExtension() : "jar"); - } - - if (!componentResult.equals(dependencyResult.getFrom())) { - - dependency.getDependencies().addAll( - transform(componentResult.getDependencies()) - ); - } - - dependencies.add(dependency); - - List files = new ArrayList(); - PublishArtifactSet artifacts = it.getArtifacts(); - if (artifacts != null && !artifacts.isEmpty()) { - PublishArtifact artifact = artifacts.iterator().next(); - final MetaProperty taskProperty = DefaultGroovyMethods.hasProperty(artifact, "archiveTask"); - if (taskProperty != null && (taskProperty.getProperty(artifact) instanceof AbstractArchiveTask)) { - - AbstractArchiveTask archiveTask = (AbstractArchiveTask)taskProperty.getProperty(artifact); - resolvedDepsFiles.add(new File(archiveTask.getDestinationDir(), archiveTask.getArchiveName())); - - - try { - final Method mainSpecGetter = AbstractCopyTask.class.getDeclaredMethod("getMainSpec"); - mainSpecGetter.setAccessible(true); - Object mainSpec = mainSpecGetter.invoke(archiveTask); - - final List sourcePathGetters = - DefaultGroovyMethods.respondsTo(mainSpec, "getSourcePaths", new Object[]{}); - if (!sourcePathGetters.isEmpty()) { - Set sourcePaths = (Set)sourcePathGetters.get(0).doMethodInvoke(mainSpec, new Object[]{}); - if (sourcePaths != null) { - for (Object path : sourcePaths) { - if (path instanceof String) { - File file = new File((String)path); - if (file.isAbsolute()) { - files.add(file); - } - } - else if (path instanceof SourceSetOutput) { - files.addAll(((SourceSetOutput)path).getFiles()); - } - } - } - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - if (!files.isEmpty()) { - final DefaultFileCollectionDependency fileCollectionDependency = new DefaultFileCollectionDependency(files); - fileCollectionDependency.setScope(scope); - dependencies.add(fileCollectionDependency); - resolvedDepsFiles.addAll(files); - } - } - } - } - - if (resolveFromArtifacts) { - Collection artifacts = artifactMap.get(componentResult.getModuleVersion()); - - if (artifacts != null && artifacts.isEmpty()) { - dependencies.addAll( - transform(componentResult.getDependencies()) - ); - } - - boolean first = true; - - if (artifacts != null) { - for (ResolvedArtifact artifact: artifacts) { - String packaging = artifact.getExtension() != null ? artifact.getExtension() : "jar"; - String classifier = artifact.getClassifier(); - final ExternalDependency dependency; - if (isProjectDependencyArtifact(artifact)) { - ProjectComponentIdentifier artifactComponentIdentifier = - (ProjectComponentIdentifier)artifact.getId().getComponentIdentifier(); - - dependency = new DefaultExternalProjectDependency(); - DefaultExternalProjectDependency dDep = (DefaultExternalProjectDependency)dependency; - dDep.setName(name); - dDep.setGroup(group); - dDep.setVersion(version); - dDep.setScope(scope); - dDep.setSelectionReason(selectionReason); - dDep.setProjectPath(artifactComponentIdentifier.getProjectPath()); - dDep.setConfigurationName(Dependency.DEFAULT_CONFIGURATION); - - List files = new ArrayList(); - for (ResolvedArtifact resolvedArtifact : artifactMap.get(componentResult.getModuleVersion())) { - files.add(resolvedArtifact.getFile()); - } - dDep.setProjectDependencyArtifacts(files); - setProjectDependencyArtifactsSources(dDep, files, mySourceSetFinder); - resolvedDepsFiles.addAll(dDep.getProjectDependencyArtifacts()); - } - else { - dependency = new DefaultExternalLibraryDependency(); - DefaultExternalLibraryDependency dDep = (DefaultExternalLibraryDependency)dependency; - dDep.setName(name); - dDep.setGroup(group); - dDep.setPackaging(packaging); - dDep.setClassifier(classifier); - dDep.setVersion(version); - dDep.setScope(scope); - dDep.setSelectionReason(selectionReason); - dDep.setFile(artifact.getFile()); - - ComponentArtifactsResult artifactsResult = componentResultsMap.get(componentIdentifier); - if (artifactsResult != null) { - ResolvedArtifactResult sourcesResult = findMatchingArtifact(artifact, artifactsResult, SourcesArtifact.class); - if (sourcesResult != null) { - ((DefaultExternalLibraryDependency)dependency).setSource(sourcesResult.getFile()); - } - - ResolvedArtifactResult javadocResult = findMatchingArtifact(artifact, artifactsResult, JavadocArtifact.class); - if (javadocResult != null) { - ((DefaultExternalLibraryDependency)dependency).setJavadoc(javadocResult.getFile()); - } - } - } - - if (first) { - dependency.getDependencies().addAll( - transform(componentResult.getDependencies()) - ); - first = false; - } - - dependencies.add(dependency); - resolvedDepsFiles.add(artifact.getFile()); - } - } - } - } - - if (dependencyResult instanceof UnresolvedDependencyResult) { - ComponentSelector attempted = ((UnresolvedDependencyResult)dependencyResult).getAttempted(); - if (attempted instanceof ModuleComponentSelector) { - final ModuleComponentSelector attemptedMCSelector = (ModuleComponentSelector)attempted; - final DefaultUnresolvedExternalDependency dependency = new DefaultUnresolvedExternalDependency(); - dependency.setName(attemptedMCSelector.getModule()); - dependency.setGroup(attemptedMCSelector.getGroup()); - dependency.setVersion(attemptedMCSelector.getVersion()); - dependency.setScope(scope); - dependency.setFailureMessage(((UnresolvedDependencyResult)dependencyResult).getFailure().getMessage()); - - dependencies.add(dependency); - } - } - } - } - - return dependencies; - } - } - - private static void setProjectDependencyArtifactsSources(DefaultExternalProjectDependency projectDependency, + public static void setProjectDependencyArtifactsSources(DefaultExternalProjectDependency projectDependency, Collection artifactFiles, SourceSetCachedFinder sourceSetFinder) { List artifactSources = new ArrayList(); @@ -1247,27 +942,7 @@ public class DependencyResolverImpl implements DependencyResolver { projectDependency.setProjectDependencyArtifactsSources(artifactSources); } - @Nullable - private static ResolvedArtifactResult findMatchingArtifact(ResolvedArtifact artifact, - ComponentArtifactsResult componentArtifacts, - Class artifactType) { - String baseName = Files.getNameWithoutExtension(artifact.getFile().getName()); - Set artifactResults = componentArtifacts.getArtifacts(artifactType); - - if (artifactResults.size() == 1) { - ArtifactResult artifactResult = artifactResults.iterator().next(); - return artifactResult instanceof ResolvedArtifactResult ? (ResolvedArtifactResult)artifactResult : null; - } - - for (ArtifactResult result : artifactResults) { - if (result instanceof ResolvedArtifactResult && ((ResolvedArtifactResult)result).getFile().getName().startsWith(baseName)) { - return (ResolvedArtifactResult)result; - } - } - return null; - } - - private static boolean isProjectDependencyArtifact(ResolvedArtifact artifact) { + public static boolean isProjectDependencyArtifact(ResolvedArtifact artifact) { return isDependencySubstitutionsSupported && artifact.getId().getComponentIdentifier() instanceof ProjectComponentIdentifier; } @@ -1278,39 +953,4 @@ public class DependencyResolverImpl implements DependencyResolver { private static MyModuleIdentifier toMyModuleIdentifier(String name, String group) { return new MyModuleIdentifier(name, group); } - - static class MyModuleIdentifier { - String name; - String group; - - public MyModuleIdentifier(String name, String group) { - this.name = name; - this.group = group; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - MyModuleIdentifier that = (MyModuleIdentifier)o; - - if (name != null ? !name.equals(that.name) : that.name != null) return false; - if (group != null ? !group.equals(that.group) : that.group != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result = (group != null ? group.hashCode() : 0); - result = 31 * result + (name != null ? name.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return group + ":" + name; - } - } } diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/DependencyResultsTransformer.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/DependencyResultsTransformer.java new file mode 100644 index 000000000000..8f162b7f193c --- /dev/null +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/DependencyResultsTransformer.java @@ -0,0 +1,323 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.tooling.util.resolve; + +import groovy.lang.MetaMethod; +import groovy.lang.MetaProperty; +import org.codehaus.groovy.runtime.DefaultGroovyMethods; +import org.gradle.api.Project; +import org.gradle.api.artifacts.*; +import org.gradle.api.artifacts.component.*; +import org.gradle.api.artifacts.result.*; +import org.gradle.api.component.Artifact; +import org.gradle.api.tasks.AbstractCopyTask; +import org.gradle.api.tasks.SourceSetOutput; +import org.gradle.api.tasks.bundling.AbstractArchiveTask; +import org.gradle.internal.impldep.com.google.common.collect.Lists; +import org.gradle.internal.impldep.com.google.common.collect.Multimap; +import org.gradle.internal.impldep.com.google.common.io.Files; +import org.gradle.language.base.artifact.SourcesArtifact; +import org.gradle.language.java.artifact.JavadocArtifact; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.model.*; +import org.jetbrains.plugins.gradle.model.ExternalDependency; +import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder; + +import java.io.File; +import java.lang.reflect.Method; +import java.util.*; + +class DependencyResultsTransformer { + private final Project myProject; + private final SourceSetCachedFinder mySourceSetFinder; + Collection handledDependencyResults; + Multimap artifactMap; + Map componentResultsMap; + Multimap configurationProjectDependencies; + String scope; + Set resolvedDepsFiles = new HashSet(); + + DependencyResultsTransformer(Project project, + SourceSetCachedFinder sourceSetFinder, + Multimap artifactMap, + Map componentResultsMap, + Multimap configurationProjectDependencies, + String scope) { + myProject = project; + mySourceSetFinder = sourceSetFinder; + this.handledDependencyResults = Lists.newArrayList(); + this.artifactMap = artifactMap; + this.componentResultsMap = componentResultsMap; + this.configurationProjectDependencies = configurationProjectDependencies; + this.scope = scope; + } + + Set transform(Collection dependencyResults) { + + Set dependencies = new LinkedHashSet(); + for (DependencyResult dependencyResult : dependencyResults) { + + // dependency cycles check + if (!handledDependencyResults.contains(dependencyResult)) { + handledDependencyResults.add(dependencyResult); + + if (dependencyResult instanceof ResolvedDependencyResult) { + ResolvedComponentResult componentResult = ((ResolvedDependencyResult)dependencyResult).getSelected(); + ComponentSelector componentSelector = dependencyResult.getRequested(); + ModuleComponentIdentifier componentIdentifier = DependencyResolverImpl.toComponentIdentifier(componentResult.getModuleVersion()); + + String name = componentResult.getModuleVersion().getName(); + String group = componentResult.getModuleVersion().getGroup(); + String version = componentResult.getModuleVersion().getVersion(); + String selectionReason = componentResult.getSelectionReason().getDescription(); + + boolean resolveFromArtifacts = componentSelector instanceof ModuleComponentSelector; + + if (componentSelector instanceof ProjectComponentSelector) { + Collection projectDependencies = configurationProjectDependencies.get(componentIdentifier); + Collection dependencyConfigurations; + if (projectDependencies.isEmpty()) { + Project dependencyProject = myProject.findProject(((ProjectComponentSelector)componentSelector).getProjectPath()); + if (dependencyProject != null) { + Configuration dependencyProjectConfiguration = + dependencyProject.getConfigurations().getByName(Dependency.DEFAULT_CONFIGURATION); + dependencyConfigurations = Collections.singleton(dependencyProjectConfiguration); + } else { + dependencyConfigurations = Collections.emptySet(); + resolveFromArtifacts = true; + selectionReason = "composite build substitution"; + } + } else { + dependencyConfigurations = new ArrayList(); + for (ProjectDependency dependency : projectDependencies) { + dependencyConfigurations.add(DependencyResolverImpl.getTargetConfiguration(dependency)); + } + } + + for (Configuration it : dependencyConfigurations) { + if (it.getName().equals(Dependency.DEFAULT_CONFIGURATION)) { + DefaultExternalProjectDependency dependency = new DefaultExternalProjectDependency(); + dependency.setName( name); + dependency.setGroup(group); + dependency.setVersion(version); + dependency.setScope(scope); + dependency.setSelectionReason(selectionReason); + dependency.setProjectPath(((ProjectComponentSelector)componentSelector).getProjectPath()); + dependency.setConfigurationName(it.getName()); + Set artifacts = it.getAllArtifacts().getFiles().getFiles(); + dependency.setProjectDependencyArtifacts(artifacts); + DependencyResolverImpl.setProjectDependencyArtifactsSources(dependency, artifacts, mySourceSetFinder); + + resolvedDepsFiles.addAll(dependency.getProjectDependencyArtifacts()); + + if (it.getArtifacts().size() == 1) { + PublishArtifact publishArtifact = it.getAllArtifacts().iterator().next(); + dependency.setClassifier(publishArtifact.getClassifier()); + dependency.setPackaging(publishArtifact.getExtension() != null ? publishArtifact.getExtension() : "jar"); + } + + if (!componentResult.equals(dependencyResult.getFrom())) { + dependency.getDependencies().addAll( + transform(componentResult.getDependencies()) + ); + } + dependencies.add(dependency); + } + else { + DefaultExternalProjectDependency dependency = new DefaultExternalProjectDependency(); + dependency.setName(name); + dependency.setGroup(group); + dependency.setVersion(version); + dependency.setScope(scope); + dependency.setSelectionReason(selectionReason); + dependency.setProjectPath(((ProjectComponentSelector)componentSelector).getProjectPath()); + dependency.setConfigurationName(it.getName()); + Set artifactsFiles = it.getAllArtifacts().getFiles().getFiles(); + dependency.setProjectDependencyArtifacts(artifactsFiles); + DependencyResolverImpl.setProjectDependencyArtifactsSources(dependency, artifactsFiles, mySourceSetFinder); + + resolvedDepsFiles.addAll(dependency.getProjectDependencyArtifacts()); + + if (it.getArtifacts().size() == 1) { + PublishArtifact publishArtifact = it.getAllArtifacts().iterator().next(); + dependency.setClassifier(publishArtifact.getClassifier()); + dependency.setPackaging(publishArtifact.getExtension() != null ? publishArtifact.getExtension() : "jar"); + } + + if (!componentResult.equals(dependencyResult.getFrom())) { + + dependency.getDependencies().addAll( + transform(componentResult.getDependencies()) + ); + } + + dependencies.add(dependency); + + List files = new ArrayList(); + PublishArtifactSet artifacts = it.getArtifacts(); + if (artifacts != null && !artifacts.isEmpty()) { + PublishArtifact artifact = artifacts.iterator().next(); + final MetaProperty taskProperty = DefaultGroovyMethods.hasProperty(artifact, "archiveTask"); + if (taskProperty != null && (taskProperty.getProperty(artifact) instanceof AbstractArchiveTask)) { + + AbstractArchiveTask archiveTask = (AbstractArchiveTask)taskProperty.getProperty(artifact); + resolvedDepsFiles.add(new File(archiveTask.getDestinationDir(), archiveTask.getArchiveName())); + + + try { + final Method mainSpecGetter = AbstractCopyTask.class.getDeclaredMethod("getMainSpec"); + mainSpecGetter.setAccessible(true); + Object mainSpec = mainSpecGetter.invoke(archiveTask); + + final List sourcePathGetters = + DefaultGroovyMethods.respondsTo(mainSpec, "getSourcePaths", new Object[]{}); + if (!sourcePathGetters.isEmpty()) { + Set sourcePaths = (Set)sourcePathGetters.get(0).doMethodInvoke(mainSpec, new Object[]{}); + if (sourcePaths != null) { + for (Object path : sourcePaths) { + if (path instanceof String) { + File file = new File((String)path); + if (file.isAbsolute()) { + files.add(file); + } + } + else if (path instanceof SourceSetOutput) { + files.addAll(((SourceSetOutput)path).getFiles()); + } + } + } + } + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + if (!files.isEmpty()) { + final DefaultFileCollectionDependency fileCollectionDependency = new DefaultFileCollectionDependency(files); + fileCollectionDependency.setScope(scope); + dependencies.add(fileCollectionDependency); + resolvedDepsFiles.addAll(files); + } + } + } + } + + if (resolveFromArtifacts) { + Collection artifacts = artifactMap.get(componentResult.getModuleVersion()); + + if (artifacts != null && artifacts.isEmpty()) { + dependencies.addAll( + transform(componentResult.getDependencies()) + ); + } + + boolean first = true; + + if (artifacts != null) { + for (ResolvedArtifact artifact: artifacts) { + String packaging = artifact.getExtension() != null ? artifact.getExtension() : "jar"; + String classifier = artifact.getClassifier(); + final ExternalDependency dependency; + if (DependencyResolverImpl.isProjectDependencyArtifact(artifact)) { + ProjectComponentIdentifier artifactComponentIdentifier = + (ProjectComponentIdentifier)artifact.getId().getComponentIdentifier(); + + dependency = new DefaultExternalProjectDependency(); + DefaultExternalProjectDependency dDep = (DefaultExternalProjectDependency)dependency; + dDep.setName(name); + dDep.setGroup(group); + dDep.setVersion(version); + dDep.setScope(scope); + dDep.setSelectionReason(selectionReason); + dDep.setProjectPath(artifactComponentIdentifier.getProjectPath()); + dDep.setConfigurationName(Dependency.DEFAULT_CONFIGURATION); + + List files = new ArrayList(); + for (ResolvedArtifact resolvedArtifact : artifactMap.get(componentResult.getModuleVersion())) { + files.add(resolvedArtifact.getFile()); + } + dDep.setProjectDependencyArtifacts(files); + DependencyResolverImpl.setProjectDependencyArtifactsSources(dDep, files, mySourceSetFinder); + resolvedDepsFiles.addAll(dDep.getProjectDependencyArtifacts()); + } + else { + dependency = new DefaultExternalLibraryDependency(); + DefaultExternalLibraryDependency dDep = (DefaultExternalLibraryDependency)dependency; + dDep.setName(name); + dDep.setGroup(group); + dDep.setPackaging(packaging); + dDep.setClassifier(classifier); + dDep.setVersion(version); + dDep.setScope(scope); + dDep.setSelectionReason(selectionReason); + dDep.setFile(artifact.getFile()); + + ComponentArtifactsResult artifactsResult = componentResultsMap.get(componentIdentifier); + if (artifactsResult != null) { + ResolvedArtifactResult + sourcesResult = findMatchingArtifact(artifact, artifactsResult, SourcesArtifact.class); + if (sourcesResult != null) { + ((DefaultExternalLibraryDependency)dependency).setSource(sourcesResult.getFile()); + } + + ResolvedArtifactResult javadocResult = findMatchingArtifact(artifact, artifactsResult, JavadocArtifact.class); + if (javadocResult != null) { + ((DefaultExternalLibraryDependency)dependency).setJavadoc(javadocResult.getFile()); + } + } + } + + if (first) { + dependency.getDependencies().addAll( + transform(componentResult.getDependencies()) + ); + first = false; + } + + dependencies.add(dependency); + resolvedDepsFiles.add(artifact.getFile()); + } + } + } + } + + if (dependencyResult instanceof UnresolvedDependencyResult) { + ComponentSelector attempted = ((UnresolvedDependencyResult)dependencyResult).getAttempted(); + if (attempted instanceof ModuleComponentSelector) { + final ModuleComponentSelector attemptedMCSelector = (ModuleComponentSelector)attempted; + final DefaultUnresolvedExternalDependency dependency = new DefaultUnresolvedExternalDependency(); + dependency.setName(attemptedMCSelector.getModule()); + dependency.setGroup(attemptedMCSelector.getGroup()); + dependency.setVersion(attemptedMCSelector.getVersion()); + dependency.setScope(scope); + dependency.setFailureMessage(((UnresolvedDependencyResult)dependencyResult).getFailure().getMessage()); + + dependencies.add(dependency); + } + } + } + } + + return dependencies; + } + + @Nullable + private static ResolvedArtifactResult findMatchingArtifact(ResolvedArtifact artifact, + ComponentArtifactsResult componentArtifacts, + Class artifactType) { + String baseName = Files.getNameWithoutExtension(artifact.getFile().getName()); + Set artifactResults = componentArtifacts.getArtifacts(artifactType); + + if (artifactResults.size() == 1) { + ArtifactResult artifactResult = artifactResults.iterator().next(); + return artifactResult instanceof ResolvedArtifactResult ? (ResolvedArtifactResult)artifactResult : null; + } + + for (ArtifactResult result : artifactResults) { + if (result instanceof ResolvedArtifactResult && ((ResolvedArtifactResult)result).getFile().getName().startsWith(baseName)) { + return (ResolvedArtifactResult)result; + } + } + return null; + } +} diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/ExternalDepsResolutionResult.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/ExternalDepsResolutionResult.java new file mode 100644 index 000000000000..f0a09f91b2dd --- /dev/null +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/ExternalDepsResolutionResult.java @@ -0,0 +1,28 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.tooling.util.resolve; + +import org.jetbrains.plugins.gradle.model.ExternalDependency; + +import java.io.File; +import java.util.Collection; +import java.util.Collections; + +class ExternalDepsResolutionResult { + public static ExternalDepsResolutionResult + EMPTY = new ExternalDepsResolutionResult(Collections.emptySet(), Collections.emptySet()); + private final Collection externalDeps; + private final Collection resolvedFiles; + + public ExternalDepsResolutionResult(Collection deps, Collection files) { + externalDeps = deps; + resolvedFiles = files; + } + + public Collection getResolvedFiles() { + return resolvedFiles; + } + + public Collection getExternalDeps() { + return externalDeps; + } +} diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/MyModuleIdentifier.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/MyModuleIdentifier.java new file mode 100644 index 000000000000..6540caf1ea0a --- /dev/null +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/util/resolve/MyModuleIdentifier.java @@ -0,0 +1,37 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.tooling.util.resolve; + +class MyModuleIdentifier { + String name; + String group; + + public MyModuleIdentifier(String name, String group) { + this.name = name; + this.group = group; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + MyModuleIdentifier that = (MyModuleIdentifier)o; + + if (name != null ? !name.equals(that.name) : that.name != null) return false; + if (group != null ? !group.equals(that.group) : that.group != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = (group != null ? group.hashCode() : 0); + result = 31 * result + (name != null ? name.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return group + ":" + name; + } +}