@Override
  public @NotNull Collection<? extends AttachSourcesAction> getActions(@NotNull List<? extends LibraryOrderEntry> orderEntries,
                                                                       @NotNull PsiFile psiFile) {
    final VirtualFile jar = getJarByPsiFile(psiFile);
    if (jar == null) return List.of();

    final String jarName = jar.getNameWithoutExtension();
    int index = jarName.lastIndexOf('-');
    if (index == -1) return List.of();

    MavenCoords mavenCoords = parse(jar);
    if (null == mavenCoords) return List.of();

    String artifactId = mavenCoords.artifactId();
    String version = mavenCoords.version();

    if (!ARTIFACT_IDENTIFIER.matcher(version).matches() || !ARTIFACT_IDENTIFIER.matcher(artifactId).matches()) {
      return List.of();
    }

    final Set<Library> libraries = new HashSet<>();
    for (LibraryOrderEntry orderEntry : orderEntries) {
      ContainerUtil.addIfNotNull(libraries, orderEntry.getLibrary());
    }

    if (libraries.isEmpty()) return List.of();

    final String sourceFileName = jarName + "-sources.jar";

    for (Library library : libraries) {
      for (VirtualFile file : library.getFiles(OrderRootType.SOURCES)) {
        if (file.getPath().contains(sourceFileName)) {
          if (isRootInExistingFile(file)) {
            return List.of(); // Sources already attached, but source-jar doesn't contain current class.
          }
        }
      }
    }

    final File libSourceDir = getLibrarySourceDir();

    final File sourceFile = new File(libSourceDir, sourceFileName);

    if (sourceFile.exists()) {
      return List.of(new LightAttachSourcesAction() {
        @Override
        public @NlsContexts.LinkLabel @Nls(capitalization = Nls.Capitalization.Title) String getName() {
          return JavaUiBundle.message("internet.attach.source.provider.name");
        }

        @Override
        public String getBusyText() {
          return getName();
        }


        @Override
        public @NotNull ActionCallback perform(@NotNull List<? extends LibraryOrderEntry> orderEntriesContainingFile) {
          attachSourceJar(sourceFile, libraries);
          return ActionCallback.DONE;
        }
      });
    }

    return List.of(new LightAttachSourcesAction() {
      @Override
      public @Nls(capitalization = Nls.Capitalization.Title) String getName() {
        return JavaUiBundle.message("internet.attach.source.provider.action.name");
      }

      @Override
      public String getBusyText() {
        return JavaUiBundle.message("internet.attach.source.provider.action.busy.text");
      }

      @Override
      public @NotNull ActionCallback perform(@NotNull List<? extends LibraryOrderEntry> orderEntriesContainingFile) {
        final Task task = new Task.Modal(psiFile.getProject(), JavaUiBundle.message("progress.title.searching.source"), true) {
          @Override
          public void run(@NotNull final ProgressIndicator indicator) {
            String artifactUrl = null;

            SourceSearcher[] searchers = {new MavenCentralSourceSearcher(), new SonatypeSourceSearcher()};
            for (SourceSearcher searcher : searchers) {
              try {
                artifactUrl = searcher.findSourceJar(indicator, artifactId, version, jar);
              }
              catch (SourceSearchException e) {
                LOG.warn(e);
                final String title = JavaUiBundle.message("internet.attach.source.provider.action.notification.title.downloading.failed");
                showMessage(title, e.getMessage(), NotificationType.ERROR);
                continue;
              }

              if (artifactUrl != null) break;
            }

            if (artifactUrl == null) {
              showMessage(JavaUiBundle.message("internet.attach.source.provider.action.notification.title.sources.not.found"),
                          JavaUiBundle.message("internet.attach.source.provider.action.notification.content.sources.for.jar.not.found", jarName),
                          NotificationType.WARNING);
              return;
            }

            if (!(libSourceDir.isDirectory() || libSourceDir.mkdirs())) {
              showMessage(JavaUiBundle.message("internet.attach.source.provider.action.notification.title.downloading.failed"),
                          JavaUiBundle.message("internet.attach.source.provider.action.notification.content.failed.to.create.directory", libSourceDir),
                          NotificationType.ERROR);
              return;
            }

            try {
              File tmpDownload = FileUtil.createTempFile(libSourceDir, "download.", ".tmp", false, false);
              HttpRequests.request(artifactUrl).saveToFile(tmpDownload, indicator);
              if (!sourceFile.exists() && !tmpDownload.renameTo(sourceFile)) {
                LOG.warn("Failed to rename file " + tmpDownload + " to " + sourceFileName);
              }
            }
            catch (IOException e) {
              LOG.warn(e);
              showMessage(JavaUiBundle.message("internet.attach.source.provider.action.notification.title.downloading.failed"),
                          JavaUiBundle.message("internet.attach.source.provider.action.notification.content.connection.problem"),
                          NotificationType.ERROR);
            }
          }

          @Override
          public void onSuccess() {
            attachSourceJar(sourceFile, libraries);
          }

          private void showMessage(@NlsContexts.NotificationTitle String title,
                                   @NlsContexts.NotificationContent String message,
                                   NotificationType notificationType) {
            new Notification("Source searcher", title, message, notificationType).notify(getProject());
          }
        };

        task.queue();

        return ActionCallback.DONE;
      }
    });
  }
@Override
  public @NotNull Collection<? extends AttachSourcesAction> getActions(@NotNull List<? extends LibraryOrderEntry> orderEntries,
                                                                       @NotNull PsiFile psiFile)