Kaynağa Gözat

Rework exit exception and provide specialized exception classes to allow flexible error handling when using JPlag programmatically.

Timur Sağlam 4 yıl önce
ebeveyn
işleme
fe5d4eb5f3

+ 2 - 1
jplag/src/main/java/de/jplag/CLI.java

@@ -17,6 +17,7 @@ import static de.jplag.CommandLineArgument.VERBOSITY;
 import java.io.File;
 import java.util.Random;
 
+import de.jplag.exceptions.ExitException;
 import de.jplag.options.JPlagOptions;
 import de.jplag.options.LanguageOption;
 import de.jplag.options.Verbosity;
@@ -59,7 +60,7 @@ public class CLI {
             Report report = new Report(reportDir, options);
             report.writeResult(result);
         } catch (ExitException exception) {
-            System.out.println("Error: " + exception.getReport());
+            System.out.println("Error: " + exception.getMessage());
             System.exit(1);
         }
     }

+ 0 - 45
jplag/src/main/java/de/jplag/ExitException.java

@@ -1,45 +0,0 @@
-package de.jplag;
-
-/**
- * Exception to be reached through to the main caller of JPlag to replace the "exit" method
- * @apiNote Created on 05.03.2005 Author Moritz Kroll, Emeric Kwemou.
- */
-public class ExitException extends Exception {
-    public static final int COMPARE_SOURCE_DONE = 300;
-    public static final int UNKNOWN_ERROR_OCCURRED = 400;
-    public static final int BAD_LANGUAGE_ERROR = 401;
-    public static final int NOT_ENOUGH_SUBMISSIONS_ERROR = 402;
-    public static final int BAD_PARAMETER = 403;
-    public static final int BAD_SENSITIVITY_OF_COMPARISON = 404;
-    public static final int SUBMISSION_ABORTED = 405;
-
-    private static final long serialVersionUID = 1L;
-    private final int errorCode;
-    private final String message;
-
-    public ExitException(String message) {
-        super(message);
-        errorCode = UNKNOWN_ERROR_OCCURRED;
-        this.message = message;
-    }
-
-    public ExitException(String message, int errorCode) {
-        super(message);
-        this.errorCode = errorCode;
-        this.message = message;
-    }
-
-    public ExitException(String message, Throwable cause) {
-        super(message, cause);
-        errorCode = UNKNOWN_ERROR_OCCURRED;
-        this.message = message;
-    }
-
-    public int getState() {
-        return errorCode;
-    }
-
-    public String getReport() {
-        return message;
-    }
-}

+ 14 - 15
jplag/src/main/java/de/jplag/JPlag.java

@@ -4,6 +4,10 @@ import java.io.File;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 
+import de.jplag.exceptions.BasecodeException;
+import de.jplag.exceptions.ExitException;
+import de.jplag.exceptions.RootDirectoryException;
+import de.jplag.exceptions.SubmissionException;
 import de.jplag.options.JPlagOptions;
 import de.jplag.options.LanguageOption;
 import de.jplag.strategy.ComparisonStrategy;
