All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jetbrains.idea.maven.importing.MavenRootModelAdapter Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition maven library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2013 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.openapi.application.AccessToken;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.ModuleOrderEntryImpl;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.util.Processor;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.model.MavenArtifact;
import org.jetbrains.idea.maven.model.MavenConstants;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.Path;
import org.jetbrains.idea.maven.utils.Url;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;

import java.io.File;
import java.util.Arrays;
import java.util.Set;

public class MavenRootModelAdapter {

  private final MavenProject myMavenProject;
  private final ModifiableModuleModel myModuleModel;
  private final ModifiableRootModel myRootModel;

  private final MavenSourceFoldersModuleExtension myRootModelModuleExtension;

  private final Set myOrderEntriesBeforeJdk = new THashSet();

  public MavenRootModelAdapter(@NotNull MavenProject p, @NotNull Module module, final MavenModifiableModelsProvider rootModelsProvider) {
    myMavenProject = p;
    myModuleModel = rootModelsProvider.getModuleModel();
    myRootModel = rootModelsProvider.getRootModel(module);

    myRootModelModuleExtension = myRootModel.getModuleExtension(MavenSourceFoldersModuleExtension.class);
    myRootModelModuleExtension.init(module, myRootModel);
  }

  public void init(boolean isNewlyCreatedModule) {
    setupInitialValues(isNewlyCreatedModule);
    initContentRoots();
    initOrderEntries();
  }

  private void setupInitialValues(boolean newlyCreatedModule) {
    if (newlyCreatedModule || myRootModel.getSdk() == null) {
      myRootModel.inheritSdk();
    }
    if (newlyCreatedModule) {
      getCompilerExtension().setExcludeOutput(true);
    }
  }

  private void initContentRoots() {
    Url url = toUrl(myMavenProject.getDirectory());
    if (getContentRootFor(url) != null) return;
    myRootModel.addContentEntry(url.getUrl());
  }

  private ContentEntry getContentRootFor(Url url) {
    for (ContentEntry e : myRootModel.getContentEntries()) {
      if (VfsUtilCore.isEqualOrAncestor(e.getUrl(), url.getUrl())) return e;
    }
    return null;
  }

  private void initOrderEntries() {
    boolean jdkProcessed = false;

    for (OrderEntry e : myRootModel.getOrderEntries()) {
      if (e instanceof ModuleSourceOrderEntry || e instanceof JdkOrderEntry) {
        jdkProcessed = true;
        continue;
      }

      if (e instanceof LibraryOrderEntry) {
        if (!isMavenLibrary(((LibraryOrderEntry)e).getLibrary())) continue;
      }
      if (e instanceof ModuleOrderEntry) {
        Module m = ((ModuleOrderEntry)e).getModule();
        if (m != null && !MavenProjectsManager.getInstance(myRootModel.getProject()).isMavenizedModule(m)) continue;
      }

      if (!jdkProcessed) {
        if (e instanceof ModuleOrderEntry) {
          myOrderEntriesBeforeJdk.add(((ModuleOrderEntry)e).getModuleName());
        }
        else if (e instanceof LibraryOrderEntry) {
          myOrderEntriesBeforeJdk.add(((LibraryOrderEntry)e).getLibraryName());
        }
      }

      myRootModel.removeOrderEntry(e);
    }
  }

  public ModifiableRootModel getRootModel() {
    return myRootModel;
  }

  @NotNull
  public String[] getSourceRootUrls(boolean includingTests) {
    return myRootModelModuleExtension.getSourceRootUrls(includingTests);
  }

  public Module getModule() {
    return myRootModel.getModule();
  }

  public void clearSourceFolders() {
    myRootModelModuleExtension.clearSourceFolders();
  }

