[MCHECKSTYLE-446] Dynamically calculate xrefLocation/xrefTestLocation
diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/AbstractCheckstyleReport.java b/src/main/java/org/apache/maven/plugins/checkstyle/AbstractCheckstyleReport.java
index 57dade9..508566f 100644
--- a/src/main/java/org/apache/maven/plugins/checkstyle/AbstractCheckstyleReport.java
+++ b/src/main/java/org/apache/maven/plugins/checkstyle/AbstractCheckstyleReport.java
@@ -26,6 +26,7 @@
 import java.io.OutputStream;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -41,6 +42,7 @@
 import org.apache.maven.model.Plugin;
 import org.apache.maven.model.PluginManagement;
 import org.apache.maven.model.ReportPlugin;
+import org.apache.maven.model.Reporting;
 import org.apache.maven.model.Resource;
 import org.apache.maven.plugin.descriptor.PluginDescriptor;
 import org.apache.maven.plugins.annotations.Component;
@@ -345,8 +347,8 @@
     private PluginDescriptor plugin;
 
     /**
-     * Link the violation line numbers to the source xref. Will link
-     * automatically if Maven JXR plugin is being used.
+     * Link the violation line numbers to the (Test) Source XRef. Links will be created automatically if the JXR plugin is
+     * being used.
      *
      * @since 2.1
      */
@@ -354,15 +356,19 @@
     private boolean linkXRef;
 
     /**
-     * Location of the Xrefs to link to.
+     * Location where Source XRef is generated for this project.
+     * <br>
+     * <strong>Default</strong>: {@link #getReportOutputDirectory()} + {@code /xref}
      */
-    @Parameter(defaultValue = "${project.reporting.outputDirectory}/xref")
+    @Parameter
     private File xrefLocation;
 
     /**
-     * Location of the XrefTests to link to.
+     * Location where Test Source XRef is generated for this project.
+     * <br>
+     * <strong>Default</strong>: {@link #getReportOutputDirectory()} + {@code /xref-test}
      */
-    @Parameter(defaultValue = "${project.reporting.outputDirectory}/xref-test")
+    @Parameter
     private File xrefTestLocation;
 
     /**
@@ -482,6 +488,45 @@
         return reactorProjects;
     }
 
+    protected String constructXrefLocation(boolean test, boolean haveResults) {
+        String location = null;
+        if (linkXRef) {
+            File xrefLocation = getXrefLocation(test);
+
+            String relativePath = PathTool.getRelativePath(
+                    getReportOutputDirectory().getAbsolutePath(), xrefLocation.getAbsolutePath());
+            if (relativePath == null || relativePath.isEmpty()) {
+                relativePath = ".";
+            }
+            relativePath = relativePath + "/" + xrefLocation.getName();
+            if (xrefLocation.exists()) {
+                // XRef was already generated by manual execution of a lifecycle binding
+                location = relativePath;
+            } else {
+                // Not yet generated - check if the report is on its way
+                Reporting reporting = project.getModel().getReporting();
+                List<ReportPlugin> reportPlugins =
+                        reporting != null ? reporting.getPlugins() : Collections.<ReportPlugin>emptyList();
+                for (ReportPlugin plugin : reportPlugins) {
+                    String artifactId = plugin.getArtifactId();
+                    if ("maven-jxr-plugin".equals(artifactId) || "jxr-maven-plugin".equals(artifactId)) {
+                        location = relativePath;
+                    }
+                }
+            }
+
+            if (location == null && haveResults) {
+                getLog().warn("Unable to locate" + (test ? " Test" : "") + " Source XRef to link to - DISABLED");
+            }
+        }
+        return location;
+    }
+
+    protected File getXrefLocation(boolean test) {
+        File location = test ? xrefTestLocation : xrefLocation;
+        return location != null ? location : new File(getReportOutputDirectory(), test ? "xref-test" : "xref");
+    }
+
     /** {@inheritDoc} */
     public void executeReport(Locale locale) throws MavenReportException {
         checkDeprecatedParameterUsage(sourceDirectory, "sourceDirectory", "sourceDirectories");
@@ -527,6 +572,7 @@
 
             CheckstyleResults results = checkstyleExecutor.executeCheckstyle(request);
 
+            boolean haveResults = results.getFileCount() > 0;
             CheckstyleReportRenderer r = new CheckstyleReportRenderer(
                     getSink(),
                     i18n,
@@ -534,23 +580,13 @@
                     project,
                     siteTool,
                     effectiveConfigLocation,
+                    constructXrefLocation(false, haveResults),
+                    constructXrefLocation(true, haveResults),
+                    linkXRef ? getTestSourceDirectories() : Collections.emptyList(),
                     enableRulesSummary,
                     enableSeveritySummary,
                     enableFilesSummary,
                     results);
-            if (linkXRef) {
-                initializeXrefLocation(r);
-                if (r.getXrefLocation() == null && results.getFileCount() > 0) {
-                    getLog().warn("Unable to locate Source XRef to link to - DISABLED");
-                }
-
-                initializeXrefTestLocation(r);
-                if (r.getXrefTestLocation() == null && results.getFileCount() > 0) {
-                    getLog().warn("Unable to locate Test Source XRef to link to - DISABLED");
-                }
-
-                r.setTestSourceDirectories(getTestSourceDirectories());
-            }
             if (treeWalkerNames != null) {
                 r.setTreeWalkerNames(treeWalkerNames);
             }
@@ -675,24 +711,6 @@
         return consoleListener;
     }
 
