diff --git a/build.gradle b/build.gradle
index 1ac40749..fdb33e1d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -79,7 +79,9 @@ dependencies {
exclude group: 'org.apache.logging.log4j', module: 'log4j-core'
exclude group: 'org.slf4j', module: 'slf4j-api'
}
- implementation 'net.sf.saxon:Saxon-HE:12.5'
+ implementation ('net.sf.saxon:Saxon-HE:12.5') {
+ exclude group: 'org.slf4j', module: 'slf4j-api'
+ }
implementation 'org.jsoup:jsoup:1.18.3'
implementation 'info.clearthought:table-layout:4.3.0'
testImplementation 'junit:junit:4.13.2'
diff --git a/src/main/java/org/jetbrains/plugins/spotbugs/actions/ImportBugCollection.java b/src/main/java/org/jetbrains/plugins/spotbugs/actions/ImportBugCollection.java
index 3571c0c0..1a6f6164 100644
--- a/src/main/java/org/jetbrains/plugins/spotbugs/actions/ImportBugCollection.java
+++ b/src/main/java/org/jetbrains/plugins/spotbugs/actions/ImportBugCollection.java
@@ -81,10 +81,12 @@ void actionPerformedImpl(
if (dialogBuilder.getDialogWrapper().getExitCode() == DialogWrapper.CANCEL_EXIT_CODE) {
return;
}
- final String fileToImport = importFileDialog.getText();
- if (fileToImport == null || fileToImport.trim().isEmpty()) {
- return;
- }
+ String inputFile = importFileDialog.getText();
+ inputFile = MergeMultipleResultsFiles.mergeFiles(inputFile);
+ if (inputFile == null || inputFile.trim().isEmpty()) {
+ return;
+ }
+ final String fileToImport = inputFile;
final FindBugsResult findBugsResult = ToolWindowPanel.getInstance(project).getResult();
diff --git a/src/main/java/org/jetbrains/plugins/spotbugs/actions/MergeMultipleResultsFiles.java b/src/main/java/org/jetbrains/plugins/spotbugs/actions/MergeMultipleResultsFiles.java
new file mode 100755
index 00000000..830f2455
--- /dev/null
+++ b/src/main/java/org/jetbrains/plugins/spotbugs/actions/MergeMultipleResultsFiles.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2020 SpotBugs plugin contributors
+ *
+ * This file is part of IntelliJ SpotBugs plugin.
+ *
+ * IntelliJ SpotBugs plugin is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * IntelliJ SpotBugs plugin is distributed in the hope that it will
+ * be useful, but WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with IntelliJ SpotBugs plugin.
+ * If not, see .
+ */
+
+package org.jetbrains.plugins.spotbugs.actions;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MergeMultipleResultsFiles {
+
+ public static String mergeFiles(final String inputFile){
+
+ if (inputFile == null || inputFile.trim().isEmpty()) {
+ return null;
+ }
+
+ if (!Files.isDirectory(Path.of(inputFile))){
+ return inputFile;
+ }
+
+ final String outputFile = Path.of(inputFile, "merged-spotbugs-report.xml").toString();
+ // input file is directory - go over all the directories under this folder,
+ // find spotbugs results file and merge them to one file
+ try {
+ final List xmlFiles = new ArrayList<>();
+ collectXmlFiles(new File(inputFile), xmlFiles);
+
+ if (xmlFiles.isEmpty()) {
+ System.out.println("No SpotBugs XML files found in the directory: " + inputFile);
+ return null;
+ }
+
+ final Document mergedDocument = mergeSpotBugsReports(xmlFiles);
+
+ saveDocumentToFile(mergedDocument, outputFile);
+ System.out.println("Merged SpotBugs report written to: " + outputFile);
+ } catch (Exception e) {
+ System.err.println("Error while merging SpotBugs reports: " + e.getMessage());
+ e.printStackTrace();
+ }
+ return outputFile;
+ }
+
+ /**
+ * Recursively collects XML files from the given directory.
+ */
+ private static void collectXmlFiles(File directory, List xmlFiles) {
+ if (!directory.exists()) {
+ System.err.println("Directory does not exist: " + directory.getAbsolutePath());
+ return;
+ }
+
+ final File[] files = directory.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ collectXmlFiles(file, xmlFiles);
+ } else if (file.getName().equals("spotbugsXml.xml")) {
+ System.out.println("adding file "+ file);
+ xmlFiles.add(file);
+ }
+ }
+ }
+ }
+
+ /**
+ * Merges multiple SpotBugs XML files into a single Document.
+ */
+ private static Document mergeSpotBugsReports(List xmlFiles)
+ throws ParserConfigurationException, SAXException, IOException {
+
+ final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ final DocumentBuilder builder = factory.newDocumentBuilder();
+ final Document mergedDocument = builder.newDocument();
+
+ // Create the root element for the merged document
+ Element rootElement = mergedDocument.createElement("BugCollection");
+ mergedDocument.appendChild(rootElement);
+
+ for (File file : xmlFiles) {
+ final Document document = builder.parse(file);
+ final NodeList bugInstances = document.getElementsByTagName("BugInstance");
+
+ for (int i = 0; i < bugInstances.getLength(); i++) {
+ final Node importedNode = mergedDocument.importNode(bugInstances.item(i), true);
+ rootElement.appendChild(importedNode);
+ }
+ }
+
+ return mergedDocument;
+ }
+
+ /**
+ * Saves the merged Document to an XML file.
+ */
+ private static void saveDocumentToFile(Document document, String outputFile) throws Exception {
+ final TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ final Transformer transformer = transformerFactory.newTransformer();
+ final DOMSource source = new DOMSource(document);
+ final StreamResult result = new StreamResult(new FileWriter(outputFile));
+ transformer.transform(source, result);
+ }
+}