4d59c0169d171068725a33dfc0ddb7c962d17d60
[idea/community.git] / platform / projectModel-api / src / com / intellij / openapi / roots / libraries / LibraryUtil.java
1 // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2
3 package com.intellij.openapi.roots.libraries;
4
5 import com.intellij.openapi.module.Module;
6 import com.intellij.openapi.module.ModuleManager;
7 import com.intellij.openapi.project.Project;
8 import com.intellij.openapi.roots.*;
9 import com.intellij.openapi.roots.impl.libraries.LibraryEx;
10 import com.intellij.openapi.util.Ref;
11 import com.intellij.openapi.vfs.VfsUtilCore;
12 import com.intellij.openapi.vfs.VirtualFile;
13 import com.intellij.util.PathUtil;
14 import com.intellij.util.containers.ContainerUtil;
15 import com.intellij.util.text.StringTokenizer;
16 import org.jetbrains.annotations.NonNls;
17 import org.jetbrains.annotations.NotNull;
18 import org.jetbrains.annotations.Nullable;
19
20 import java.util.Arrays;
21 import java.util.HashSet;
22 import java.util.List;
23 import java.util.Set;
24
25 public final class LibraryUtil {
26   private LibraryUtil() {
27   }
28
29   public static boolean isClassAvailableInLibrary(@NotNull Library library, @NotNull String fqn) {
30     return isClassAvailableInLibrary(library.getFiles(OrderRootType.CLASSES), fqn);
31   }
32
33   public static boolean isClassAvailableInLibrary(VirtualFile @NotNull [] files, @NotNull String fqn) {
34     return isClassAvailableInLibrary(Arrays.asList(files), fqn);
35   }
36
37   public static boolean isClassAvailableInLibrary(@NotNull List<? extends VirtualFile> files, @NotNull String fqn) {
38     for (VirtualFile file : files) {
39       if (findInFile(file, new StringTokenizer(fqn, "."))) return true;
40     }
41     return false;
42   }
43
44   @Nullable
45   public static Library findLibraryByClass(@NotNull String fqn, @Nullable Project project) {
46     if (project != null) {
47       final LibraryTable projectTable = LibraryTablesRegistrar.getInstance().getLibraryTable(project);
48       Library library = findInTable(projectTable, fqn);
49       if (library != null) {
50         return library;
51       }
52     }
53     final LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTable();
54     return findInTable(table, fqn);
55   }
56
57
58   private static boolean findInFile(@NotNull VirtualFile file, @NotNull StringTokenizer tokenizer) {
59     if (!tokenizer.hasMoreTokens()) return true;
60     @NonNls StringBuilder name = new StringBuilder(tokenizer.nextToken());
61     if (!tokenizer.hasMoreTokens()) {
62       name.append(".class");
63     }
64     final VirtualFile child = file.findChild(name.toString());
65     return child != null && findInFile(child, tokenizer);
66   }
67
68   @Nullable
69   private static Library findInTable(@NotNull LibraryTable table, @NotNull String fqn) {
70     for (Library library : table.getLibraries()) {
71       if (isClassAvailableInLibrary(library, fqn)) {
72         return library;
73       }
74     }
75     return null;
76   }
77
78   @NotNull
79   public static Library createLibrary(@NotNull LibraryTable libraryTable, @NonNls @NotNull String baseName) {
80     String name = baseName;
81     int count = 2;
82     while (libraryTable.getLibraryByName(name) != null) {
83       name = baseName + " (" + count++ + ")";
84     }
85     return libraryTable.createLibrary(name);
86   }
87
88   public static VirtualFile @NotNull [] getLibraryRoots(@NotNull Project project) {
89     return getLibraryRoots(project, true, true);
90   }
91
92   public static VirtualFile @NotNull [] getLibraryRoots(@NotNull Project project, final boolean includeSourceFiles, final boolean includeJdk) {
93     return getLibraryRoots(ModuleManager.getInstance(project).getModules(), includeSourceFiles, includeJdk);
94   }
95
96   public static VirtualFile @NotNull [] getLibraryRoots(Module @NotNull [] modules, final boolean includeSourceFiles, final boolean includeJdk) {
97     Set<VirtualFile> roots = new HashSet<>();
98     for (Module module : modules) {
99       final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
100       final OrderEntry[] orderEntries = moduleRootManager.getOrderEntries();
101       for (OrderEntry entry : orderEntries) {
102         if (entry instanceof LibraryOrderEntry){
103           final Library library = ((LibraryOrderEntry)entry).getLibrary();
104           if (library != null) {
105             VirtualFile[] files = includeSourceFiles ? library.getFiles(OrderRootType.SOURCES) : null;
106             if (files == null || files.length == 0) {
107               files = library.getFiles(OrderRootType.CLASSES);
108             }
109             ContainerUtil.addAll(roots, files);
110           }
111         } else if (includeJdk && entry instanceof JdkOrderEntry) {
112           JdkOrderEntry jdkEntry = (JdkOrderEntry)entry;
113           VirtualFile[] files = includeSourceFiles ? jdkEntry.getRootFiles(OrderRootType.SOURCES) : null;
114           if (files == null || files.length == 0) {
115             files = jdkEntry.getRootFiles(OrderRootType.CLASSES);
116           }
117           ContainerUtil.addAll(roots, files);
118         }
119       }
120     }
121     return VfsUtilCore.toVirtualFileArray(roots);
122   }
123
124   @Nullable
125   public static Library findLibrary(@NotNull Module module, @NotNull final String name) {
126     final Ref<Library> result = Ref.create(null);
127     OrderEnumerator.orderEntries(module).forEachLibrary(library -> {
128       if (name.equals(library.getName())) {
129         result.set(library);
130         return false;
131       }
132       return true;
133     });
134     return result.get();
135   }
136
137   @Nullable
138   public static OrderEntry findLibraryEntry(@NotNull VirtualFile file, @NotNull Project project) {
139     List<OrderEntry> entries = ProjectRootManager.getInstance(project).getFileIndex().getOrderEntriesForFile(file);
140     for (OrderEntry entry : entries) {
141       if (entry instanceof LibraryOrderEntry || entry instanceof JdkOrderEntry) {
142         return entry;
143       }
144     }
145     return null;
146   }
147
148   @NotNull
149   public static String getPresentableName(@NotNull Library library) {
150     final String name = library.getName();
151     if (name != null) {
152       return name;
153     }
154     if (library instanceof LibraryEx && ((LibraryEx)library).isDisposed()) {
155       return "Disposed Library";
156     }
157     String[] urls = library.getUrls(OrderRootType.CLASSES);
158     if (urls.length > 0) {
159       return PathUtil.getFileName(VfsUtilCore.urlToPath(urls[0]));
160     }
161     return "Empty Library";
162   }
163 }