com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl.java

Source

/*
 * 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 com.intellij.ide.util.projectWizard.importSources.impl;

import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.importProject.LibraryDescriptor;
import com.intellij.ide.util.importProject.ModuleDescriptor;
import com.intellij.ide.util.importProject.ModuleInsight;
import com.intellij.ide.util.importProject.ProjectDescriptor;
import com.intellij.ide.util.newProjectWizard.modes.ImportImlMode;
import com.intellij.ide.util.projectWizard.ExistingModuleLoader;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
import com.intellij.ide.util.projectWizard.importSources.ProjectFromSourcesBuilder;
import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleWithNameAlreadyExists;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.roots.types.BinariesOrderRootType;
import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.ModifiableArtifactModel;
import com.intellij.projectImport.ProjectImportBuilder;
import com.intellij.util.containers.MultiMap;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.mustbe.consulo.roots.impl.ProductionContentFolderTypeProvider;
import org.mustbe.consulo.roots.impl.TestContentFolderTypeProvider;

import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.util.*;

/**
 * @author Eugene Zhuravlev
 *         Date: Jul 17, 2007
 */
public class ProjectFromSourcesBuilderImpl extends ProjectImportBuilder implements ProjectFromSourcesBuilder {
    private static final Logger LOG = Logger
            .getInstance("#com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl");
    private static final String NAME = "Existing Sources";
    private String myBaseProjectPath;
    private final List<ProjectConfigurationUpdater> myUpdaters = new ArrayList<ProjectConfigurationUpdater>();
    private final Map<ProjectStructureDetector, ProjectDescriptor> myProjectDescriptors = new LinkedHashMap<ProjectStructureDetector, ProjectDescriptor>();
    private MultiMap<ProjectStructureDetector, DetectedProjectRoot> myRoots = MultiMap.emptyInstance();
    private final WizardContext myContext;
    private final ModulesProvider myModulesProvider;
    private Set<String> myModuleNames;
    private Set<String> myProjectLibrariesNames;

    public ProjectFromSourcesBuilderImpl(WizardContext context, ModulesProvider modulesProvider) {
        myContext = context;
        myModulesProvider = modulesProvider;
        for (ProjectStructureDetector detector : ProjectStructureDetector.EP_NAME.getExtensions()) {
            myProjectDescriptors.put(detector, new ProjectDescriptor());
        }
    }

    @NotNull
    @Override
    public Set<String> getExistingModuleNames() {
        if (myModuleNames == null) {
            myModuleNames = new HashSet<String>();
            for (Module module : myModulesProvider.getModules()) {
                myModuleNames.add(module.getName());
            }
        }
        return myModuleNames;
    }

    @NotNull
    @Override
    public Set<String> getExistingProjectLibraryNames() {
        if (myProjectLibrariesNames == null) {
            myProjectLibrariesNames = new HashSet<String>();
            final LibrariesContainer container = LibrariesContainerFactory.createContainer(myContext,
                    myModulesProvider);
            for (Library library : container.getLibraries(LibrariesContainer.LibraryLevel.PROJECT)) {
                myProjectLibrariesNames.add(library.getName());
            }
        }
        return myProjectLibrariesNames;
    }

    @NotNull
    @Override
    public WizardContext getContext() {
        return myContext;
    }

    public void setBaseProjectPath(final String contentRootPath) {
        myBaseProjectPath = contentRootPath;
    }

    @Override
    public String getBaseProjectPath() {
        return myBaseProjectPath;
    }

    public void setProjectRoots(MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots) {
        myRoots = roots;
    }

    @NotNull
    @Override
    public Collection<DetectedProjectRoot> getProjectRoots(@NotNull ProjectStructureDetector detector) {
        return myRoots.get(detector);
    }

    @NotNull
    @Override
    public String getName() {
        return NAME;
    }

    @Override
    public Icon getIcon() {
        return AllIcons.Nodes.Folder;
    }

    @Override
    public List getList() {
        return null;
    }

    @Override
    public boolean isMarked(Object element) {
        return false;
    }

    @Override
    public void setList(List list) throws ConfigurationException {
    }

    @Override
    public void setOpenProjectSettingsAfter(boolean on) {
    }

    public void setFileToImport(String path) {
        setBaseProjectPath(path);
    }

