@Nullable
  @Override
  public Element getSerializedState(
      @NotNull Boolean storageData,
      Object component,
      @NotNull String componentName,
      boolean archive) {
    if (storageData) {
      return null;
    }

    Element element = new Element("component");
    ModifiableRootModel model = null;
    AccessToken token = ReadAction.start();
    try {
      model = ((ModuleRootManagerImpl) component).getModifiableModel();
      // IDEA-137969 Eclipse integration: external remove of classpathentry is not synchronized
      model.clear();
      try {
        myConverter.readClasspath(model);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
      ((RootModelImpl) model).writeExternal(element);
    } catch (WriteExternalException e) {
      LOG.error(e);
    } finally {
      try {
        token.finish();
      } finally {
        if (model != null) {
          model.dispose();
        }
      }
    }

    if (myPathMacroSubstitutor != null) {
      myPathMacroSubstitutor.expandPaths(element);
      myPathMacroSubstitutor.addUnknownMacros(
          "NewModuleRootManager", PathMacrosCollector.getMacroNames(element));
    }

    getStorageDataRef().set(true);
    return element;
  }
  public ClasspathStorage(
      @NotNull final Module module, @NotNull StateStorageManager storageManager) {
    String storageType = module.getOptionValue(JpsProjectLoader.CLASSPATH_ATTRIBUTE);
    if (storageType == null) {
      throw new IllegalStateException("Classpath storage requires non-default storage type");
    }

    ClasspathStorageProvider provider = getProvider(storageType);
    if (provider == null) {
      if (module.getUserData(ERROR_NOTIFIED_KEY) == null) {
        Notification n =
            new Notification(
                StorageUtil.NOTIFICATION_GROUP_ID,
                "Cannot load module '" + module.getName() + "'",
                "Support for " + storageType + " format is not installed.",
                NotificationType.ERROR);
        n.notify(module.getProject());
        module.putUserData(ERROR_NOTIFIED_KEY, Boolean.TRUE);
        LOG.info("Classpath storage provider " + storageType + " not found");
      }

      myConverter = new MissingClasspathConverter();
    } else {
      myConverter = provider.createConverter(module);
    }

    myPathMacroSubstitutor = storageManager.getMacroSubstitutor();

    final List<String> paths = myConverter.getFilePaths();
    MessageBusConnection busConnection = module.getMessageBus().connect();
    busConnection.subscribe(
        VirtualFileManager.VFS_CHANGES,
        new BulkFileListener.Adapter() {
          @Override
          public void after(@NotNull List<? extends VFileEvent> events) {
            for (VFileEvent event : events) {
              if (!event.isFromRefresh() || !(event instanceof VFileContentChangeEvent)) {
                continue;
              }

              for (String path : paths) {
                if (path.equals(event.getPath())) {
                  module
                      .getMessageBus()
                      .syncPublisher(StateStorageManager.STORAGE_TOPIC)
                      .storageFileChanged(event, ClasspathStorage.this, module);
                  return;
                }
              }
            }
          }
        });

    busConnection.subscribe(
        StateStorageManager.STORAGE_TOPIC,
        new StorageManagerListener() {
          private String fileNameToModuleName(@NotNull String fileName) {
            return fileName.substring(
                0, fileName.length() - ModuleFileType.DOT_DEFAULT_EXTENSION.length());
          }

          @Override
          public void storageFileChanged(
              @NotNull VFileEvent event,
              @NotNull StateStorage storage,
              @NotNull ComponentManager componentManager) {
            assert componentManager == module;
            if (!(event instanceof VFilePropertyChangeEvent)) {
              return;
            }

            VFilePropertyChangeEvent propertyEvent = (VFilePropertyChangeEvent) event;
            if (propertyEvent.getPropertyName().equals(VirtualFile.PROP_NAME)) {
              String oldFileName = (String) propertyEvent.getOldValue();
              if (oldFileName.endsWith(ModuleFileType.DOT_DEFAULT_EXTENSION)) {
                ClasspathStorageProvider provider =
                    getProvider(ClassPathStorageUtil.getStorageType(module));
                if (provider != null) {
                  provider.moduleRenamed(
                      module,
                      fileNameToModuleName(oldFileName),
                      fileNameToModuleName((String) propertyEvent.getNewValue()));
                }
              }
            }
          }
        });
  }
 @Override
 @NotNull
 public ExternalizationSession startExternalization() {
   return myConverter.startExternalization();
 }