IDEA-155548 gradle: classpath does not include generated resources
[idea/community.git] / plugins / gradle / tooling-extension-impl / src / org / jetbrains / plugins / gradle / tooling / builder / ModelBuildScriptClasspathBuilderImpl.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.jetbrains.plugins.gradle.tooling.builder;
17
18 import org.gradle.api.Project;
19 import org.gradle.api.artifacts.Configuration;
20 import org.gradle.plugins.ide.idea.IdeaPlugin;
21 import org.gradle.plugins.ide.idea.model.IdeaModule;
22 import org.gradle.util.GradleVersion;
23 import org.jetbrains.annotations.NotNull;
24 import org.jetbrains.annotations.Nullable;
25 import org.jetbrains.plugins.gradle.model.*;
26 import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder;
27 import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
28 import org.jetbrains.plugins.gradle.tooling.internal.BuildScriptClasspathModelImpl;
29 import org.jetbrains.plugins.gradle.tooling.internal.ClasspathEntryModelImpl;
30 import org.jetbrains.plugins.gradle.tooling.util.DependencyResolverImpl;
31 import org.jetbrains.plugins.gradle.tooling.util.DependencyTraverser;
32 import org.jetbrains.plugins.gradle.tooling.util.SourceSetCachedFinder;
33
34 import java.io.File;
35 import java.util.*;
36 import java.util.concurrent.ConcurrentHashMap;
37
38 /**
39  * @author Vladislav.Soroka
40  * @since 12/20/13
41  */
42 public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService {
43
44   private static final String CLASSPATH_CONFIGURATION_NAME = "classpath";
45   private final Map<String, BuildScriptClasspathModelImpl> cache = new ConcurrentHashMap<String, BuildScriptClasspathModelImpl>();
46   private SourceSetCachedFinder mySourceSetFinder = null;
47
48   @Override
49   public boolean canBuild(String modelName) {
50     return BuildScriptClasspathModel.class.getName().equals(modelName);
51   }
52
53   @Nullable
54   @Override
55   public Object buildAll(final String modelName, final Project project) {
56     BuildScriptClasspathModelImpl buildScriptClasspath = cache.get(project.getPath());
57     if (buildScriptClasspath != null) return buildScriptClasspath;
58
59     if(mySourceSetFinder == null) mySourceSetFinder = new SourceSetCachedFinder(project);
60
61     buildScriptClasspath = new BuildScriptClasspathModelImpl();
62     final File gradleHomeDir = project.getGradle().getGradleHomeDir();
63     buildScriptClasspath.setGradleHomeDir(gradleHomeDir);
64     buildScriptClasspath.setGradleVersion(GradleVersion.current().getVersion());
65
66     boolean downloadJavadoc = false;
67     boolean downloadSources = true;
68
69     final IdeaPlugin ideaPlugin = project.getPlugins().findPlugin(IdeaPlugin.class);
70     if (ideaPlugin != null) {
71       final IdeaModule ideaModule = ideaPlugin.getModel().getModule();
72       downloadJavadoc = ideaModule.isDownloadJavadoc();
73       downloadSources = ideaModule.isDownloadSources();
74     }
75
76     Project parent = project.getParent();
77     if (parent != null) {
78       BuildScriptClasspathModelImpl parentBuildScriptClasspath = (BuildScriptClasspathModelImpl)buildAll(modelName, parent);
79       if (parentBuildScriptClasspath != null) {
80         for (ClasspathEntryModel classpathEntryModel : parentBuildScriptClasspath.getClasspath()) {
81           buildScriptClasspath.add(classpathEntryModel);
82         }
83       }
84     }
85     Configuration classpathConfiguration = project.getBuildscript().getConfigurations().findByName(CLASSPATH_CONFIGURATION_NAME);
86     if (classpathConfiguration == null) return null;
87
88     Collection<ExternalDependency> dependencies =
89       new DependencyResolverImpl(project, false, downloadJavadoc, downloadSources, mySourceSetFinder).resolveDependencies(classpathConfiguration);
90
91     for (ExternalDependency dependency : new DependencyTraverser(dependencies)) {
92       if (dependency instanceof ExternalLibraryDependency) {
93         final ExternalLibraryDependency libraryDep = (ExternalLibraryDependency)dependency;
94         buildScriptClasspath.add(new ClasspathEntryModelImpl(
95           pathSet(libraryDep.getFile()),
96           pathSet(libraryDep.getSource()),
97           pathSet(libraryDep.getJavadoc())
98         ));
99       }
100       if (dependency instanceof ExternalMultiLibraryDependency) {
101         ExternalMultiLibraryDependency multiLibraryDependency = (ExternalMultiLibraryDependency)dependency;
102         buildScriptClasspath.add(new ClasspathEntryModelImpl(
103           pathSet(multiLibraryDependency.getFiles()),
104           pathSet(multiLibraryDependency.getSources()),
105           pathSet(multiLibraryDependency.getJavadoc())
106         ));
107       }
108
109       if (dependency instanceof FileCollectionDependency) {
110         FileCollectionDependency fileCollectionDependency = (FileCollectionDependency)dependency;
111         buildScriptClasspath.add(new ClasspathEntryModelImpl(
112           pathSet(fileCollectionDependency.getFiles()),
113           new HashSet<String>(),
114           new HashSet<String>()
115         ));
116       }
117     }
118
119     cache.put(project.getPath(), buildScriptClasspath);
120     return buildScriptClasspath;
121   }
122
123   @NotNull
124   @Override
125   public ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) {
126     return ErrorMessageBuilder.create(
127       project, e, "Project build classpath resolve errors"
128     ).withDescription("Unable to resolve additional buildscript classpath dependencies");
129   }
130
131   private static Set<String> pathSet(Collection<File> files) {
132     Set<String> set = new HashSet<String>();
133     for (File file : files) {
134       if(file != null) {
135         set.add(file.getPath());
136       }
137     }
138     return set;
139   }
140
141   private static Set<String> pathSet(File... files) {
142     return pathSet(Arrays.asList(files));
143   }
144 }