@NotNull
  public static TreeMap<String, Element> load(
      @NotNull Element rootElement,
      @Nullable PathMacroSubstitutor pathMacroSubstitutor,
      boolean intern) {
    if (pathMacroSubstitutor != null) {
      pathMacroSubstitutor.expandPaths(rootElement);
    }

    StringInterner interner = intern ? new StringInterner() : null;
    List<Element> children = rootElement.getChildren(COMPONENT);
    TreeMap<String, Element> map = new TreeMap<String, Element>();
    for (Element element : children) {
      String name = getComponentNameIfValid(element);
      if (name == null
          || !(element.getAttributes().size() > 1 || !element.getChildren().isEmpty())) {
        continue;
      }

      if (interner != null) {
        JDOMUtil.internElement(element, interner);
      }

      map.put(name, element);

      if (pathMacroSubstitutor instanceof TrackingPathMacroSubstitutor) {
        ((TrackingPathMacroSubstitutor) pathMacroSubstitutor)
            .addUnknownMacros(name, PathMacrosCollector.getMacroNames(element));
      }

      // remove only after "getMacroNames" - some PathMacroFilter requires element name attribute
      element.removeAttribute(NAME);
    }
    return map;
  }
  @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;
  }
Esempio n. 3
0
  public static void notifyUnknownMacros(
      @NotNull TrackingPathMacroSubstitutor substitutor,
      @NotNull final Project project,
      @Nullable final String componentName) {
    final LinkedHashSet<String> macros =
        new LinkedHashSet<String>(substitutor.getUnknownMacros(componentName));
    if (macros.isEmpty()) {
      return;
    }

    UIUtil.invokeLaterIfNeeded(
        new Runnable() {
          @Override
          public void run() {
            macros.removeAll(getMacrosFromExistingNotifications(project));

            if (!macros.isEmpty()) {
              LOG.debug(
                  "Reporting unknown path macros " + macros + " in component " + componentName);
              String format = "<p><i>%s</i> %s undefined. <a href=\"define\">Fix it</a></p>";
              String productName = ApplicationNamesInfo.getInstance().getProductName();
              String content =
                  String.format(
                          format, StringUtil.join(macros, ", "), macros.size() == 1 ? "is" : "are")
                      + "<br>Path variables are used to substitute absolute paths "
                      + "in "
                      + productName
                      + " project files "
                      + "and allow project file sharing in version control systems.<br>"
                      + "Some of the files describing the current project settings contain unknown path variables "
                      + "and "
                      + productName
                      + " cannot restore those paths.";
              new UnknownMacroNotification(
                      "Load Error",
                      "Load error: undefined path variables",
                      content,
                      NotificationType.ERROR,
                      new NotificationListener() {
                        @Override
                        public void hyperlinkUpdate(
                            @NotNull Notification notification, @NotNull HyperlinkEvent event) {
                          ((ProjectEx) project).checkUnknownMacros(true);
                        }
                      },
                      macros)
                  .notify(project);
            }
          }
        });
  }