IDEA-134641 (refresh on .jimage files update)
authorRoman Shevchenko <roman.shevchenko@jetbrains.com>
Wed, 14 Jan 2015 18:44:22 +0000 (19:44 +0100)
committerRoman Shevchenko <roman.shevchenko@jetbrains.com>
Wed, 14 Jan 2015 18:47:44 +0000 (19:47 +0100)
java/java-impl/src/com/intellij/openapi/vfs/JrtFileSystem.java
platform/core-api/src/com/intellij/openapi/vfs/StandardFileSystems.java
platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java

index 853a8b44d4c57575f17d9c21bafc53300b557634..280d5fd4838cef789f0d48466e5cb43e02448b51 100644 (file)
@@ -20,26 +20,39 @@ import com.intellij.lang.LangBundle;
 import com.intellij.notification.Notification;
 import com.intellij.notification.NotificationType;
 import com.intellij.notification.Notifications;
+import com.intellij.openapi.application.Application;
 import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
 import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.JavaSdkType;
+import com.intellij.openapi.projectRoots.JavaSdk;
 import com.intellij.openapi.projectRoots.ProjectJdkTable;
 import com.intellij.openapi.projectRoots.Sdk;
 import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.openapi.vfs.impl.ArchiveHandler;
-import com.intellij.openapi.vfs.newvfs.ArchiveFileSystem;
-import com.intellij.openapi.vfs.newvfs.VfsImplUtil;
-import com.intellij.util.Function;
+import com.intellij.openapi.vfs.newvfs.*;
+import com.intellij.openapi.vfs.newvfs.events.VFileContentChangeEvent;
+import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
+import com.intellij.util.containers.ContainerUtil;
 import com.intellij.util.messages.MessageBusConnection;
 import org.jetbrains.annotations.NotNull;
 
 import java.io.File;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static com.intellij.util.containers.ContainerUtil.newTroveMap;
 
 public class JrtFileSystem extends ArchiveFileSystem {
-  public static final String PROTOCOL = "jrt";
+  public static final String PROTOCOL = StandardFileSystems.JRT_PROTOCOL;
   public static final String SEPARATOR = JarFileSystem.JAR_SEPARATOR;
 
+  private final Map<String, ArchiveHandler> myHandlers = newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
+  private final AtomicBoolean mySubscribed = new AtomicBoolean(false);
+
   public JrtFileSystem() {
     scheduleConfiguredSdkCheck();
   }
@@ -50,8 +63,9 @@ public class JrtFileSystem extends ArchiveFileSystem {
     connection.subscribe(AppLifecycleListener.TOPIC, new AppLifecycleListener.Adapter() {
       @Override
       public void appStarting(Project project) {
-        for (Sdk sdk : ProjectJdkTable.getInstance().getAllJdks()) {
-          if (getHomePathIfModular(sdk) != null) {
+        for (Sdk sdk : ProjectJdkTable.getInstance().getSdksOfType(JavaSdk.getInstance())) {
+          String homePath = sdk.getHomePath();
+          if (homePath != null && isModularJdk(homePath)) {
             String title = LangBundle.message("jrt.not.available.title", sdk.getName());
             String message = LangBundle.message("jrt.not.available.message");
             Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID, title, message, NotificationType.WARNING));
@@ -62,16 +76,6 @@ public class JrtFileSystem extends ArchiveFileSystem {
     });
   }
 
-  private static String getHomePathIfModular(Sdk sdk) {
-    if (sdk != null && sdk.getSdkType() instanceof JavaSdkType) {
-      String homePath = sdk.getHomePath();
-      if (homePath != null && isModularJdk(homePath)) {
-        return homePath;
-      }
-    }
-    return null;
-  }
-
   @NotNull
   @Override
   public String getProtocol() {
@@ -101,11 +105,54 @@ public class JrtFileSystem extends ArchiveFileSystem {
   @NotNull
   @Override
   protected ArchiveHandler getHandler(@NotNull VirtualFile entryFile) {
+    checkSubscription();
+
     final String homePath = extractLocalPath(extractRootPath(entryFile.getPath()));
-    return VfsImplUtil.getHandler(this, homePath + "/lib/modules", new Function<String, ArchiveHandler>() {
+    ArchiveHandler handler = myHandlers.get(homePath);
+    if (handler == null) {
+      handler = isSupported() ? new JrtHandler(homePath) : new JrtHandlerStub(homePath);
+      myHandlers.put(homePath, handler);
+      ApplicationManager.getApplication().invokeLater(new Runnable() {
+        @Override
+        public void run() {
+          VirtualFile dir = LocalFileSystem.getInstance().refreshAndFindFileByPath(homePath + "/lib/modules");
+          if (dir != null) dir.getChildren();
+        }
+      }, ModalityState.defaultModalityState());
+    }
+    return handler;
+  }
+
+  private void checkSubscription() {
+    if (mySubscribed.getAndSet(true)) return;
+
+    Application app = ApplicationManager.getApplication();
+    app.getMessageBus().connect(app).subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
       @Override
-      public ArchiveHandler fun(String localPath) {
-        return isSupported() ? new JrtHandler(homePath) : new JrtHandlerStub(homePath);
+      public void after(@NotNull List<? extends VFileEvent> events) {
+        Set<VirtualFile> toRefresh = null;
+
+        for (VFileEvent event : events) {
+          if (event.getFileSystem() instanceof LocalFileSystem && event instanceof VFileContentChangeEvent) {
+            VirtualFile file = event.getFile();
+            if (file != null && "jimage".equals(file.getExtension())) {
+              String homePath = file.getParent().getParent().getParent().getPath();
+              if (myHandlers.remove(homePath) != null) {
+                VirtualFile root = findFileByPath(composeRootPath(homePath));
+                if (root != null) {
+                  ((NewVirtualFile)root).markDirtyRecursively();
+                  if (toRefresh == null) toRefresh = ContainerUtil.newHashSet();
+                  toRefresh.add(root);
+                }
+              }
+            }
+          }
+        }
+
+        if (toRefresh != null) {
+          boolean async = !ApplicationManager.getApplication().isUnitTestMode();
+          RefreshQueue.getInstance().refresh(async, true, null, toRefresh);
+        }
       }
     });
   }
index bd789c191206cda234bfce7266d5f2bc7a87e1f0..25818811e739a1917c1d1b13d17fe1507402f5f4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * Copyright 2000-2015 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.
@@ -23,22 +23,11 @@ import org.jetbrains.annotations.Nullable;
 public class StandardFileSystems {
   public static final String FILE_PROTOCOL = URLUtil.FILE_PROTOCOL;
   public static final String FILE_PROTOCOL_PREFIX = FILE_PROTOCOL + URLUtil.SCHEME_SEPARATOR;
+
   public static final String JAR_PROTOCOL = URLUtil.JAR_PROTOCOL;
   public static final String JAR_PROTOCOL_PREFIX = JAR_PROTOCOL + URLUtil.SCHEME_SEPARATOR;
 
-  @Deprecated
-  @SuppressWarnings("UnusedDeclaration")
-  /**
-   * @deprecated use {@link com.intellij.util.io.URLUtil#JAR_SEPARATOR}
-   */
-  public static final String JAR_SEPARATOR = URLUtil.JAR_SEPARATOR;
-
-  @Deprecated
-  @SuppressWarnings("UnusedDeclaration")
-  /**
-   * @deprecated use {@link com.intellij.util.io.URLUtil#HTTP_PROTOCOL}
-   */
-  public static final String HTTP_PROTOCOL = URLUtil.HTTP_PROTOCOL;
+  public static final String JRT_PROTOCOL = "jrt";
 
   private static final NotNullLazyValue<VirtualFileSystem> ourLocal = new NotNullLazyValue<VirtualFileSystem>() {
     @NotNull
@@ -79,4 +68,12 @@ public class StandardFileSystems {
     String localPath = path.substring(0, separatorIndex);
     return local().findFileByPath(localPath);
   }
+
+  @SuppressWarnings("UnusedDeclaration")
+  /** @deprecated use {@link URLUtil#JAR_SEPARATOR} (to be removed in IDEA 15) */
+  public static final String JAR_SEPARATOR = URLUtil.JAR_SEPARATOR;
+
+  @SuppressWarnings("UnusedDeclaration")
+  /** @deprecated use {@link URLUtil#HTTP_PROTOCOL} (to be removed in IDEA 15) */
+  public static final String HTTP_PROTOCOL = URLUtil.HTTP_PROTOCOL;
 }
index c5c263131f925832881e57419f18af264c5d7dda..0a15e14d7b504beb3c7299a3791962920da9eeff 100644 (file)
@@ -312,6 +312,9 @@ public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
         else if (JarFileSystem.PROTOCOL.equals(protocol)) {
           flat.add(extractLocalPath(url));
         }
+        else if (StandardFileSystems.JRT_PROTOCOL.equals(protocol)) {
+          recursive.add(extractLocalPath(url));
+        }
       }
     }
   }