blob: 1b40dfadccee08318ba513da96aad029cadb838b [file] [log] [blame]
/*
* Copyright 2000-2012 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.
*/
package org.jetbrains.idea.maven.importing;
import com.intellij.ide.util.projectWizard.importSources.JavaModuleSourceRoot;
import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetectionUtil;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.SourceFolder;
import com.intellij.openapi.roots.impl.ModifiableModelCommitter;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PairConsumer;
import com.intellij.util.containers.LinkedMultiMap;
import com.intellij.util.containers.MultiMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.model.MavenResource;
import org.jetbrains.idea.maven.project.MavenImportingSettings;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
import org.jetbrains.jps.model.java.JavaResourceRootType;
import org.jetbrains.jps.model.java.JavaSourceRootProperties;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class MavenFoldersImporter {
private final MavenProject myMavenProject;
private final MavenImportingSettings myImportingSettings;
private final MavenRootModelAdapter myModel;
public static void updateProjectFolders(final Project project, final boolean updateTargetFoldersOnly) {
final MavenProjectsManager manager = MavenProjectsManager.getInstance(project);
final MavenImportingSettings settings = manager.getImportingSettings();
AccessToken accessToken = WriteAction.start();
try {
List<ModifiableRootModel> rootModels = new ArrayList<ModifiableRootModel>();
for (Module each : ModuleManager.getInstance(project).getModules()) {
MavenProject mavenProject = manager.findProject(each);
if (mavenProject == null) continue;
MavenRootModelAdapter a = new MavenRootModelAdapter(mavenProject, each, new MavenDefaultModifiableModelsProvider(project));
new MavenFoldersImporter(mavenProject, settings, a).config(updateTargetFoldersOnly);
ModifiableRootModel model = a.getRootModel();
if (model.isChanged()) {
rootModels.add(model);
}
else {
model.dispose();
}
}
if (!rootModels.isEmpty()) {
ModifiableRootModel[] modelsArray = rootModels.toArray(new ModifiableRootModel[rootModels.size()]);
if (modelsArray.length > 0) {
ModifiableModelCommitter.multiCommit(modelsArray, ModuleManager.getInstance(modelsArray[0].getProject()).getModifiableModel());
}
}
}
finally {
accessToken.finish();
}
}
public MavenFoldersImporter(MavenProject mavenProject, MavenImportingSettings settings, MavenRootModelAdapter model) {
myMavenProject = mavenProject;
myImportingSettings = settings;
myModel = model;
}
public void config() {
config(false);
}
private void config(boolean updateTargetFoldersOnly) {
if (!updateTargetFoldersOnly) {
if (!myImportingSettings.isKeepSourceFolders()) {
myModel.clearSourceFolders();
}
configSourceFolders();
configOutputFolders();
}
configGeneratedAndExcludedFolders();
}
private void configSourceFolders() {
final MultiMap<JpsModuleSourceRootType<?>, String> roots = new LinkedMultiMap<JpsModuleSourceRootType<?>, String>();
roots.putValues(JavaSourceRootType.SOURCE, myMavenProject.getSources());
roots.putValues(JavaSourceRootType.TEST_SOURCE, myMavenProject.getTestSources());
for (MavenImporter each : MavenImporter.getSuitableImporters(myMavenProject)) {
each.collectSourceRoots(myMavenProject, new PairConsumer<String, JpsModuleSourceRootType<?>>() {
@Override
public void consume(String s, JpsModuleSourceRootType<?> type) {
roots.putValue(type, s);
}
});
}
for (MavenResource each : myMavenProject.getResources()) {
roots.putValue(JavaResourceRootType.RESOURCE, each.getDirectory());
}
for (MavenResource each : myMavenProject.getTestResources()) {
roots.putValue(JavaResourceRootType.TEST_RESOURCE, each.getDirectory());
}
addBuilderHelperPaths("add-source", roots.getModifiable(JavaSourceRootType.SOURCE));
addBuilderHelperPaths("add-test-source", roots.getModifiable(JavaSourceRootType.TEST_SOURCE));
List<String> addedPaths = new ArrayList<String>();
for (JpsModuleSourceRootType<?> type : roots.keySet()) {
for (String path : roots.get(type)) {
addSourceFolderIfNotOverlap(path, type, addedPaths);
}
}
}
private void addBuilderHelperPaths(String goal, Collection<String> folders) {
final Element configurationElement = myMavenProject.getPluginGoalConfiguration("org.codehaus.mojo", "build-helper-maven-plugin", goal);
if (configurationElement != null) {
final Element sourcesElement = configurationElement.getChild("sources");
if (sourcesElement != null) {
for (Element element : sourcesElement.getChildren()) {
folders.add(element.getTextTrim());
}
}
}
}
private void addSourceFolderIfNotOverlap(String path, JpsModuleSourceRootType<?> type, List<String> addedPaths) {
String canonicalPath = myModel.toPath(path).getPath();
for (String existing : addedPaths) {
if (VfsUtilCore.isEqualOrAncestor(existing, canonicalPath)
|| VfsUtilCore.isEqualOrAncestor(canonicalPath, existing)) {
return;
}
}
addedPaths.add(canonicalPath);
myModel.addSourceFolder(canonicalPath, type);
}
private void configOutputFolders() {
if (myImportingSettings.isUseMavenOutput()) {
myModel.useModuleOutput(myMavenProject.getOutputDirectory(),
myMavenProject.getTestOutputDirectory());
}
String buildDirPath = myModel.toPath(myMavenProject.getBuildDirectory()).getPath();
String outputDirPath = myModel.toPath(myMavenProject.getOutputDirectory()).getPath();
if ((!VfsUtilCore.isEqualOrAncestor(buildDirPath, outputDirPath))) {
myModel.addExcludedFolder(myMavenProject.getOutputDirectory());
}
String testOutputDirPath = myModel.toPath(myMavenProject.getTestOutputDirectory()).getPath();
if ((!VfsUtilCore.isEqualOrAncestor(buildDirPath, testOutputDirPath))) {
myModel.addExcludedFolder(myMavenProject.getTestOutputDirectory());
}
}
private void configGeneratedAndExcludedFolders() {
File targetDir = new File(myMavenProject.getBuildDirectory());
String generatedDir = myMavenProject.getGeneratedSourcesDirectory(false);
String generatedDirTest = myMavenProject.getGeneratedSourcesDirectory(true);
myModel.unregisterAll(targetDir.getPath(), false, false);
if (myImportingSettings.getGeneratedSourcesFolder() != MavenImportingSettings.GeneratedSourcesFolder.IGNORE) {
myModel.addGeneratedJavaSourceFolder(myMavenProject.getAnnotationProcessorDirectory(true), JavaSourceRootType.TEST_SOURCE);
myModel.addGeneratedJavaSourceFolder(myMavenProject.getAnnotationProcessorDirectory(false), JavaSourceRootType.SOURCE);
}
File[] targetChildren = targetDir.listFiles();
if (targetChildren != null) {
for (File f : targetChildren) {
if (!f.isDirectory()) continue;
if (FileUtil.pathsEqual(generatedDir, f.getPath())) {
configGeneratedSourceFolder(f, JavaSourceRootType.SOURCE);
}
else if (FileUtil.pathsEqual(generatedDirTest, f.getPath())) {
configGeneratedSourceFolder(f, JavaSourceRootType.TEST_SOURCE);
}
else {
if (myImportingSettings.isExcludeTargetFolder()) {
if (myModel.hasRegisteredSourceSubfolder(f)) continue;
if (myModel.isAlreadyExcluded(f)) continue;
myModel.addExcludedFolder(f.getPath());
}
}
}
}
List<String> facetExcludes = new ArrayList<String>();
for (MavenImporter each : MavenImporter.getSuitableImporters(myMavenProject)) {
each.collectExcludedFolders(myMavenProject, facetExcludes);
}
for (String eachFolder : facetExcludes) {
myModel.unregisterAll(eachFolder, true, true);
myModel.addExcludedFolder(eachFolder);
}
if (myImportingSettings.isExcludeTargetFolder()) {
if (!myModel.hasRegisteredSourceSubfolder(targetDir)) {
myModel.addExcludedFolder(targetDir.getPath());
}
}
}
private void configGeneratedSourceFolder(@NotNull File targetDir, final JavaSourceRootType rootType) {
switch (myImportingSettings.getGeneratedSourcesFolder()) {
case GENERATED_SOURCE_FOLDER:
myModel.addGeneratedJavaSourceFolder(targetDir.getPath(), rootType);
break;
case SUBFOLDER:
addAllSubDirsAsGeneratedSources(targetDir, rootType);
break;
case AUTODETECT:
Collection<JavaModuleSourceRoot> sourceRoots = JavaSourceRootDetectionUtil.suggestRoots(targetDir);
for (JavaModuleSourceRoot root : sourceRoots) {
if (FileUtil.filesEqual(targetDir, root.getDirectory())) {
myModel.addGeneratedJavaSourceFolder(targetDir.getPath(), rootType);
return;
}
addAsGeneratedSourceFolder(root.getDirectory(), rootType);
}
addAllSubDirsAsGeneratedSources(targetDir, rootType);
break;
case IGNORE:
break; // Ignore.
}
}
private void addAsGeneratedSourceFolder(@NotNull File dir, final JavaSourceRootType rootType) {
SourceFolder folder = myModel.getSourceFolder(dir);
if (!myModel.hasRegisteredSourceSubfolder(dir) || folder != null && !isGenerated(folder)) {
myModel.addGeneratedJavaSourceFolder(dir.getPath(), rootType);
}
}
private static boolean isGenerated(@NotNull SourceFolder folder) {
JavaSourceRootProperties properties = folder.getJpsElement().getProperties(JavaModuleSourceRootTypes.SOURCES);
return properties != null && properties.isForGeneratedSources();
}
private void addAllSubDirsAsGeneratedSources(@NotNull File dir, final JavaSourceRootType rootType) {
for (File f : getChildren(dir)) {
if (f.isDirectory()) {
addAsGeneratedSourceFolder(f, rootType);
}
}
}
private static File[] getChildren(File dir) {
File[] result = dir.listFiles();
return result == null ? ArrayUtil.EMPTY_FILE_ARRAY : result;
}
}