  public 

void addSourceFolder(String path, final JpsModuleSourceRootType

rootType) { addSourceFolder(path, rootType, false, rootType.createDefaultProperties()); } public void addGeneratedJavaSourceFolder(String path, JavaSourceRootType rootType) { addSourceFolder(path, rootType, true, JpsJavaExtensionService.getInstance().createSourceRootProperties("", true)); } private

void addSourceFolder(@NotNull String path, final @NotNull JpsModuleSourceRootType

rootType, boolean ifNotEmpty, final @NotNull P properties) { if (ifNotEmpty) { String[] childs = new File(toPath(path).getPath()).list(); if (childs == null || childs.length == 0) return; } else { if (!exists(path)) return; } Url url = toUrl(path); myRootModelModuleExtension.addSourceFolder(url, rootType, properties); } public boolean hasRegisteredSourceSubfolder(@NotNull File f) { String url = toUrl(f.getPath()).getUrl(); return myRootModelModuleExtension.hasRegisteredSourceSubfolder(url); } @Nullable public SourceFolder getSourceFolder(File folder) { String url = toUrl(folder.getPath()).getUrl(); return myRootModelModuleExtension.getSourceFolder(url); } public boolean isAlreadyExcluded(File f) { String url = toUrl(f.getPath()).getUrl(); return VfsUtilCore.isUnder(url, Arrays.asList(myRootModel.getExcludeRootUrls())); } private boolean exists(String path) { return new File(toPath(path).getPath()).exists(); } public void addExcludedFolder(String path) { unregisterAll(path, true, false); Url url = toUrl(path); ContentEntry e = getContentRootFor(url); if (e == null) return; if (e.getUrl().equals(url.getUrl())) return; e.addExcludeFolder(url.getUrl()); if (!Registry.is("ide.hide.excluded.files")) { Project project = myRootModel.getProject(); ChangeListManager.getInstance(project).addDirectoryToIgnoreImplicitly(toPath(path).getPath()); } } public void unregisterAll(String path, boolean under, boolean unregisterSources) { Url url = toUrl(path); for (ContentEntry eachEntry : myRootModel.getContentEntries()) { if (unregisterSources) { myRootModelModuleExtension.unregisterAll(url, under); } for (String excludedUrl : eachEntry.getExcludeFolderUrls()) { String ancestor = under ? url.getUrl() : excludedUrl; String child = under ? excludedUrl : url.getUrl(); if (VfsUtilCore.isEqualOrAncestor(ancestor, child)) { eachEntry.removeExcludeFolder(excludedUrl); } } for (String outputUrl : getCompilerExtension().getOutputRootUrls(true)) { String ancestor = under ? url.getUrl() : outputUrl; String child = under ? outputUrl : url.getUrl(); if (VfsUtilCore.isEqualOrAncestor(ancestor, child)) { getCompilerExtension().setExcludeOutput(false); } } } } public boolean hasCollision(String sourceRootPath) { Url url = toUrl(sourceRootPath); for (ContentEntry eachEntry : myRootModel.getContentEntries()) { for (SourceFolder eachFolder : eachEntry.getSourceFolders()) { String ancestor = url.getUrl(); String child = eachFolder.getUrl(); if (VfsUtilCore.isEqualOrAncestor(ancestor, child) || VfsUtilCore.isEqualOrAncestor(child, ancestor)) { return true; } } for (String excludeUrl : eachEntry.getExcludeFolderUrls()) { String ancestor = url.getUrl(); if (VfsUtilCore.isEqualOrAncestor(ancestor, excludeUrl) || VfsUtilCore.isEqualOrAncestor(excludeUrl, ancestor)) { return true; } } } return false; } public void useModuleOutput(String production, String test) { getCompilerExtension().inheritCompilerOutputPath(false); getCompilerExtension().setCompilerOutputPath(toUrl(production).getUrl()); getCompilerExtension().setCompilerOutputPathForTests(toUrl(test).getUrl()); } private CompilerModuleExtension getCompilerExtension() { return myRootModel.getModuleExtension(CompilerModuleExtension.class); } private Url toUrl(String path) { return toPath(path).toUrl(); } public Path toPath(String path) { if (!FileUtil.isAbsolute(path)) { path = new File(myMavenProject.getDirectory(), path).getPath(); } return new Path(path); } public void addModuleDependency(@NotNull String moduleName, @NotNull DependencyScope scope, boolean testJar) { Module m = findModuleByName(moduleName); ModuleOrderEntry e; if (m != null) { e = myRootModel.addModuleOrderEntry(m); } else { AccessToken accessToken = ReadAction.start(); try { e = myRootModel.addInvalidModuleEntry(moduleName); } finally { accessToken.finish(); } } e.setScope(scope); if (testJar) { ((ModuleOrderEntryImpl)e).setProductionOnTestDependency(true); } if (myOrderEntriesBeforeJdk.contains(moduleName)) { moveLastOrderEntryBeforeJdk(); } } @Nullable public Module findModuleByName(String moduleName) { return myModuleModel.findModuleByName(moduleName); } public void addSystemDependency(MavenArtifact artifact, DependencyScope scope) { assert MavenConstants.SCOPE_SYSTEM.equals(artifact.getScope()); String libraryName = artifact.getLibraryName(); Library library = myRootModel.getModuleLibraryTable().getLibraryByName(libraryName); if (library == null) { library = myRootModel.getModuleLibraryTable().createLibrary(libraryName); } LibraryOrderEntry orderEntry = myRootModel.findLibraryOrderEntry(library); assert orderEntry != null; orderEntry.setScope(scope); Library.ModifiableModel modifiableModel = library.getModifiableModel(); updateUrl(modifiableModel, OrderRootType.CLASSES, artifact, null, null, true); modifiableModel.commit(); if (myOrderEntriesBeforeJdk.contains(libraryName)) { moveLastOrderEntryBeforeJdk(); } } public void addLibraryDependency(MavenArtifact artifact, DependencyScope scope, MavenModifiableModelsProvider provider, MavenProject project) { assert !MavenConstants.SCOPE_SYSTEM.equals(artifact.getScope()); // System dependencies must be added ad module library, not as project wide library. String libraryName = artifact.getLibraryName(); Library library = provider.getLibraryByName(libraryName); if (library == null) { library = provider.createLibrary(libraryName); } Library.ModifiableModel libraryModel = provider.getLibraryModel(library); updateUrl(libraryModel, OrderRootType.CLASSES, artifact, null, null, true); updateUrl(libraryModel, OrderRootType.SOURCES, artifact, MavenExtraArtifactType.SOURCES, project, false); updateUrl(libraryModel, JavadocOrderRootType.getInstance(), artifact, MavenExtraArtifactType.DOCS, project, false); LibraryOrderEntry e = myRootModel.addLibraryEntry(library); e.setScope(scope); if (myOrderEntriesBeforeJdk.contains(libraryName)) { moveLastOrderEntryBeforeJdk(); } } private void moveLastOrderEntryBeforeJdk() { OrderEntry[] entries = myRootModel.getOrderEntries().clone(); int i = entries.length - 1; while (i > 0 && (entries[i - 1] instanceof ModuleSourceOrderEntry || entries[i - 1] instanceof JdkOrderEntry)) { OrderEntry e = entries[i - 1]; entries[i - 1] = entries[i]; entries[i] = e; i--; } if (i < entries.length) { myRootModel.rearrangeOrderEntries(entries); } } private static void updateUrl(Library.ModifiableModel library, OrderRootType type, MavenArtifact artifact, MavenExtraArtifactType artifactType, MavenProject project, boolean clearAll) { String classifier = null; String extension = null; if (artifactType != null) { Pair result = project.getClassifierAndExtension(artifact, artifactType); classifier = result.first; extension = result.second; } String newPath = artifact.getPathForExtraArtifact(classifier, extension); String newUrl = VirtualFileManager.constructUrl(JarFileSystem.PROTOCOL, newPath) + JarFileSystem.JAR_SEPARATOR; boolean urlExists = false; for (String url : library.getUrls(type)) { if (newUrl.equals(url)) { urlExists = true; continue; } if (clearAll || (isRepositoryUrl(artifact, url) && !url.startsWith(newUrl))) { library.removeRoot(url, type); } } if (!urlExists) { library.addRoot(newUrl, type); } } private static boolean isRepositoryUrl(MavenArtifact artifact, String url) { return url.contains(artifact.getGroupId().replace('.', '/') + '/' + artifact.getArtifactId() + '/' + artifact.getBaseVersion() + '/' + artifact.getArtifactId() + '-'); } public static boolean isChangedByUser(Library library) { String[] classRoots = library.getUrls(OrderRootType.CLASSES); if (classRoots.length != 1) return true; String classes = classRoots[0]; if (!classes.endsWith("!/")) return true; int dotPos = classes.lastIndexOf("/", classes.length() - 2 /* trim ending !/ */); if (dotPos == -1) return true; String pathToJar = classes.substring(0, dotPos); if (hasUserPaths(OrderRootType.SOURCES, library, pathToJar)) return true; if (hasUserPaths(JavadocOrderRootType.getInstance(), library, pathToJar)) return true; return false; } private static boolean hasUserPaths(OrderRootType rootType, Library library, String pathToJar) { String[] sources = library.getUrls(rootType); for (String each : sources) { if (!FileUtil.startsWith(each, pathToJar)) return true; } return false; } public Library findLibrary(@NotNull final MavenArtifact artifact) { final String name = artifact.getLibraryName(); final Ref result = Ref.create(null); myRootModel.orderEntries().forEachLibrary(new Processor() { @Override public boolean process(Library library) { if (name.equals(library.getName())) { result.set(library); } return true; } }); return result.get(); } @Deprecated // Use artifact.getLibraryName(); public static String makeLibraryName(@NotNull MavenArtifact artifact) { return artifact.getLibraryName(); } public static boolean isMavenLibrary(@Nullable Library library) { return library != null && MavenArtifact.isMavenLibrary(library.getName()); } @Nullable public static OrderEntry findLibraryEntry(@NotNull Module m, @NotNull MavenArtifact artifact) { String name = artifact.getLibraryName(); for (OrderEntry each : ModuleRootManager.getInstance(m).getOrderEntries()) { if (each instanceof LibraryOrderEntry && name.equals(((LibraryOrderEntry)each).getLibraryName())) { return each; } } return null; } @Nullable public static MavenArtifact findArtifact(@NotNull MavenProject project, @Nullable Library library) { if (library == null) return null; String name = library.getName(); if (!MavenArtifact.isMavenLibrary(name)) return null; for (MavenArtifact each : project.getDependencies()) { if (each.getLibraryName().equals(name)) return each; } return null; } public void setLanguageLevel(LanguageLevel level) { try { myRootModel.getModuleExtension(LanguageLevelModuleExtension.class).setLanguageLevel(level); } catch (IllegalArgumentException e) { //bad value was stored } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy