gradle: do not perform import of maven repositories after project open if auto-import...
[idea/community.git] / plugins / gradle / src / org / jetbrains / plugins / gradle / integrations / maven / ImportMavenRepositoriesTask.java
1 /*
2  * Copyright 2000-2013 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.integrations.maven;
17
18 import com.intellij.openapi.application.ApplicationManager;
19 import com.intellij.openapi.application.ReadAction;
20 import com.intellij.openapi.application.Result;
21 import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
22 import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
23 import com.intellij.openapi.module.Module;
24 import com.intellij.openapi.module.ModuleManager;
25 import com.intellij.openapi.project.Project;
26 import com.intellij.openapi.util.io.FileUtil;
27 import com.intellij.openapi.util.text.StringUtil;
28 import com.intellij.openapi.vfs.LocalFileSystem;
29 import com.intellij.openapi.vfs.VirtualFile;
30 import com.intellij.psi.*;
31 import com.intellij.psi.util.PsiTreeUtil;
32 import com.intellij.util.ArrayUtil;
33 import com.intellij.util.Consumer;
34 import com.intellij.util.Function;
35 import com.intellij.util.containers.ContainerUtil;
36 import org.jetbrains.annotations.NotNull;
37 import org.jetbrains.annotations.Nullable;
38 import org.jetbrains.idea.maven.indices.MavenIndex;
39 import org.jetbrains.idea.maven.indices.MavenProjectIndicesManager;
40 import org.jetbrains.idea.maven.model.MavenRemoteRepository;
41 import org.jetbrains.plugins.gradle.util.GradleConstants;
42 import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
43 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
44 import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
45 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement;
46 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
47 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
48 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
49 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
50
51 import java.net.URI;
52 import java.net.URISyntaxException;
53 import java.util.Collection;
54 import java.util.Collections;
55 import java.util.List;
56 import java.util.Set;
57
58 /**
59  * @author Vladislav.Soroka
60  * @since 10/29/13
61  */
62 public class ImportMavenRepositoriesTask implements Runnable {
63   @NotNull
64   private final static MavenRemoteRepository mavenCentralRemoteRepository;
65
66   static {
67     mavenCentralRemoteRepository = new MavenRemoteRepository("central", null, "http://repo1.maven.org/maven2/", null, null, null);
68   }
69
70   private final Project myProject;
71   private final boolean myForce;
72
73   public ImportMavenRepositoriesTask(Project project, boolean force) {
74     myProject = project;
75     myForce = force;
76   }
77
78   public ImportMavenRepositoriesTask(Project project) {
79     this(project, true);
80   }
81
82   @Override
83   public void run() {
84     if(myProject.isDisposed()) return;
85     if (ApplicationManager.getApplication().isUnitTestMode()) return;
86
87     final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
88     final List<PsiFile> psiFileList = ContainerUtil.newArrayList();
89
90     final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
91     for (Module module : moduleManager.getModules()) {
92       if (!ExternalSystemApiUtil.isExternalSystemAwareModule(GradleConstants.SYSTEM_ID, module)) continue;
93
94       final String modulePath = ExternalSystemApiUtil.getExternalProjectPath(module);
95       assert modulePath != null;
96
97       if (!myForce) {
98         final ExternalProjectSettings linkedProjectSettings =
99           ExternalSystemApiUtil.getSettings(myProject, GradleConstants.SYSTEM_ID).getLinkedProjectSettings(modulePath);
100
101         if (linkedProjectSettings == null || !linkedProjectSettings.isUseAutoImport()) continue;
102       }
103
104       String buildScript = FileUtil.findFileInProvidedPath(modulePath, GradleConstants.DEFAULT_SCRIPT_NAME);
105       if (StringUtil.isEmpty(buildScript)) continue;
106
107       VirtualFile virtualFile =
108         localFileSystem.refreshAndFindFileByPath(buildScript);
109       if (virtualFile == null) continue;
110
111       final PsiFile psiFile = PsiManager.getInstance(myProject).findFile(virtualFile);
112       if (psiFile == null) continue;
113       psiFileList.add(psiFile);
114     }
115
116     final PsiFile[] psiFiles = ArrayUtil.toObjectArray(psiFileList, PsiFile.class);
117
118     final Set<MavenRemoteRepository> mavenRemoteRepositories = new ReadAction<Set<MavenRemoteRepository>>() {
119       @Override
120       protected void run(@NotNull Result<Set<MavenRemoteRepository>> result) throws Throwable {
121         Set<MavenRemoteRepository> myRemoteRepositories = ContainerUtil.newHashSet();
122         for (PsiFile psiFile : psiFiles) {
123           List<GrClosableBlock> repositoriesBlocks = ContainerUtil.newArrayList();
124           repositoriesBlocks.addAll(findClosableBlocks(psiFile, "repositories"));
125
126           for (GrClosableBlock closableBlock : findClosableBlocks(psiFile, "buildscript", "subprojects", "allprojects", "project", "configure")) {
127             repositoriesBlocks.addAll(findClosableBlocks(closableBlock, "repositories"));
128           }
129
130           for (GrClosableBlock repositoriesBlock : repositoriesBlocks) {
131             myRemoteRepositories.addAll(findMavenRemoteRepositories(repositoriesBlock));
132           }
133         }
134
135         result.setResult(myRemoteRepositories);
136       }
137     }.execute().getResultObject();
138
139     if (mavenRemoteRepositories == null || mavenRemoteRepositories.isEmpty()) return;
140
141     MavenRepositoriesHolder.getInstance(myProject).update(mavenRemoteRepositories);
142
143     MavenProjectIndicesManager.getInstance(myProject).scheduleUpdateIndicesList(new Consumer<List<MavenIndex>>() {
144       @Override
145       public void consume(List<MavenIndex> indexes) {
146         if(myProject.isDisposed()) return;
147         for (MavenIndex mavenIndex : indexes) {
148           if (mavenIndex.getUpdateTimestamp() == -1 &&
149               MavenRepositoriesHolder.getInstance(myProject).contains(mavenIndex.getRepositoryId())) {
150             MavenProjectIndicesManager.getInstance(myProject).scheduleUpdate(Collections.singletonList(mavenIndex));
151           }
152         }
153       }
154     });
155   }
156
157   @NotNull
158   private static Collection<? extends GrClosableBlock> findClosableBlocks(@NotNull final PsiElement element,
159                                                                           @NotNull final String... blockNames) {
160     List<GrMethodCall> methodCalls = PsiTreeUtil.getChildrenOfTypeAsList(element, GrMethodCall.class);
161     return ContainerUtil.mapNotNull(methodCalls, new Function<GrMethodCall, GrClosableBlock>() {
162       @Override
163       public GrClosableBlock fun(GrMethodCall call) {
164         if (call == null || call.getClosureArguments().length != 1) return null;
165
166         GrExpression expression = call.getInvokedExpression();
167         return expression != null && ArrayUtil.contains(expression.getText(), blockNames) ? call.getClosureArguments()[0] : null;
168       }
169     });
170   }
171
172   @NotNull
173   private static Collection<? extends MavenRemoteRepository> findMavenRemoteRepositories(@Nullable GrClosableBlock repositoriesBlock) {
174     Set<MavenRemoteRepository> myRemoteRepositories = ContainerUtil.newHashSet();
175     for (GrMethodCall repo : PsiTreeUtil
176       .getChildrenOfTypeAsList(repositoriesBlock, GrMethodCall.class)) {
177       if (repo.getInvokedExpression() == null) continue;
178
179       final String expressionText = repo.getInvokedExpression().getText();
180       if ("mavenCentral".equals(expressionText)) {
181         myRemoteRepositories.add(mavenCentralRemoteRepository);
182       }
183       else if ("mavenRepo".equals(expressionText)) {
184         for (GrNamedArgument namedArgument : repo.getNamedArguments()) {
185           if ("url".equals(namedArgument.getLabelName())) {
186             URI urlArgumentValue = resolveUriFromSimpleExpression(namedArgument.getExpression());
187             if (urlArgumentValue != null) {
188               String textUri = urlArgumentValue.toString();
189               myRemoteRepositories.add(new MavenRemoteRepository(textUri, null, textUri, null, null, null));
190             }
191             break;
192           }
193         }
194       }
195       else if ("maven".equals(expressionText) && repo.getClosureArguments().length > 0) {
196         List<GrApplicationStatement> applicationStatementList =
197           PsiTreeUtil.getChildrenOfTypeAsList(repo.getClosureArguments()[0], GrApplicationStatement.class);
198         if (!applicationStatementList.isEmpty()) {
199           GrApplicationStatement statement = applicationStatementList.get(0);
200           if (statement == null) continue;
201           GrExpression expression = statement.getInvokedExpression();
202           if (expression == null) continue;
203
204           if ("url".equals(expression.getText())) {
205             URI urlArgumentValue = resolveUriFromSimpleExpression(statement.getExpressionArguments()[0]);
206             if (urlArgumentValue != null) {
207               String textUri = urlArgumentValue.toString();
208               myRemoteRepositories.add(new MavenRemoteRepository(textUri, null, textUri, null, null, null));
209             }
210           }
211         }
212
213         List<GrAssignmentExpression> assignmentExpressionList =
214           PsiTreeUtil.getChildrenOfTypeAsList(repo.getClosureArguments()[0], GrAssignmentExpression.class);
215         if (!assignmentExpressionList.isEmpty()) {
216           GrAssignmentExpression statement = assignmentExpressionList.get(0);
217           if (statement == null) continue;
218           GrExpression expression = statement.getLValue();
219
220           if ("url".equals(expression.getText())) {
221             URI urlArgumentValue = resolveUriFromSimpleExpression(statement.getRValue());
222             if (urlArgumentValue != null) {
223               String textUri = urlArgumentValue.toString();
224               myRemoteRepositories.add(new MavenRemoteRepository(textUri, null, textUri, null, null, null));
225             }
226           }
227         }
228       }
229     }
230
231     return myRemoteRepositories;
232   }
233
234   @Nullable
235   private static URI resolveUriFromSimpleExpression(@Nullable GrExpression expression) {
236     if (expression == null) return null;
237
238     try {
239       if (expression instanceof PsiLiteral) {
240         URI uri = new URI(String.valueOf(PsiLiteral.class.cast(expression).getValue()));
241         if (uri.getScheme() != null && StringUtil.startsWith(uri.getScheme(), "http")) return uri;
242       }
243     }
244     catch (URISyntaxException ignored) {
245       // ignore it
246     }
247
248     try {
249       PsiReference reference = expression.getReference();
250       if (reference == null) return null;
251       PsiElement element = reference.resolve();
252       if (element instanceof GrVariable) {
253         List<GrLiteral> grLiterals = PsiTreeUtil.getChildrenOfTypeAsList(element, GrLiteral.class);
254         if (grLiterals.isEmpty()) return null;
255         URI uri = new URI(String.valueOf(grLiterals.get(0).getValue()));
256         if (uri.getScheme() != null && StringUtil.startsWith("http", uri.getScheme())) return uri;
257       }
258     }
259     catch (URISyntaxException ignored) {
260       // ignore it
261     }
262
263     return null;
264   }
265 }