public FileDocumentManagerImpl(
      @NotNull VirtualFileManager virtualFileManager, @NotNull ProjectManager projectManager) {
    virtualFileManager.addVirtualFileListener(this);
    projectManager.addProjectManagerListener(this);

    myBus = ApplicationManager.getApplication().getMessageBus();
    InvocationHandler handler =
        new InvocationHandler() {
          @Nullable
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            multiCast(method, args);
            return null;
          }
        };

    final ClassLoader loader = FileDocumentManagerListener.class.getClassLoader();
    myMultiCaster =
        (FileDocumentManagerListener)
            Proxy.newProxyInstance(
                loader, new Class[] {FileDocumentManagerListener.class}, handler);
  }
  public JavaSdkImpl(final VirtualFileManager fileManager, final FileTypeManager fileTypeManager) {
    super("JavaSDK");

    fileManager.addVirtualFileListener(
        new VirtualFileAdapter() {
          @Override
          public void fileDeleted(@NotNull VirtualFileEvent event) {
            updateCache(event);
          }

          @Override
          public void contentsChanged(@NotNull VirtualFileEvent event) {
            updateCache(event);
          }

          @Override
          public void fileCreated(@NotNull VirtualFileEvent event) {
            updateCache(event);
          }

          private void updateCache(VirtualFileEvent event) {
            final VirtualFile file = event.getFile();
            if (FileTypes.ARCHIVE.equals(
                fileTypeManager.getFileTypeByFileName(event.getFileName()))) {
              final String filePath = file.getPath();
              synchronized (myCachedVersionStrings) {
                for (String sdkHome : myCachedVersionStrings.keySet()) {
                  if (FileUtil.isAncestor(sdkHome, filePath, false)) {
                    myCachedVersionStrings.remove(sdkHome);
                    break;
                  }
                }
              }
            }
          }
        });
  }
  private void installPropertiesChangeListeners() {
    final VirtualFileManager virtualFileManager = VirtualFileManager.getInstance();
    if (myVfsListener != null) {
      assert false;
      virtualFileManager.removeVirtualFileListener(myVfsListener);
    }
    myVfsListener =
        new VirtualFileAdapter() {
          @Override
          public void fileCreated(@NotNull VirtualFileEvent event) {
            if (PropertiesImplUtil.isPropertiesFile(event.getFile(), myProject)) {
              recreateEditorsPanel();
            }
          }

          @Override
          public void fileDeleted(@NotNull VirtualFileEvent event) {
            for (PropertiesFile file : myEditors.keySet()) {
              if (Comparing.equal(file.getVirtualFile(), event.getFile())) {
                recreateEditorsPanel();
                return;
              }
            }
          }

          @Override
          public void propertyChanged(@NotNull VirtualFilePropertyEvent event) {
            if (PropertiesImplUtil.isPropertiesFile(event.getFile(), myProject)) {
              if (VirtualFile.PROP_NAME.equals(event.getPropertyName())) {
                recreateEditorsPanel();
              } else {
                updateEditorsFromProperties();
              }
            }
          }
        };

    virtualFileManager.addVirtualFileListener(myVfsListener, this);
    PsiTreeChangeAdapter psiTreeChangeAdapter =
        new PsiTreeChangeAdapter() {
          @Override
          public void childAdded(@NotNull PsiTreeChangeEvent event) {
            childrenChanged(event);
          }

          @Override
          public void childRemoved(@NotNull PsiTreeChangeEvent event) {
            childrenChanged(event);
          }

          @Override
          public void childReplaced(@NotNull PsiTreeChangeEvent event) {
            childrenChanged(event);
          }

          @Override
          public void childMoved(@NotNull PsiTreeChangeEvent event) {
            childrenChanged(event);
          }

          @Override
          public void childrenChanged(@NotNull PsiTreeChangeEvent event) {
            final PsiFile file = event.getFile();
            PropertiesFile propertiesFile = PropertiesImplUtil.getPropertiesFile(file);
            if (propertiesFile == null) return;
            if (!propertiesFile.getResourceBundle().equals(myResourceBundle)) return;
            updateEditorsFromProperties();
          }
        };
    PsiManager.getInstance(myProject).addPsiTreeChangeListener(psiTreeChangeAdapter, this);
  }