-    private void initializeXrefLocation(CheckstyleReportRenderer renderer) {
-        String relativePath = determineRelativePath(xrefLocation);
-        if (xrefLocation.exists() || checkMavenJxrPluginIsConfigured()) {
-            // XRef was already generated by manual execution of a lifecycle binding
-            // the report is on its way
-            renderer.setXrefLocation(relativePath);
-        }
-    }
-
-    private void initializeXrefTestLocation(CheckstyleReportRenderer renderer) {
-        String relativePath = determineRelativePath(xrefTestLocation);
-        if (xrefTestLocation.exists() || checkMavenJxrPluginIsConfigured()) {
-            // XRef was already generated by manual execution of a lifecycle binding
-            // the report is on its way
-            renderer.setXrefTestLocation(relativePath);
-        }
-    }
-
     private String determineRelativePath(File location) {
         String relativePath =
                 PathTool.getRelativePath(getReportOutputDirectory().getAbsolutePath(), location.getAbsolutePath());
@@ -703,17 +721,6 @@
         return relativePath + "/" + location.getName();
     }
 
-    private boolean checkMavenJxrPluginIsConfigured() {
-        for (ReportPlugin report : (Iterable<ReportPlugin>) getProject().getReportPlugins()) {
-            String artifactId = report.getArtifactId();
-            if ("maven-jxr-plugin".equals(artifactId) || "jxr-maven-plugin".equals(artifactId)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
     protected List<File> getSourceDirectories() {
         if (sourceDirectories == null) {
             sourceDirectories = filterBuildTarget(project.getCompileSourceRoots());
diff --git a/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleReportRenderer.java b/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleReportRenderer.java
index b1dd166..3e985fb 100644
--- a/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleReportRenderer.java
+++ b/src/main/java/org/apache/maven/plugins/checkstyle/CheckstyleReportRenderer.java
@@ -69,7 +69,7 @@
 
     private String xrefTestLocation;
 
-    private List<File> testSourceDirectories = new ArrayList<>();
+    private List<File> testSourceDirectories;
 
     private List<String> treeWalkerNames = Collections.singletonList("TreeWalker");
 
@@ -84,6 +84,9 @@
             MavenProject project,
             SiteTool siteTool,
             String ruleset,
+            String xrefLocation,
+            String xrefTestLocation,
+            List<File> testSourceDirectories,
             boolean enableRulesSummary,
             boolean enableSeveritySummary,
             boolean enableFilesSummary,
@@ -94,6 +97,9 @@
         this.project = project;
         this.siteTool = siteTool;
         this.ruleset = ruleset;
+        this.xrefLocation = xrefLocation;
+        this.xrefTestLocation = xrefTestLocation;
+        this.testSourceDirectories = testSourceDirectories;
         this.enableRulesSummary = enableRulesSummary;
         this.enableSeveritySummary = enableSeveritySummary;
         this.enableFilesSummary = enableFilesSummary;
@@ -541,9 +547,9 @@
     private String getEffectiveXrefLocation(List<AuditEvent> eventList) {
         String absoluteFilename = eventList.get(0).getFileName();
         if (isTestSource(absoluteFilename)) {
-            return getXrefTestLocation();
+            return xrefTestLocation;
         } else {
-            return getXrefLocation();
+            return xrefLocation;
         }
     }
 
@@ -557,26 +563,6 @@
         return false;
     }
 
-    public String getXrefLocation() {
-        return xrefLocation;
-    }
-
-    public void setXrefLocation(String xrefLocation) {
-        this.xrefLocation = xrefLocation;
-    }
-
-    public String getXrefTestLocation() {
-        return xrefTestLocation;
-    }
-
-    public void setXrefTestLocation(String xrefTestLocation) {
-        this.xrefTestLocation = xrefTestLocation;
-    }
-
-    public void setTestSourceDirectories(List<File> testSourceDirectories) {
-        this.testSourceDirectories = testSourceDirectories;
-    }
-
     public void setTreeWalkerNames(List<String> treeWalkerNames) {
         this.treeWalkerNames = treeWalkerNames;
     }