@@ -53,8 +57,7 @@ public class JPlag {
 
         int submissionCount = submissionSet.numberOfSubmissions();
         if (submissionCount < 2) {
-            throw new ExitException("Not enough valid submissions! (found " + submissionCount + " valid submissions)",
-                    ExitException.NOT_ENOUGH_SUBMISSIONS_ERROR);
+            throw new SubmissionException("Not enough valid submissions! (found " + submissionCount + " valid submissions)");
         }
 
         // Compare valid submissions.
@@ -72,18 +75,17 @@ public class JPlag {
         if (options.hasBaseCode()) {
             String baseCode = options.getBaseCodeSubmissionName();
             if (baseCode.contains(".")) {
-                throw new ExitException("The basecode directory name \"" + baseCode + "\" cannot contain dots!", ExitException.BAD_PARAMETER);
+                throw new BasecodeException("The basecode directory name \"" + baseCode + "\" cannot contain dots!");
             }
             String baseCodePath = options.getRootDirectoryName() + File.separator + baseCode;
             if (!new File(baseCodePath).exists()) {
-                throw new ExitException("Basecode directory \"" + baseCodePath + "\" doesn't exist!", ExitException.BAD_PARAMETER);
+                throw new BasecodeException("Basecode directory \"" + baseCodePath + "\" doesn't exist!");
             }
 
             String subdirectory = options.getSubdirectoryName();
             if (subdirectory != null && subdirectory.length() != 0) {
                 if (!new File(baseCodePath, subdirectory).exists()) {
-                    throw new ExitException("Basecode directory doesn't contain" + " the subdirectory \"" + subdirectory + "\"!",
-                            ExitException.BAD_PARAMETER);
+                    throw new BasecodeException("Basecode directory doesn't contain" + " the subdirectory \"" + subdirectory + "\"!");
                 }
             }
             System.out.println("Basecode directory \"" + baseCodePath + "\" will be used");
@@ -97,17 +99,15 @@ public class JPlag {
         String rootDirectoryName = options.getRootDirectoryName();
         File rootDir = new File(rootDirectoryName);
         if (!rootDir.exists()) {
-            String msg = String.format("Root directory \"%s\" does not exist!", rootDirectoryName);
-            throw new ExitException(msg, ExitException.BAD_PARAMETER);
+            throw new RootDirectoryException(String.format("Root directory \"%s\" does not exist!", rootDirectoryName));
         }
         if (!rootDir.isDirectory()) {
-            String msg = String.format("Root directory \"%s\" is not a directory!", rootDirectoryName);
-            throw new ExitException(msg, ExitException.BAD_PARAMETER);
+            throw new RootDirectoryException(String.format("Root directory \"%s\" is not a directory!", rootDirectoryName));
         }
         return rootDir;
     }
 
-    private void initializeComparisonStrategy() throws ExitException {
+    private void initializeComparisonStrategy() {
         switch (options.getComparisonMode()) {
         case NORMAL:
             comparisonStrategy = new NormalComparisonStrategy(options, coreAlgorithm);
@@ -116,11 +116,11 @@ public class JPlag {
             comparisonStrategy = new ParallelComparisonStrategy(options, coreAlgorithm);
             break;
         default:
-            throw new ExitException("Illegal comparison mode: " + options.getComparisonMode());
+            throw new UnsupportedOperationException("Comparison mode not properly supported: " + options.getComparisonMode());
         }
     }
 
-    private void initializeLanguage() throws ExitException {
+    private void initializeLanguage() {
         LanguageOption languageOption = this.options.getLanguageOption();
 
         try {
@@ -134,8 +134,7 @@ public class JPlag {
         } catch (NoSuchMethodException | SecurityException | ClassNotFoundException | InstantiationException | IllegalAccessException
                 | IllegalArgumentException | InvocationTargetException e) {
             e.printStackTrace();
-
-            throw new ExitException("Language instantiation failed", ExitException.BAD_LANGUAGE_ERROR);
+            throw new IllegalStateException("Language instantiation failed:" + e.getMessage());
         }
 
         this.options.setLanguageDefaults(this.language);

+ 8 - 8
jplag/src/main/java/de/jplag/Submission.java

@@ -15,6 +15,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import de.jplag.exceptions.ReportGenerationException;
 import de.jplag.options.JPlagOptions;
 
 /**
@@ -96,7 +97,6 @@ public class Submission implements Comparable<Submission> {
         if (tokenList == null) {
             return 0;
         }
-
         return tokenList.size();
     }
 
@@ -184,7 +184,7 @@ public class Submission implements Comparable<Submission> {
     /**
      * Used by the "Report" class. All source files are returned as an array of an array of strings.
      */
-    public String[][] readFiles(String[] files) throws de.jplag.ExitException {
+    public String[][] readFiles(String[] files) throws ReportGenerationException {
         String[][] result = new String[files.length][];
         String help;
         List<String> text = new ArrayList<>();
@@ -211,7 +211,7 @@ public class Submission implements Comparable<Submission> {
             } catch (FileNotFoundException e) {
                 System.out.println("File not found: " + ((new File(submissionRoot, files[i])).toString()));
             } catch (IOException e) {
-                throw new de.jplag.ExitException("I/O exception!");
+                throw new ReportGenerationException("I/O exception!", e);
             }
 
             result[i] = new String[text.size()];
@@ -224,7 +224,7 @@ public class Submission implements Comparable<Submission> {
     /**
      * Used by the "Report" class. All source files are returned as an array of an array of chars.
      */
-    public char[][] readFilesChar(String[] files) throws de.jplag.ExitException {
+    public char[][] readFilesChar(String[] files) throws ReportGenerationException {
         char[][] result = new char[files.length][];
 
         for (int i = 0; i < files.length; i++) {
@@ -247,9 +247,9 @@ public class Submission implements Comparable<Submission> {
                 result[i] = buffer;
                 reader.close();
             } catch (FileNotFoundException e) {
-                throw new de.jplag.ExitException("File not found: " + file.getPath(), e);
+                throw new ReportGenerationException("File not found: " + file.getPath(), e);
             } catch (IOException e) {
-                throw new de.jplag.ExitException("I/O exception reading file \"" + file.getPath() + "\"!", e);
+                throw new ReportGenerationException("I/O exception reading file \"" + file.getPath() + "\"!", e);
             }
         }
 
@@ -345,8 +345,8 @@ public class Submission implements Comparable<Submission> {
     /**
      * Map all files of this submission to their path relative to the submission directory.
      * <p>
-     * This method is required to stay compatible with `language.parse(...)` as it requires the given file paths to
-     * be relative to the submission directory.
+     * This method is required to stay compatible with `language.parse(...)` as it requires the given file paths to be
+     * relative to the submission directory.
      * <p>
      * In a future update, `language.parse(...)` should probably just take a list of files.
      * @param baseFile - File to base all relative file paths on.

+ 7 - 4
jplag/src/main/java/de/jplag/SubmissionSet.java

@@ -7,6 +7,9 @@ import java.util.List;
 import java.util.Optional;
 import java.util.stream.Collectors;
 
+import de.jplag.exceptions.BasecodeException;
+import de.jplag.exceptions.ExitException;
+import de.jplag.exceptions.SubmissionException;
 import de.jplag.options.JPlagOptions;
 
 /**
@@ -103,7 +106,7 @@ public class SubmissionSet {
                 parseBaseCodeSubmission(baseCodeSubmission.get()); // cannot use ifPresent because of throws declaration
             }
         } catch (OutOfMemoryError exception) {
-            throw new ExitException("Out of memory during parsing of submission \"" + currentSubmissionName + "\"");
+            throw new SubmissionException("Out of memory during parsing of submission \"" + currentSubmissionName + "\"");
         }
         if (errorCollector.hasErrors()) {
             errorCollector.printCollectedErrors();
@@ -113,14 +116,14 @@ public class SubmissionSet {
     /**
      * Parse the given base code submission.
      */
-    private void parseBaseCodeSubmission(Submission baseCode) throws ExitException {
+    private void parseBaseCodeSubmission(Submission baseCode) throws BasecodeException {
         long startTime = System.currentTimeMillis();
         errorCollector.print("----- Parsing basecode submission: " + baseCode.getName(), null);
         if (!baseCode.parse(options.isDebugParser())) {
             errorCollector.printCollectedErrors();
-            throw new ExitException("Bad basecode submission");
+            throw new BasecodeException("Could not successfully parse basecode submission!");
         } else if (baseCode.getNumberOfTokens() < options.getMinimumTokenMatch()) {
-            throw new ExitException("Basecode submission contains fewer tokens than minimum match length allows!");
+            throw new BasecodeException("Basecode submission contains fewer tokens than minimum match length allows!");
         }
         errorCollector.print("Basecode submission parsed!", null);
         long duration = System.currentTimeMillis() - startTime;

+ 8 - 4
jplag/src/main/java/de/jplag/SubmissionSetBuilder.java

@@ -14,6 +14,9 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
 
+import de.jplag.exceptions.ExitException;
+import de.jplag.exceptions.RootDirectoryException;
+import de.jplag.exceptions.SubmissionException;
 import de.jplag.options.JPlagOptions;
 
 /**
@@ -52,11 +55,12 @@ public class SubmissionSetBuilder {
         try {
             fileNames = rootDirectory.list();
         } catch (SecurityException exception) {
-            throw new ExitException("Cannot list files of the root directory! " + exception.getMessage());
+            throw new RootDirectoryException("Cannot list files of the root directory! " + exception.getMessage());
         }
 
         if (fileNames == null) {
-            throw new ExitException("Cannot list files of the root directory! " + "Make sure the specified root directory is in fact a directory.");
+            throw new RootDirectoryException(
+                    "Cannot list files of the root directory! Make sure the specified root directory is in fact a directory.");
         }
 
         Arrays.sort(fileNames);
@@ -108,12 +112,12 @@ public class SubmissionSetBuilder {
                 submissionFile = new File(submissionFile, options.getSubdirectoryName());
 
                 if (!submissionFile.exists()) {
-                    throw new ExitException(
+                    throw new SubmissionException(
                             String.format("Submission %s does not contain the given subdirectory '%s'", fileName, options.getSubdirectoryName()));
                 }
 
                 if (!submissionFile.isDirectory()) {
-                    throw new ExitException(String.format("The given subdirectory '%s' is not a directory!", options.getSubdirectoryName()));
+                    throw new SubmissionException(String.format("The given subdirectory '%s' is not a directory!", options.getSubdirectoryName()));
                 }
             }
 

+ 13 - 0
jplag/src/main/java/de/jplag/exceptions/BasecodeException.java

@@ -0,0 +1,13 @@
+package de.jplag.exceptions;
+
+/**
+ * Exceptions for problems with the basecode submission that lead to an preemptive exit.
+ */
+public class BasecodeException extends ExitException {
+
+    private static final long serialVersionUID = -3911476090624995247L; // generated
+
+    public BasecodeException(String message) {
+        super(message);
+    }
+}

+ 17 - 0
jplag/src/main/java/de/jplag/exceptions/ExitException.java

@@ -0,0 +1,17 @@
+package de.jplag.exceptions;
+
+/**
+ * Exceptions for problems during the execution of JPlag that lead to an preemptive exit.
+ */
+public abstract class ExitException extends Exception {
+
+    private static final long serialVersionUID = 7091658804288889231L; // generated
+
+    public ExitException(String message) {
+        super(message);
+    }
+
+    public ExitException(String message, Throwable cause) {
+        super(message, cause);
+    }
+}

+ 18 - 0
jplag/src/main/java/de/jplag/exceptions/ReportGenerationException.java

@@ -0,0 +1,18 @@
+package de.jplag.exceptions;
+
+/**
+ * Exceptions for problems with the report generation that lead to an preemptive exit.
+ */
+public class ReportGenerationException extends ExitException {
+
+    private static final long serialVersionUID = 628097693006117102L; // generated
+
+    public ReportGenerationException(String message) {
+        super(message);
+    }
+
+    public ReportGenerationException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+}

+ 14 - 0
jplag/src/main/java/de/jplag/exceptions/RootDirectoryException.java

@@ -0,0 +1,14 @@
+package de.jplag.exceptions;
+
+/**
+ * Exceptions for problems with the root directory that lead to an preemptive exit.
+ */
+public class RootDirectoryException extends ExitException {
+
+    private static final long serialVersionUID = 3134534079325843267L; // generated
+
+    public RootDirectoryException(String message) {
+        super(message);
+    }
+
+}

+ 14 - 0
jplag/src/main/java/de/jplag/exceptions/SubmissionException.java

@@ -0,0 +1,14 @@
+package de.jplag.exceptions;
+
+/**
+ * Exceptions for problems with the regular submissions that lead to an preemptive exit.
+ */
+public class SubmissionException extends ExitException {
+
+    private static final long serialVersionUID = 794916053362767596L; // generated
+
+    public SubmissionException(String message) {
+        super(message);
+    }
+
+}

+ 34 - 36
jplag/src/main/java/de/jplag/reporting/Report.java

@@ -16,13 +16,14 @@ import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
 
-import de.jplag.ExitException;
 import de.jplag.JPlagComparison;
 import de.jplag.JPlagResult;
 import de.jplag.Match;
 import de.jplag.Submission;
 import de.jplag.Token;
 import de.jplag.TokenList;
+import de.jplag.exceptions.ExitException;
+import de.jplag.exceptions.ReportGenerationException;
 import de.jplag.options.JPlagOptions;
 
 /**
@@ -44,7 +45,7 @@ public class Report { // Mostly legacy code with some minor improvements.
     private int matchWritingProgess = 0;
     private int matchesWritten = 0;
 
-    public Report(File reportDir, JPlagOptions options) throws ExitException {
+    public Report(File reportDir, JPlagOptions options) throws ReportGenerationException {
         this.reportDir = reportDir;
         this.options = options;
         msg = new Messages("en");
@@ -52,7 +53,7 @@ public class Report { // Mostly legacy code with some minor improvements.
         validateReportDir();
     }
 
-    public void writeResult(JPlagResult result) throws ExitException {
+    public void writeResult(JPlagResult result) throws ReportGenerationException {
         this.result = result;
         System.out.println("\nWriting report...");
         writeIndex();
@@ -109,13 +110,13 @@ public class Report { // Mostly legacy code with some minor improvements.
     /**
      * Create a new HTML file.
      */
-    private HTMLFile createHTMLFile(String name) throws ExitException {
+    private HTMLFile createHTMLFile(String name) throws ReportGenerationException {
         File file = new File(reportDir, name);
 
         try {
             return HTMLFile.fromFile(file);
         } catch (IOException e) {
-            throw new de.jplag.ExitException("Error opening file: " + file);
+            throw new ReportGenerationException("Error opening file: " + file);
         }
     }
 
@@ -201,17 +202,17 @@ public class Report { // Mostly legacy code with some minor improvements.
     /**
      * Make sure the report directory exists, is a directory and has write access.
      */
-    private void validateReportDir() throws ExitException {
+    private void validateReportDir() throws ReportGenerationException {
         if (!reportDir.exists() && !reportDir.mkdirs()) {
-            throw new ExitException("Cannot create report directory!");
+            throw new ReportGenerationException("Cannot create report directory!");
         }
 
         if (!reportDir.isDirectory()) {
-            throw new ExitException(reportDir + " is not a directory!");
+            throw new ReportGenerationException(reportDir + " is not a directory!");
         }
 
         if (!reportDir.canWrite()) {
-            throw new ExitException("Cannot write directory: " + reportDir);
+            throw new ReportGenerationException("Cannot write directory: " + reportDir);
         }
     }
 
@@ -263,7 +264,7 @@ public class Report { // Mostly legacy code with some minor improvements.
      * i is the number of the match j == 0 if subA is considered, otherwise (j must then be 1) it is subB This procedure
      * makes use of the column and length information!
      */
-    private int writeImprovedSubmission(HTMLFile f, int i, JPlagComparison comparison, int j) throws de.jplag.ExitException {
+    private int writeImprovedSubmission(HTMLFile f, int i, JPlagComparison comparison, int j) throws ReportGenerationException {
         Submission sub = comparison.getSubmission(j == 0);
         String[] files = comparison.files(j);
         String[][] text = sub.readFiles(files);
@@ -308,10 +309,9 @@ public class Report { // Mostly legacy code with some minor improvements.
         if (result.getOptions().hasBaseCode() && comparison.getFirstBaseCodeMatches() != null && comparison.getSecondBaseCodeMatches() != null) {
             JPlagComparison baseCodeComparison = comparison.getBaseCodeMatches(j == 0);
 
-            for (int x = 0; x < baseCodeComparison.getMatches().size(); x++) {
-                Match onematch = baseCodeComparison.getMatches().get(x);
-                Token start = tokens.getToken(onematch.getStartOfFirst());
-                Token end = tokens.getToken(onematch.getStartOfFirst() + onematch.getLength() - 1);
+            for (Match match : baseCodeComparison.getMatches()) {
+                Token start = tokens.getToken(match.getStartOfFirst());
+                Token end = tokens.getToken(match.getStartOfFirst() + match.getLength() - 1);
 
                 for (int fileIndex = 0; fileIndex < files.length; fileIndex++) {
                     if (start.file.equals(files[fileIndex]) && text[fileIndex] != null) {
@@ -332,43 +332,43 @@ public class Report { // Mostly legacy code with some minor improvements.
             String tmp = text[markup.fileIndex][markup.lineIndex];
             // is there any &quot;, &amp;, &gt; or &lt; in the String?
             if (tmp.indexOf('&') >= 0) {
-                List<String> tmpV = new ArrayList<>();
+                List<String> list = new ArrayList<>();
                 // convert the string into a vector
                 int strLength = tmp.length();
                 for (int k = 0; k < strLength; k++) {
                     if (tmp.charAt(k) != '&') {
-                        tmpV.add(tmp.charAt(k) + "");
+                        list.add(tmp.charAt(k) + "");
                     } else { // put &quot;, &amp;, &gt; and &lt; into one element
                         String tmpSub = tmp.substring(k);
                         if (tmpSub.startsWith("&quot;")) {
-                            tmpV.add("&quot;");
+                            list.add("&quot;");
                             k = k + 5;
                         } else if (tmpSub.startsWith("&amp;")) {
-                            tmpV.add("&amp;");
+                            list.add("&amp;");
                             k = k + 4;
                         } else if (tmpSub.startsWith("&lt;")) {
-                            tmpV.add("&lt;");
+                            list.add("&lt;");
                             k = k + 3;
                         } else if (tmpSub.startsWith("&gt;")) {
-                            tmpV.add("&gt;");
+                            list.add("&gt;");
                             k = k + 3;
                         } else {
-                            tmpV.add(tmp.charAt(k) + "");
+                            list.add(tmp.charAt(k) + "");
                         }
                     }
                 }
-                if (markup.column <= tmpV.size()) {
-                    tmpV.add(markup.column, markup.text);
+                if (markup.column <= list.size()) {
+                    list.add(markup.column, markup.text);
                 } else {
-                    tmpV.add(markup.text);
+                    list.add(markup.text);
                 }
 
-                StringBuilder tmpVStr = new StringBuilder();
+                StringBuilder builder = new StringBuilder();
                 // reconvert the Vector into a String
-                for (int k = 0; k < tmpV.size(); k++) {
-                    tmpVStr.append(tmpV.get(k));
+                for (String element : list) {
+                    builder.append(element);
                 }
-                text[markup.fileIndex][markup.lineIndex] = tmpVStr.toString();
+                text[markup.fileIndex][markup.lineIndex] = builder.toString();
             } else {
                 text[markup.fileIndex][markup.lineIndex] = tmp.substring(0, (Math.min(tmp.length(), markup.column))) + markup.text
                         + tmp.substring((Math.min(tmp.length(), markup.column)));
@@ -410,7 +410,7 @@ public class Report { // Mostly legacy code with some minor improvements.
     /**
      * Write the index.html file.
      */
-    private void writeIndex() throws ExitException {
+    private void writeIndex() throws ReportGenerationException {
         HTMLFile htmlFile = createHTMLFile("index.html");
 
         writeIndexBegin(htmlFile, msg.getString("Report.Search_Results"));
@@ -476,7 +476,7 @@ public class Report { // Mostly legacy code with some minor improvements.
      * i is the number of the match j == 0 if subA is considered, otherwise it is subB This procedure uses only the
      * getIndex() method of the token. It is meant to be used with the Character front end
      */
-    private void writeIndexedSubmission(HTMLFile f, int i, JPlagComparison comparison, int j) throws ExitException {
+    private void writeIndexedSubmission(HTMLFile f, int i, JPlagComparison comparison, int j) throws ReportGenerationException {
         boolean useFirst = j == 0;
         Submission sub = comparison.getSubmission(useFirst);
         String[] files = comparison.files(j);
@@ -581,7 +581,7 @@ public class Report { // Mostly legacy code with some minor improvements.
         htmlFile.println("<!---->");
     }
 
-    private void writeMatch(JPlagComparison comparison, int i) throws ExitException {
+    private void writeMatch(JPlagComparison comparison, int i) throws ReportGenerationException {
         HTMLFile htmlFile = createHTMLFile("match" + i + ".html");
 
         writeHTMLHeader(htmlFile, TagParser.parse(msg.getString("Report.Matches_for_X1_AND_X2"),
@@ -682,18 +682,17 @@ public class Report { // Mostly legacy code with some minor improvements.
     /*
      * i is the number of the match j == 0 if subA is considered, otherwise (j must then be 1) it is subB
      */
-    private void writeNormalSubmission(HTMLFile f, int i, JPlagComparison comparison, int j) throws ExitException {
+    private void writeNormalSubmission(HTMLFile f, int i, JPlagComparison comparison, int j) throws ReportGenerationException {
         Submission sub = comparison.getSubmission(j == 0);
         String[] files = comparison.files(j);
 
         String[][] text = sub.readFiles(files);
 
         TokenList tokens = comparison.getSubmission(j == 0).getTokenList();
-        Match currentMatch;
         String hilf;
         int h;
         for (int x = 0; x < comparison.getMatches().size(); x++) {
-            currentMatch = comparison.getMatches().get(x);
+            Match currentMatch = comparison.getMatches().get(x);
 
             Token start = tokens.getToken(currentMatch.getStart(j == 0));
             Token end = tokens.getToken((currentMatch.getStart(j == 0)) + currentMatch.getLength() - 1);
@@ -727,8 +726,7 @@ public class Report { // Mostly legacy code with some minor improvements.
         if (result.getOptions().hasBaseCode() && comparison.getFirstBaseCodeMatches() != null && comparison.getSecondBaseCodeMatches() != null) {
             JPlagComparison baseCodeComparison = comparison.getBaseCodeMatches(j == 0);
 
-            for (int x = 0; x < baseCodeComparison.getMatches().size(); x++) {
-                currentMatch = baseCodeComparison.getMatches().get(x);
+            for (Match currentMatch : baseCodeComparison.getMatches()) {
                 Token start = tokens.getToken(currentMatch.getStartOfFirst());
                 Token end = tokens.getToken(currentMatch.getStartOfFirst() + currentMatch.getLength() - 1);
 

+ 2 - 0
jplag/src/test/java/de/jplag/BaseCodeTest.java

@@ -6,6 +6,8 @@ import java.io.File;
 
 import org.junit.Test;
 
+import de.jplag.exceptions.ExitException;
+
 public class BaseCodeTest extends TestBase {
 
     @Test

+ 2 - 0
jplag/src/test/java/de/jplag/JPlagComparisonTest.java

@@ -7,6 +7,8 @@ import java.util.List;
 
 import org.junit.Test;
 
+import de.jplag.exceptions.ExitException;
+
 public class JPlagComparisonTest extends TestBase {
 
     private static final String[] FILES = {"GSTiling.java", "Match.java", "Matches.java", "Structure.java", "Submission.java", "Table.java", "Token.java"};

+ 2 - 0
jplag/src/test/java/de/jplag/NewJavaFeaturesTest.java

@@ -4,6 +4,8 @@ import static org.junit.Assert.assertEquals;
 
 import org.junit.Test;
 
+import de.jplag.exceptions.ExitException;
+
 public class NewJavaFeaturesTest extends TestBase {
     private static final String EXCLUSION_FILE_NAME = "blacklist.txt";
     private static final String ROOT_DIRECTORY = "NewJavaFeatures";

+ 2 - 0
jplag/src/test/java/de/jplag/NormalComparisonTest.java

@@ -6,6 +6,8 @@ import java.util.Optional;
 
 import org.junit.Test;
 
+import de.jplag.exceptions.ExitException;
+
 public class NormalComparisonTest extends TestBase {
 
     /**

+ 1 - 0
jplag/src/test/java/de/jplag/ParallelComparisonTest.java

@@ -7,6 +7,7 @@ import java.util.Optional;
 
 import org.junit.Test;
 
+import de.jplag.exceptions.ExitException;
 import de.jplag.strategy.ParallelComparisonStrategy;
 
 /**

+ 1 - 0
jplag/src/test/java/de/jplag/TestBase.java

@@ -3,6 +3,7 @@ package de.jplag;
 import java.nio.file.Path;
 import java.util.function.Consumer;
 
+import de.jplag.exceptions.ExitException;
 import de.jplag.options.JPlagOptions;
 import de.jplag.options.LanguageOption;
 import de.jplag.options.Verbosity;

+ 1 - 0
jplag/src/test/java/de/jplag/VolumeTest.java

@@ -13,6 +13,7 @@ import java.util.Map;
 
 import org.junit.Test;
 
+import de.jplag.exceptions.ExitException;
 import de.jplag.options.JPlagOptions;
 
 /**

+ 1 - 1
jplag/src/test/java/de/jplag/cli/MinTokenMatchTest.java

@@ -10,8 +10,8 @@ import org.junit.Test;
 import org.junit.contrib.java.lang.system.ExpectedSystemExit;
 
 import de.jplag.CommandLineArgument;
-import de.jplag.ExitException;
 import de.jplag.JPlag;
+import de.jplag.exceptions.ExitException;
 
 public class MinTokenMatchTest extends CommandLineInterfaceTest {