    public List<Module> commit(final Project project, final ModifiableModuleModel model,
            final ModulesProvider modulesProvider) {
        final boolean fromProjectStructure = model != null;
        ModifiableModelsProvider modelsProvider = new IdeaModifiableModelsProvider();
        final LibraryTable.ModifiableModel projectLibraryTable = modelsProvider
                .getLibraryTableModifiableModel(project);
        final Map<LibraryDescriptor, Library> projectLibs = new HashMap<LibraryDescriptor, Library>();
        final List<Module> result = new ArrayList<Module>();
        try {
            AccessToken token = WriteAction.start();
            try {
                // create project-level libraries
                for (ProjectDescriptor projectDescriptor : getSelectedDescriptors()) {
                    for (LibraryDescriptor lib : projectDescriptor.getLibraries()) {
                        final Collection<File> files = lib.getJars();
                        final Library projectLib = projectLibraryTable.createLibrary(lib.getName());
                        final Library.ModifiableModel libraryModel = projectLib.getModifiableModel();
                        for (File file : files) {
                            libraryModel.addRoot(VfsUtil.getUrlForLibraryRoot(file),
                                    BinariesOrderRootType.getInstance());
                        }
                        libraryModel.commit();
                        projectLibs.put(lib, projectLib);
                    }
                }
                if (!fromProjectStructure) {
                    projectLibraryTable.commit();
                }
            } finally {
                token.finish();
            }
        } catch (Exception e) {
            LOG.info(e);
            Messages.showErrorDialog(IdeBundle.message("error.adding.module.to.project", e.getMessage()),
                    IdeBundle.message("title.add.module"));
        }

        final Map<ModuleDescriptor, Module> descriptorToModuleMap = new HashMap<ModuleDescriptor, Module>();

        try {
            AccessToken token = WriteAction.start();
            try {
                final ModifiableModuleModel moduleModel = fromProjectStructure ? model
                        : ModuleManager.getInstance(project).getModifiableModel();
                for (ProjectDescriptor descriptor : getSelectedDescriptors()) {
                    for (final ModuleDescriptor moduleDescriptor : descriptor.getModules()) {
                        final Module module;
                        if (moduleDescriptor.isReuseExistingElement()) {
                            final ExistingModuleLoader moduleLoader = ImportImlMode.setUpLoader(
                                    FileUtil.toSystemIndependentName(moduleDescriptor.computeModuleDir()));
                            module = moduleLoader.createModule(moduleModel);
                        } else {
                            module = createModule(descriptor, moduleDescriptor, projectLibs, moduleModel);
                        }
                        result.add(module);
                        descriptorToModuleMap.put(moduleDescriptor, module);
                    }
                }

                if (!fromProjectStructure) {
                    moduleModel.commit();
                }
            } finally {
                token.finish();
            }
        } catch (Exception e) {
            LOG.info(e);
            Messages.showErrorDialog(IdeBundle.message("error.adding.module.to.project", e.getMessage()),
                    IdeBundle.message("title.add.module"));
        }

        // setup dependencies between modules
        try {
            AccessToken token = WriteAction.start();
            try {
                for (ProjectDescriptor data : getSelectedDescriptors()) {
                    for (final ModuleDescriptor descriptor : data.getModules()) {
                        final Module module = descriptorToModuleMap.get(descriptor);
                        if (module == null) {
                            continue;
                        }
                        final Set<ModuleDescriptor> deps = descriptor.getDependencies();
                        if (deps.size() == 0) {
                            continue;
                        }
                        final ModifiableRootModel rootModel = ModuleRootManager.getInstance(module)
                                .getModifiableModel();
                        for (ModuleDescriptor dependentDescriptor : deps) {
                            final Module dependentModule = descriptorToModuleMap.get(dependentDescriptor);
                            if (dependentModule != null) {
                                rootModel.addModuleOrderEntry(dependentModule);
                            }
                        }
                        rootModel.commit();
                    }
                }
            } finally {
                token.finish();
            }
        } catch (Exception e) {
            LOG.info(e);
            Messages.showErrorDialog(IdeBundle.message("error.adding.module.to.project", e.getMessage()),
                    IdeBundle.message("title.add.module"));
        }

        AccessToken token = WriteAction.start();
        try {
            ModulesProvider updatedModulesProvider = fromProjectStructure ? modulesProvider
                    : new DefaultModulesProvider(project);
            for (ProjectConfigurationUpdater updater : myUpdaters) {
                updater.updateProject(project, modelsProvider, updatedModulesProvider);
            }
        } finally {
            token.finish();
        }

        return result;
    }

    @Nullable
    @Override
    public List<Module> commit(Project project, ModifiableModuleModel model, ModulesProvider modulesProvider,
            ModifiableArtifactModel artifactModel) {
        return commit(project, model, modulesProvider);
    }

    public Collection<ProjectDescriptor> getSelectedDescriptors() {
        return myProjectDescriptors.values();
    }

