summaryrefslogtreecommitdiff
path: root/xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java')
-rw-r--r--xml/impl/src/org/jetbrains/builtInWebServer/WebServerPathToFileManager.java142
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