diff options
Diffstat (limited to 'xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java')
-rw-r--r-- | xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java new file mode 100644 index 000000000000..987fdcd3a139 --- /dev/null +++ b/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java @@ -0,0 +1,142 @@ +package org.jetbrains.builtInWebServer; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.intellij.ProjectTopics; +import com.intellij.openapi.application.Application; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootAdapter; +import com.intellij.openapi.roots.ModuleRootEvent; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.openapi.vfs.VirtualFileManager; +import com.intellij.openapi.vfs.newvfs.BulkFileListener; +import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent; +import com.intellij.openapi.vfs.newvfs.events.VFileEvent; +import com.intellij.util.PairFunction; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * Implement {@link WebServerRootsProvider} to add your provider + */ +public class WebServerPathToFileManager { + private static final PairFunction<String, VirtualFile, VirtualFile> RELATIVE_PATH_RESOLVER = new PairFunction<String, VirtualFile, VirtualFile>() { + @Nullable + @Override + public VirtualFile fun(String path, VirtualFile parent) { + return parent.findFileByRelativePath(path); + } + }; + + private static final PairFunction<String, VirtualFile, VirtualFile> EMPTY_PATH_RESOLVER = new PairFunction<String, VirtualFile, VirtualFile>() { + @Nullable + @Override + public VirtualFile fun(String path, VirtualFile parent) { + return BuiltInWebServer.findIndexFile(parent); + } + }; + + private final Project project; + + final Cache<String, VirtualFile> pathToFileCache = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(10, TimeUnit.MINUTES).build(); + // time to expire should be greater than pathToFileCache + private final Cache<VirtualFile, PathInfo> fileToRoot = CacheBuilder.newBuilder().maximumSize(512).expireAfterAccess(11, TimeUnit.MINUTES).build(); + + public static WebServerPathToFileManager getInstance(@NotNull Project project) { + return ServiceManager.getService(project, WebServerPathToFileManager.class); + } + + public WebServerPathToFileManager(@NotNull Application application, @NotNull Project project) { + this.project = project; + application.getMessageBus().connect(project).subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() { + @Override + public void after(@NotNull List<? extends VFileEvent> events) { + for (VFileEvent event : events) { + if (event instanceof VFileContentChangeEvent) { + VirtualFile file = ((VFileContentChangeEvent)event).getFile(); + for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) { + if (rootsProvider.isClearCacheOnFileContentChanged(file)) { + clearCache(); + break; + } + } + } + else { + clearCache(); + break; + } + } + } + }); + project.getMessageBus().connect().subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() { + @Override + public void rootsChanged(ModuleRootEvent event) { + clearCache(); + } + }); + } + + private void clearCache() { + pathToFileCache.invalidateAll(); + fileToRoot.invalidateAll(); + } + + @Nullable + public VirtualFile get(@NotNull String path) { + return get(path, true); + } + + @Nullable + public VirtualFile get(@NotNull String path, boolean cacheResult) { + VirtualFile result = pathToFileCache.getIfPresent(path); + if (result == null || !result.isValid()) { + result = findByRelativePath(project, path); + if (cacheResult && result != null && result.isValid()) { + pathToFileCache.put(path, result); + } + } + return result; + } + + @Nullable + public String getPath(@NotNull VirtualFile file) { + PathInfo pathInfo = getRoot(file); + return pathInfo == null ? null : pathInfo.getPath(); + } + + @Nullable + public PathInfo getRoot(@NotNull VirtualFile child) { + PathInfo result = fileToRoot.getIfPresent(child); + if (result == null) { + for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) { + result = rootsProvider.getRoot(child, project); + if (result != null) { + fileToRoot.put(child, result); + break; + } + } + } + return result; + } + + @Nullable + VirtualFile findByRelativePath(@NotNull Project project, @NotNull String path) { + for (WebServerRootsProvider rootsProvider : WebServerRootsProvider.EP_NAME.getExtensions()) { + PathInfo result = rootsProvider.resolve(path, project); + if (result != null) { + fileToRoot.put(result.getChild(), result); + return result.getChild(); + } + } + return null; + } + + @NotNull + public PairFunction<String, VirtualFile, VirtualFile> getResolver(@NotNull String path) { + return path.isEmpty() ? EMPTY_PATH_RESOLVER : RELATIVE_PATH_RESOLVER; + } +}
\ No newline at end of file |