blob: b85d131e6b0b30d53cdacace59f2a877bdd3f568 [file]
// Copyright 2000-2019 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.
package org.jetbrains.plugins.gradle.service;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.model.project.ExternalModuleBuildClasspathPojo;
import com.intellij.openapi.externalSystem.model.project.ExternalProjectBuildClasspathPojo;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemLocalSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.impl.PackageDirectoryCache;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
/**
* @author Vladislav.Soroka
*/
public class GradleBuildClasspathManager {
@NotNull
private final Project myProject;
@NotNull
private volatile List<VirtualFile> allFilesCache;
@NotNull
private final AtomicReference<Map<String/*module path*/, List<VirtualFile> /*module build classpath*/>> myClasspathMap
= new AtomicReference<>(new HashMap<>());
@NotNull
private final Map<String, PackageDirectoryCache> myClassFinderCache = ConcurrentFactoryMap
.createMap(path -> PackageDirectoryCache.createCache(getModuleClasspathEntries(path)));
public GradleBuildClasspathManager(@NotNull Project project) {
myProject = project;
allFilesCache = new ArrayList<>();
}
@NotNull
public static GradleBuildClasspathManager getInstance(@NotNull Project project) {
return ServiceManager.getService(project, GradleBuildClasspathManager.class);
}
public void reload() {
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(GradleConstants.SYSTEM_ID);
assert manager != null;
AbstractExternalSystemLocalSettings<?> localSettings = manager.getLocalSettingsProvider().fun(myProject);
Map<String/*module path*/, List<VirtualFile> /*module build classpath*/> map = new HashMap<>();
final JarFileSystem jarFileSystem = JarFileSystem.getInstance();
final Map<String, VirtualFile> localVFCache = new HashMap<>();
for (final ExternalProjectBuildClasspathPojo projectBuildClasspathPojo : localSettings.getProjectBuildClasspath().values()) {
final List<VirtualFile> projectBuildClasspath = new ArrayList<>();
for (String path : projectBuildClasspathPojo.getProjectBuildClasspath()) {
final VirtualFile virtualFile = localVFCache.computeIfAbsent(path, it -> ExternalSystemUtil.findLocalFileByPath(it)) ;
ContainerUtil.addIfNotNull(projectBuildClasspath,
virtualFile == null || virtualFile.isDirectory()
? virtualFile
: jarFileSystem.getJarRootForLocalFile(virtualFile));
}
for (final ExternalModuleBuildClasspathPojo moduleBuildClasspathPojo : projectBuildClasspathPojo.getModulesBuildClasspath().values()) {
final List<VirtualFile> moduleBuildClasspath = new ArrayList<>(projectBuildClasspath);
for (String path : moduleBuildClasspathPojo.getEntries()) {
final VirtualFile virtualFile = localVFCache.computeIfAbsent(path, it -> ExternalSystemUtil.findLocalFileByPath(it)) ;
ContainerUtil.addIfNotNull(moduleBuildClasspath,
virtualFile == null || virtualFile.isDirectory()
? virtualFile
: jarFileSystem.getJarRootForLocalFile(virtualFile));
}
map.put(moduleBuildClasspathPojo.getPath(), moduleBuildClasspath);
}
}
myClasspathMap.set(map);
Set<VirtualFile> set = new LinkedHashSet<>();
for (List<VirtualFile> virtualFiles : myClasspathMap.get().values()) {
set.addAll(virtualFiles);
}
allFilesCache = new ArrayList<>(set);
myClassFinderCache.clear();
}
@NotNull
public Map<String, PackageDirectoryCache> getClassFinderCache() {
return myClassFinderCache;
}
@NotNull
public List<VirtualFile> getAllClasspathEntries() {
checkRootsValidity(allFilesCache);
return allFilesCache;
}
@NotNull
public List<VirtualFile> getModuleClasspathEntries(@NotNull String externalModulePath) {
checkRootsValidity(myClasspathMap.get().get(externalModulePath));
List<VirtualFile> virtualFiles = myClasspathMap.get().get(externalModulePath);
return virtualFiles == null ? Collections.emptyList() : virtualFiles;
}
private void checkRootsValidity(@Nullable List<VirtualFile> virtualFiles) {
if (virtualFiles == null) return;
if (!virtualFiles.isEmpty()) {
for (VirtualFile file : virtualFiles) {
if (!file.isValid()) {
reload();
break;
}
}
}
}
}