when gradle/maven project is opened in headless mode (e.g. to run offline inspections...
[idea/community.git] / java / idea-ui / src / com / intellij / projectImport / ProjectOpenProcessorBase.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 com.intellij.projectImport;
17
18 import com.intellij.CommonBundle;
19 import com.intellij.ide.IdeBundle;
20 import com.intellij.ide.highlighter.ProjectFileType;
21 import com.intellij.ide.impl.NewProjectUtil;
22 import com.intellij.ide.impl.ProjectUtil;
23 import com.intellij.ide.util.projectWizard.WizardContext;
24 import com.intellij.openapi.application.ApplicationManager;
25 import com.intellij.openapi.components.StorageScheme;
26 import com.intellij.openapi.project.Project;
27 import com.intellij.openapi.project.ProjectManager;
28 import com.intellij.openapi.project.ex.ProjectManagerEx;
29 import com.intellij.openapi.projectRoots.JavaSdk;
30 import com.intellij.openapi.projectRoots.ProjectJdkTable;
31 import com.intellij.openapi.projectRoots.Sdk;
32 import com.intellij.openapi.roots.CompilerProjectExtension;
33 import com.intellij.openapi.roots.ProjectRootManager;
34 import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
35 import com.intellij.openapi.ui.Messages;
36 import com.intellij.openapi.util.io.FileUtil;
37 import com.intellij.openapi.util.text.StringUtil;
38 import com.intellij.openapi.vfs.VfsUtilCore;
39 import com.intellij.openapi.vfs.VirtualFile;
40 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
41 import org.jetbrains.annotations.NonNls;
42 import org.jetbrains.annotations.NotNull;
43 import org.jetbrains.annotations.Nullable;
44
45 import javax.swing.*;
46 import java.io.File;
47 import java.io.IOException;
48 import java.util.Arrays;
49 import java.util.Collection;
50
51 /**
52  * @author anna
53  * @since 12-Jul-2007
54  */
55 public abstract class ProjectOpenProcessorBase<T extends ProjectImportBuilder> extends ProjectOpenProcessor {
56   private final T myBuilder;
57
58   protected ProjectOpenProcessorBase(@NotNull final T builder) {
59     myBuilder = builder;
60   }
61
62   public String getName() {
63     return getBuilder().getName();
64   }
65
66   @Nullable
67   public Icon getIcon() {
68     return getBuilder().getIcon();
69   }
70
71   public boolean canOpenProject(final VirtualFile file) {
72     final String[] supported = getSupportedExtensions();
73     if (supported != null) {
74       if (file.isDirectory()) {
75         for (VirtualFile child : getFileChildren(file)) {
76           if (canOpenFile(child, supported)) return true;
77         }
78         return false;
79       }
80       if (canOpenFile(file, supported)) return true;
81     }
82     return false;
83   }
84
85   private static Collection<VirtualFile> getFileChildren(VirtualFile file) {
86     if (file instanceof NewVirtualFile) {
87       return ((NewVirtualFile)file).getCachedChildren();
88     }
89
90     return Arrays.asList(file.getChildren());
91   }
92
93   protected static boolean canOpenFile(VirtualFile file, String[] supported) {
94     final String fileName = file.getName();
95     for (String name : supported) {
96       if (fileName.equals(name)) {
97         return true;
98       }
99     }
100     return false;
101   }
102
103   protected boolean doQuickImport(VirtualFile file, final WizardContext wizardContext) {
104     return false;
105   }
106
107   @NotNull
108   public T getBuilder() {
109     return myBuilder;
110   }
111
112   @Nullable
113   public abstract String[] getSupportedExtensions();
114
115   @Nullable
116   public Project doOpenProject(@NotNull VirtualFile virtualFile, Project projectToClose, boolean forceOpenInNewFrame) {
117     try {
118       getBuilder().setUpdate(false);
119       final WizardContext wizardContext = new WizardContext(null);
120       if (virtualFile.isDirectory()) {
121         final String[] supported = getSupportedExtensions();
122         for (VirtualFile file : getFileChildren(virtualFile)) {
123           if (canOpenFile(file, supported)) {
124             virtualFile = file;
125             break;
126           }
127         }
128       }
129
130       wizardContext.setProjectFileDirectory(virtualFile.getParent().getPath());
131
132       if (!doQuickImport(virtualFile, wizardContext)) return null;
133
134       if (wizardContext.getProjectName() == null) {
135         if (wizardContext.getProjectStorageFormat() == StorageScheme.DEFAULT) {
136           wizardContext.setProjectName(IdeBundle.message("project.import.default.name", getName()) + ProjectFileType.DOT_DEFAULT_EXTENSION);
137         }
138         else {
139           wizardContext.setProjectName(IdeBundle.message("project.import.default.name.dotIdea", getName()));
140         }
141       }
142
143       Project defaultProject = ProjectManager.getInstance().getDefaultProject();
144       Sdk jdk = ProjectRootManager.getInstance(defaultProject).getProjectSdk();
145       if (jdk == null) {
146         jdk = ProjectJdkTable.getInstance().findMostRecentSdkOfType(JavaSdk.getInstance());
147       }
148       wizardContext.setProjectJdk(jdk);
149
150       final String dotIdeaFilePath = wizardContext.getProjectFileDirectory() + File.separator + Project.DIRECTORY_STORE_FOLDER;
151       final String projectFilePath = wizardContext.getProjectFileDirectory() + File.separator + wizardContext.getProjectName() +
152                                      ProjectFileType.DOT_DEFAULT_EXTENSION;
153
154       File dotIdeaFile = new File(dotIdeaFilePath);
155       File projectFile = new File(projectFilePath);
156
157       String pathToOpen;
158       if (wizardContext.getProjectStorageFormat() == StorageScheme.DEFAULT) {
159         pathToOpen = projectFilePath;
160       } else {
161         pathToOpen = dotIdeaFile.getParent();
162       }
163
164       boolean shouldOpenExisting = false;
165       boolean importToProject = false;
166       if (projectFile.exists() || dotIdeaFile.exists()) {
167         if (ApplicationManager.getApplication().isHeadlessEnvironment()) {
168           shouldOpenExisting = true;
169           importToProject = true;
170         }
171         else {
172           String existingName;
173           if (dotIdeaFile.exists()) {
174             existingName = "an existing project";
175             pathToOpen = dotIdeaFile.getParent();
176           }
177           else {
178             existingName = "'" + projectFile.getName() + "'";
179             pathToOpen = projectFilePath;
180           }
181           int result = Messages.showYesNoCancelDialog(
182             projectToClose,
183             IdeBundle.message("project.import.open.existing", existingName, projectFile.getParent(), virtualFile.getName()),
184             IdeBundle.message("title.open.project"),
185             IdeBundle.message("project.import.open.existing.openExisting"),
186             IdeBundle.message("project.import.open.existing.reimport"),
187             CommonBundle.message("button.cancel"),
188             Messages.getQuestionIcon());
189           if (result == Messages.CANCEL) return null;
190           shouldOpenExisting = result == Messages.YES;
191           importToProject = !shouldOpenExisting;
192         }
193       }
194
195       final Project projectToOpen;
196       if (shouldOpenExisting) {
197         try {
198           projectToOpen = ProjectManagerEx.getInstanceEx().loadProject(pathToOpen);
199         }
200         catch (Exception e) {
201           return null;
202         }
203       }
204       else {
205         projectToOpen = ProjectManagerEx.getInstanceEx().newProject(wizardContext.getProjectName(), pathToOpen, true, false);
206       }
207       if (projectToOpen == null) return null;
208
209       if (importToProject) {
210         if (!getBuilder().validate(projectToClose, projectToOpen)) {
211           return null;
212         }
213
214         projectToOpen.save();
215
216         ApplicationManager.getApplication().runWriteAction(new Runnable() {
217           @Override
218           public void run() {
219             Sdk jdk = wizardContext.getProjectJdk();
220             if (jdk != null) {
221               NewProjectUtil.applyJdkToProject(projectToOpen, jdk);
222             }
223
224             String projectDirPath = wizardContext.getProjectFileDirectory();
225             String path = StringUtil.endsWithChar(projectDirPath, '/') ? projectDirPath + "classes" : projectDirPath + "/classes";
226             CompilerProjectExtension extension = CompilerProjectExtension.getInstance(projectToOpen);
227             if (extension != null) {
228               extension.setCompilerOutputUrl(getUrl(path));
229             }
230           }
231         });
232
233         getBuilder().commit(projectToOpen, null, ModulesProvider.EMPTY_MODULES_PROVIDER);
234       }
235
236       if (!forceOpenInNewFrame) {
237         NewProjectUtil.closePreviousProject(projectToClose);
238       }
239       ProjectUtil.updateLastProjectLocation(pathToOpen);
240       ProjectManagerEx.getInstanceEx().openProject(projectToOpen);
241
242       return projectToOpen;
243     }
244     finally {
245       getBuilder().cleanup();
246     }
247   }
248
249   public static String getUrl(@NonNls String path) {
250     try {
251       path = FileUtil.resolveShortWindowsName(path);
252     }
253     catch (IOException ignored) { }
254     return VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(path));
255   }
256 }