    public void addConfigurationUpdater(ProjectConfigurationUpdater updater) {
        myUpdaters.add(updater);
    }

    public boolean hasRootsFromOtherDetectors(ProjectStructureDetector thisDetector) {
        for (ProjectStructureDetector projectStructureDetector : Extensions
                .getExtensions(ProjectStructureDetector.EP_NAME)) {
            if (projectStructureDetector != thisDetector && !getProjectRoots(projectStructureDetector).isEmpty()) {
                return true;
            }
        }
        return false;
    }

    @NotNull
    private static Module createModule(ProjectDescriptor projectDescriptor, final ModuleDescriptor descriptor,
            final Map<LibraryDescriptor, Library> projectLibs, final ModifiableModuleModel moduleModel)
            throws InvalidDataException, IOException, ModuleWithNameAlreadyExists, JDOMException,
            ConfigurationException {

        final Module module = moduleModel.newModule(descriptor.getName(), descriptor.computeModuleDir());
        final ModifiableRootModel modifiableModel = ModuleRootManager.getInstance(module).getModifiableModel();
        setupRootModel(projectDescriptor, descriptor, modifiableModel, projectLibs);
        descriptor.updateModuleConfiguration(module, modifiableModel);
        modifiableModel.commit();
        return module;
    }

    private static void setupRootModel(ProjectDescriptor projectDescriptor, final ModuleDescriptor descriptor,
            final ModifiableRootModel rootModel, final Map<LibraryDescriptor, Library> projectLibs) {

        final Set<File> contentRoots = descriptor.getContentRoots();
        for (File contentRoot : contentRoots) {
            final LocalFileSystem lfs = LocalFileSystem.getInstance();
            VirtualFile moduleContentRoot = lfs
                    .refreshAndFindFileByPath(FileUtil.toSystemIndependentName(contentRoot.getPath()));
            if (moduleContentRoot != null) {
                final ContentEntry contentEntry = rootModel.addContentEntry(moduleContentRoot);
                final Collection<DetectedProjectRoot> sourceRoots = descriptor.getSourceRoots(contentRoot);
                for (DetectedProjectRoot srcRoot : sourceRoots) {
                    final String srcpath = FileUtil.toSystemIndependentName(srcRoot.getDirectory().getPath());
                    final VirtualFile sourceRoot = lfs.refreshAndFindFileByPath(srcpath);
                    if (sourceRoot != null) {
                        contentEntry.addFolder(sourceRoot,
                                shouldBeTestRoot(srcRoot.getDirectory())
                                        ? TestContentFolderTypeProvider.getInstance()
                                        : ProductionContentFolderTypeProvider.getInstance());
                    }
                }
            }
        }

        final LibraryTable moduleLibraryTable = rootModel.getModuleLibraryTable();
        for (LibraryDescriptor libDescriptor : ModuleInsight.getLibraryDependencies(descriptor,
                projectDescriptor.getLibraries())) {
            final Library projectLib = projectLibs.get(libDescriptor);
            if (projectLib != null) {
                rootModel.addLibraryEntry(projectLib);
            } else {
                // add as module library
                final Collection<File> jars = libDescriptor.getJars();
                for (File file : jars) {
                    Library library = moduleLibraryTable.createLibrary();
                    Library.ModifiableModel modifiableModel = library.getModifiableModel();
                    modifiableModel.addRoot(VfsUtil.getUrlForLibraryRoot(file),
                            BinariesOrderRootType.getInstance());
                    modifiableModel.commit();
                }
            }
        }

    }

    @NotNull
    @Override
    public ProjectDescriptor getProjectDescriptor(@NotNull ProjectStructureDetector detector) {
        return myProjectDescriptors.get(detector);
    }

    private static boolean shouldBeTestRoot(final File srcRoot) {
        if (isTestRootName(srcRoot.getName())) {
            return true;
        }
        final File parentFile = srcRoot.getParentFile();
        return parentFile != null && isTestRootName(parentFile.getName());
    }

    private static boolean isTestRootName(final String name) {
        return "test".equalsIgnoreCase(name) || "tests".equalsIgnoreCase(name)
                || "testSource".equalsIgnoreCase(name) || "testSources".equalsIgnoreCase(name)
                || "testSrc".equalsIgnoreCase(name);
    }

    public interface ProjectConfigurationUpdater {
        void updateProject(@NotNull Project project, @NotNull ModifiableModelsProvider modelsProvider,
                @NotNull ModulesProvider modulesProvider);
    }

    @Override
    public boolean isSuitableSdkType(final SdkTypeId sdkTypeId) {

        return true;
    }
}