diff --git a/docs/maven-plugin.md b/docs/maven-plugin.md
index c69b02e5..9628e450 100644
--- a/docs/maven-plugin.md
+++ b/docs/maven-plugin.md
@@ -116,10 +116,10 @@ Parameters:
| **spotbugsRuleset** | String | Relative path to the XML that specifies the bug detectors which should be run. If not set the default file will be used|
| **spotbugsInclude** | String | Relative path to the XML that specifies the bug instances that will be included in the report. If not set the default file will be used|
| **spotbugsExclude** | String | Relative path to the XML that specifies the bug instances that will be excluded from the report. If not set the default file will be used|
-| **maven.spotbugs.version** | String | The version of the spotbugs-maven-plugin that will be used (default value is **3.1.6**)|
-| **spotbugs.version** | String | The version of SpotBugs that will be used (default value is **3.1.7**)|
+| **maven.spotbugs.version** | String | The version of the spotbugs-maven-plugin that will be used (default value is **3.1.12.2**)|
+| **spotbugs.version** | String | The version of SpotBugs that will be used (default value is **3.1.12**)|
| **spotbugsPlugins** | List | A list with artifacts that contain additional detectors/patterns for SpotBugs |
-| **findbugs.slf4j.version** | String | The version of the findbugs-slf4j plugin that will be used (default value is **1.2.4**)|
+| **findbugs.slf4j.version** | String | The version of the findbugs-slf4j plugin that will be used (default value is **1.5.0**)|
### sat-plugin:report
diff --git a/pom.xml b/pom.xml
index c6a9b7f3..fcffb500 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,7 +9,7 @@
0.9.0-SNAPSHOT
pom
- Static Code Analysis Tool Parent Pom
+ Static Code Analysis Tool Parent POM
Tool that aggregates reports of PMD, Checkstyle and FindBugs
https://github.com/openhab/static-code-analysis
@@ -21,8 +21,8 @@
- openhab.org
- http://www.openhab.org
+ openHAB.org
+ https://www.openhab.org
@@ -37,7 +37,7 @@
git@github.com:openhab/static-code-analysis.git
- github
+ GitHub
https://github.com/openhab/static-code-analysis/issues
@@ -51,20 +51,21 @@
2.4
6.7.0
8.12
- 3.1.7
- 3.1.1
+ 3.1.12
+ 3.5.0
+ 3.5.0
3.5
3.5
3.6.1
- 2.2.0
+ 2.3.0
2.4.0
1.7.1
3.11.1
- 0.6.1
+ 0.8.0
2.1.0
0.28.6
2.12.4
- 9.3.14.v20161028
+ 9.4.20.v20190813
9.1.0.8
@@ -186,7 +187,7 @@
2.4.3-01
-
+
org.apache.maven.plugins
maven-source-plugin
@@ -227,7 +228,7 @@
-
+
junit
@@ -262,9 +263,10 @@
test
-
+
custom-checks
+ sat-extension
sat-plugin
codestyle
diff --git a/sat-extension/pom.xml b/sat-extension/pom.xml
new file mode 100644
index 00000000..da8636d9
--- /dev/null
+++ b/sat-extension/pom.xml
@@ -0,0 +1,89 @@
+
+
+
+ 4.0.0
+
+
+ org.openhab.tools.sat
+ pom
+ 0.9.0-SNAPSHOT
+
+
+ sat-extension
+
+ Static Code Analysis Tool Maven Extension
+ Generates HTML summaries from analysis results
+
+
+
+
+ org.apache.maven
+ maven-core
+ ${maven.core.version}
+ provided
+
+
+
+
+ org.openhab.tools.sat
+ sat-plugin
+ ${project.version}
+
+
+
+
+ net.sourceforge.saxon
+ saxon
+ ${saxon.version}
+
+
+
+
+
+
+ org.codehaus.plexus
+ plexus-component-metadata
+ 1.7.1
+
+
+
+ generate-metadata
+ generate-test-metadata
+
+
+
+
+
+
+
+
+ org.eclipse.m2e
+ lifecycle-mapping
+ 1.0.0
+
+
+
+
+
+ org.codehaus.plexus
+ plexus-component-metadata
+ [1.7.1,)
+
+ generate-metadata
+ generate-test-metadata
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportExecutionListener.java b/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportExecutionListener.java
new file mode 100644
index 00000000..eeefcfb7
--- /dev/null
+++ b/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportExecutionListener.java
@@ -0,0 +1,265 @@
+/**
+ * Copyright (c) 2010-2019 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.tools.analysis.report;
+
+import static org.openhab.tools.analysis.report.ReportUtil.*;
+
+import java.io.File;
+import java.time.Instant;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import org.apache.maven.execution.AbstractExecutionListener;
+import org.apache.maven.execution.ExecutionEvent;
+import org.apache.maven.execution.ExecutionListener;
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.plugin.PluginParameterExpressionEvaluator;
+import org.apache.maven.plugin.descriptor.Parameter;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException;
+import org.codehaus.plexus.logging.Logger;
+
+/**
+ * Listens to Maven executions, delegates events to the default {@link ExecutionListener} and updates HTML summaries
+ * based on SAT plugin configuration values.
+ *
+ * @author Wouter Born - Initial contribution
+ */
+@Component(role = SummaryReportExecutionListener.class)
+public class SummaryReportExecutionListener extends AbstractExecutionListener {
+
+ @Requirement
+ private Logger logger;
+
+ @Requirement
+ private SummaryReportHtmlGenerator summaryReportHtmlGenerator;
+
+ private final ExecutorService executor = Executors.newSingleThreadExecutor();
+
+ /**
+ * The default ExecutionListener
+ */
+ private ExecutionListener listener;
+
+ /**
+ * Maps each directory for which a summary report needs to be generated to a {@link SummaryUpdater}.
+ */
+ private final Map summaryUpdaters = Collections.synchronizedMap(new HashMap<>());
+
+ /**
+ * Updates HTML summaries in a directory based on SAT plugin configuration values.
+ */
+ private class SummaryUpdater {
+ private final String directory;
+ private final SummaryHtmlGeneration htmlGeneration;
+ private final int htmlGenerationPeriod;
+ private Instant lastUpdate = Instant.MIN;
+
+ public SummaryUpdater(String directory, SummaryHtmlGeneration htmlGeneration, int htmlGenerationPeriod) {
+ this.directory = directory;
+ this.htmlGeneration = htmlGeneration;
+ this.htmlGenerationPeriod = htmlGenerationPeriod;
+ }
+
+ private File update() {
+ File latestSummaryReport = summaryReportHtmlGenerator.generateHtmlSummaryByRules(directory);
+ lastUpdate = Instant.now();
+ return latestSummaryReport;
+ }
+
+ public void incrementalUpdate() {
+ executor.submit(() -> {
+ if (htmlGeneration == SummaryHtmlGeneration.CONTINUOUS
+ || (htmlGeneration == SummaryHtmlGeneration.PERIODIC
+ && Instant.now().isAfter(lastUpdate.plusSeconds(htmlGenerationPeriod)))) {
+ File latestSummaryReport = update();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("Updated static code analysis summary report in:");
+ logger.debug(latestSummaryReport.toURI().toString());
+ }
+ }
+ });
+ }
+
+ public void finalUpdate() {
+ if (htmlGeneration != SummaryHtmlGeneration.NEVER) {
+ File latestSummaryReport = update();
+
+ if (latestSummaryReport != null) {
+ logger.info("Static code analysis summary report is available in:");
+ logger.info(latestSummaryReport.toURI().toString());
+ }
+ }
+ }
+ }
+
+ public void chainListener(MavenSession session) {
+ listener = session.getRequest().getExecutionListener();
+ session.getRequest().setExecutionListener(this);
+ }
+
+ private void generateSummaryReportForExecution(ExecutionEvent event) {
+ try {
+ getOrCreateSummaryUpdater(event).incrementalUpdate();
+ } catch (ExpressionEvaluationException e) {
+ logger.error("Exception while evaluating '" + DIRECTORY_PARAMETER + "' plugin parameter", e);
+ }
+ }
+
+ private SummaryUpdater getOrCreateSummaryUpdater(ExecutionEvent event) throws ExpressionEvaluationException {
+ String directory = getPluginParameterValue(event, DIRECTORY_PARAMETER);
+ SummaryUpdater summaryUpdater;
+ synchronized (summaryUpdaters) {
+ summaryUpdater = summaryUpdaters.get(directory);
+ if (summaryUpdater == null) {
+ SummaryHtmlGeneration htmlGeneration = SummaryHtmlGeneration
+ .valueOf(getPluginParameterValue(event, HTML_GENERATION_PARAMETER).toUpperCase());
+ int htmlGenerationPeriod = Integer
+ .parseInt(getPluginParameterValue(event, HTML_GENERATION_PERIOD_PARAMETER));
+
+ summaryUpdater = new SummaryUpdater(directory, htmlGeneration, htmlGenerationPeriod);
+ summaryUpdaters.put(directory, summaryUpdater);
+ }
+ }
+ return summaryUpdater;
+ }
+
+ private String getPluginParameterValue(ExecutionEvent event, String parameterName)
+ throws ExpressionEvaluationException {
+ Parameter parameter = event.getMojoExecution().getMojoDescriptor().getParameterMap().get(parameterName);
+
+ PluginParameterExpressionEvaluator evaluator = getEvaluator(event);
+ String parameterValue = (String) evaluator.evaluate(parameter.getExpression());
+ if (parameterValue == null) {
+ parameterValue = (String) evaluator.evaluate(parameter.getDefaultValue());
+ }
+ return parameterValue;
+ }
+
+ public void generateFinalSummaryReports() {
+ synchronized (summaryUpdaters) {
+ summaryUpdaters.values().forEach(SummaryUpdater::finalUpdate);
+ }
+ }
+
+ private PluginParameterExpressionEvaluator getEvaluator(ExecutionEvent event) {
+ PluginParameterExpressionEvaluator evaluator;
+ MavenSession session = event.getSession();
+ MavenProject currentProject = session.getCurrentProject();
+ // Maven 3: PluginParameterExpressionEvaluator gets the current project from the session:
+ // synchronize in case another thread wants to fetch the real current project in between
+ synchronized (session) {
+ session.setCurrentProject(event.getProject());
+ evaluator = new PluginParameterExpressionEvaluator(session, event.getMojoExecution());
+ session.setCurrentProject(currentProject);
+ }
+ return evaluator;
+ }
+
+ // These overrides make sure the original listener still receives all events
+
+ @Override
+ public void projectDiscoveryStarted(ExecutionEvent event) {
+ listener.projectDiscoveryStarted(event);
+ }
+
+ @Override
+ public void sessionStarted(ExecutionEvent event) {
+ listener.sessionStarted(event);
+ }
+
+ @Override
+ public void sessionEnded(ExecutionEvent event) {
+ listener.sessionEnded(event);
+ }
+
+ @Override
+ public void projectSkipped(ExecutionEvent event) {
+ listener.projectSkipped(event);
+ }
+
+ @Override
+ public void projectStarted(ExecutionEvent event) {
+ listener.projectStarted(event);
+ }
+
+ @Override
+ public void projectSucceeded(ExecutionEvent event) {
+ listener.projectSucceeded(event);
+ }
+
+ @Override
+ public void projectFailed(ExecutionEvent event) {
+ listener.projectFailed(event);
+ }
+
+ @Override
+ public void forkStarted(ExecutionEvent event) {
+ listener.forkStarted(event);
+ }
+
+ @Override
+ public void forkSucceeded(ExecutionEvent event) {
+ listener.forkSucceeded(event);
+ }
+
+ @Override
+ public void forkFailed(ExecutionEvent event) {
+ listener.forkFailed(event);
+ }
+
+ @Override
+ public void mojoSkipped(ExecutionEvent event) {
+ listener.mojoSkipped(event);
+ }
+
+ @Override
+ public void mojoStarted(ExecutionEvent event) {
+ listener.mojoStarted(event);
+ }
+
+ @Override
+ public void mojoSucceeded(ExecutionEvent event) {
+ listener.mojoSucceeded(event);
+ if (isReportExecution(event)) {
+ generateSummaryReportForExecution(event);
+ }
+ }
+
+ @Override
+ public void mojoFailed(ExecutionEvent event) {
+ listener.mojoFailed(event);
+ }
+
+ @Override
+ public void forkedProjectStarted(ExecutionEvent event) {
+ listener.forkedProjectStarted(event);
+ }
+
+ @Override
+ public void forkedProjectSucceeded(ExecutionEvent event) {
+ listener.forkedProjectSucceeded(event);
+ }
+
+ @Override
+ public void forkedProjectFailed(ExecutionEvent event) {
+ listener.forkedProjectFailed(event);
+ }
+
+}
diff --git a/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportHtmlGenerator.java b/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportHtmlGenerator.java
new file mode 100644
index 00000000..5e35a227
--- /dev/null
+++ b/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportHtmlGenerator.java
@@ -0,0 +1,155 @@
+/**
+ * Copyright (c) 2010-2019 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.tools.analysis.report;
+
+import static org.openhab.tools.analysis.report.ReportUtil.*;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLockInterruptionException;
+import java.text.MessageFormat;
+import java.time.Duration;
+import java.time.Instant;
+
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+import org.codehaus.plexus.logging.Logger;
+
+import com.google.common.io.Files;
+
+import net.sf.saxon.TransformerFactoryImpl;
+
+/**
+ * Generates HTML report summaries based on the the content in the merge XML file using XSLT.
+ *
+ * @author Wouter Born - Initial contribution
+ */
+@Component(role = SummaryReportHtmlGenerator.class)
+public class SummaryReportHtmlGenerator {
+
+ @Requirement
+ private Logger logger;
+
+ private TransformerFactory transformerFactory;
+
+ private ClassLoader contextClassLoader;
+
+ void initialize() {
+ contextClassLoader = Thread.currentThread().getContextClassLoader();
+ transformerFactory = TransformerFactory.newInstance(TransformerFactoryImpl.class.getName(), contextClassLoader);
+ }
+
+ File generateHtmlSummaryByRules(final String summaryReportDirectory) {
+ File latestMergeResult = new File(summaryReportDirectory, MERGE_XML_FILE_NAME);
+ File latestMergeResultCopy = new File(summaryReportDirectory, SUMMARY_XML_FILE_NAME);
+
+ FileChannel mergeLockFileChannel = null;
+ FileChannel summaryLockFileChannel = null;
+
+ try {
+ // Acquire the merge and summary locks
+ mergeLockFileChannel = acquireFileLock(summaryReportDirectory, MERGE_LOCK_FILE_NAME);
+ if (!latestMergeResult.exists()) {
+ return null;
+ }
+ summaryLockFileChannel = acquireFileLock(summaryReportDirectory, SUMMARY_LOCK_FILE_NAME);
+
+ // Copy merge.xml to summary.xml which is used for generating the report
+ Files.copy(latestMergeResult, latestMergeResultCopy);
+
+ // Release the merge lock so plugin reporting goals executed in parallel can keep merging
+ closeFileChannel(mergeLockFileChannel);
+
+ File latestSummaryReport = new File(summaryReportDirectory, SUMMARY_REPORT_FILE_NAME);
+ run(CREATE_HTML_XSLT, latestMergeResultCopy, latestSummaryReport);
+
+ if (!latestMergeResultCopy.delete()) {
+ logger.error("Unable to delete file: " + latestMergeResultCopy.getAbsolutePath());
+ }
+
+ return latestSummaryReport;
+ } catch (InterruptedException | FileLockInterruptionException e) {
+ Thread.currentThread().interrupt();
+ } catch (IOException e) {
+ throw new IllegalStateException("Exception while acquiring lock file", e);
+ } finally {
+ closeFileChannel(mergeLockFileChannel);
+ closeFileChannel(summaryLockFileChannel);
+ }
+ return null;
+ }
+
+ private void closeFileChannel(FileChannel fileChannel) {
+ if (fileChannel != null) {
+ try {
+ fileChannel.close();
+ } catch (IOException e) {
+ logger.error("Exception while closing file channel: " + fileChannel, e);
+ }
+ }
+ }
+
+ private FileChannel acquireFileLock(final String summaryReportDirectory, final String fileName)
+ throws InterruptedException, FileLockInterruptionException {
+ File mergeLockFile = new File(summaryReportDirectory, fileName);
+ try {
+ return ReportUtil.acquireFileLock(mergeLockFile);
+ } catch (IOException e) {
+ throw new IllegalStateException("Exception while acquiring lock file: " + mergeLockFile, e);
+ }
+ }
+
+ private void run(final String xslt, final File input, final File output) {
+ try (FileOutputStream outputStream = new FileOutputStream(output)) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(MessageFormat.format("{0} > {1} > {2}", input, xslt, output));
+ }
+
+ // Process the Source into a Transformer Object
+ final InputStream inputStream = contextClassLoader.getResourceAsStream(xslt);
+ final BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+ final StreamSource source = new StreamSource(reader);
+
+ final Transformer transformer = transformerFactory.newTransformer(source);
+
+ final StreamResult outputTarget = new StreamResult(outputStream);
+ final StreamSource xmlSource = new StreamSource(input);
+
+ // Transform the XML Source to a Result
+ Instant start = Instant.now();
+ transformer.transform(xmlSource, outputTarget);
+ Instant end = Instant.now();
+
+ if (logger.isDebugEnabled()) {
+ logger.debug(MessageFormat.format("Transformation '{0}' took {1}ms", xslt,
+ Duration.between(start, end).toMillis()));
+ }
+ } catch (IOException e) {
+ logger.error("IOException occurred", e);
+ } catch (TransformerException e) {
+ logger.error("TransformerException occurred", e);
+ }
+ }
+
+}
diff --git a/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportLifecycleParticipant.java b/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportLifecycleParticipant.java
new file mode 100644
index 00000000..39730c3c
--- /dev/null
+++ b/sat-extension/src/main/java/org/openhab/tools/analysis/report/SummaryReportLifecycleParticipant.java
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2010-2019 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.tools.analysis.report;
+
+import org.apache.maven.AbstractMavenLifecycleParticipant;
+import org.apache.maven.MavenExecutionException;
+import org.apache.maven.execution.MavenSession;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.component.annotations.Requirement;
+
+/**
+ * Handles {@link MavenSession} events so the SAT extension can generate HTML report summaries.
+ *
+ * @author Wouter Born - Initial contribution
+ */
+@Component(role = AbstractMavenLifecycleParticipant.class)
+public class SummaryReportLifecycleParticipant extends AbstractMavenLifecycleParticipant {
+
+ @Requirement
+ private SummaryReportExecutionListener summaryReportExecutionListener;
+
+ @Requirement
+ private SummaryReportHtmlGenerator summaryReportHtmlGenerator;
+
+ @Override
+ public void afterProjectsRead(MavenSession session) throws MavenExecutionException {
+ // The context class loader of the current thread needs to be used with the
+ // SummaryReportHtmlGenerator or it will not find the XSLT files on the class path
+ summaryReportHtmlGenerator.initialize();
+ summaryReportExecutionListener.chainListener(session);
+ }
+
+ @Override
+ public void afterSessionEnd(MavenSession session) throws MavenExecutionException {
+ summaryReportExecutionListener.generateFinalSummaryReports();
+ }
+}
diff --git a/sat-plugin/pom.xml b/sat-plugin/pom.xml
index 6720f328..975efc77 100644
--- a/sat-plugin/pom.xml
+++ b/sat-plugin/pom.xml
@@ -58,7 +58,7 @@
-
+
maven-plugin-plugin
${maven.plugin.plugin.version}
@@ -78,7 +78,7 @@
-
+
-
+
diff --git a/sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportUtility.java b/sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportMojo.java
similarity index 83%
rename from sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportUtility.java
rename to sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportMojo.java
index 1616edcd..fa92abe8 100644
--- a/sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportUtility.java
+++ b/sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportMojo.java
@@ -35,6 +35,8 @@
*/
package org.openhab.tools.analysis.report;
+import static org.openhab.tools.analysis.report.ReportUtil.*;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
@@ -42,10 +44,13 @@
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
+import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
+import java.time.Duration;
+import java.time.Instant;
import java.util.Date;
import java.util.LinkedList;
import java.util.Queue;
@@ -88,14 +93,14 @@
* MarkusSprunck/static-
* code-analysis-report
*
- * @author Markus Sprunck - Initial Implementation
+ * @author Markus Sprunck - Initial contribution
* @author Svilen Valkanov - Some minor changes and adaptations
* @author Petar Valchev - Changed the logging to be parameterized
* @author Martin van Wingerden - added maven console logging of all messages
+ * @author Wouter Born - Synchronize summary updates to make Mojo thread-safe
*/
-
-@Mojo(name = "report")
-public class ReportUtility extends AbstractMojo {
+@Mojo(name = "report", threadSafe = true)
+public class ReportMojo extends AbstractMojo {
/**
* The directory where the individual report will be generated
@@ -116,30 +121,14 @@ public class ReportUtility extends AbstractMojo {
@Parameter(property = "report.summary.targetDir", defaultValue = "${session.executionRootDirectory}/target")
private File summaryReportDirectory;
- private static final String REPORT_SUBDIR = "report";
-
@Parameter(property = "report.in.maven", defaultValue = "true")
private boolean reportInMaven;
- // XSLT files that are used to create the merged report, located in the resources folder
- private static final String CREATE_HTML_XSLT = REPORT_SUBDIR + "/create_html.xslt";
- private static final String MERGE_XSLT = REPORT_SUBDIR + "/merge.xslt";
- private static final String PREPARE_PMD_XSLT = REPORT_SUBDIR + "/prepare_pmd.xslt";
- private static final String PREPARE_CHECKSTYLE_XSLT = REPORT_SUBDIR + "/prepare_checkstyle.xslt";
- private static final String PREPARE_FINDBUGS_XSLT = REPORT_SUBDIR + "/prepare_findbugs.xslt";
-
- private static final String SUMMARY_TEMPLATE_FILE_NAME = "summary.html";
+ @Parameter(property = "report.summary.html.generation", defaultValue = "PERIODIC")
+ private SummaryHtmlGeneration summaryHtmlGeneration;
- // Input files that contain the reports of the different tools
- private static final String PMD_INPUT_FILE_NAME = "pmd.xml";
- private static final String CHECKSTYLE_INPUT_FILE_NAME = "checkstyle-result.xml";
- private static final String FINDBUGS_INPUT_FILE_NAME = "spotbugsXml.xml";
-
- // Name of the file that contains the merged report
- public static final String RESULT_FILE_NAME = "report.html";
- public static final String SUMMARY_REPORT_FILE_NAME = "summary_report.html";
- public static final String SUMMARY_BUNLES_FILE_NAME = "summary_bundles.html";
- private static final String EMPTY = "";
+ @Parameter(property = "report.summary.html.generation.period", defaultValue = "60")
+ private int summaryHtmlGenerationPeriod;
private TransformerFactory transformerFactory;
@@ -217,8 +206,16 @@ public void execute() throws MojoFailureException {
// 7. Append the individual report to the summary, if it is not empty
if (summaryReportDirectory != null) {
ensureSummaryReportDirectoryExists();
- generateSummaryByBundle(htmlOutputFileName, mergedReport);
- generateSummaryByRules(htmlOutputFileName, mergedReport);
+ File mergeLockFile = new File(summaryReportDirectory, MERGE_LOCK_FILE_NAME);
+ try (FileChannel fileChannel = acquireFileLock(mergeLockFile)) {
+ generateSummaryByBundle(htmlOutputFileName, mergedReport);
+ generateSummaryByRules(htmlOutputFileName, mergedReport);
+ } catch (IOException e) {
+ throw new MojoFailureException("Exception while acquiring merge lock file: " + mergeLockFile, e);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return;
+ }
}
// 8. Report errors and warnings in Maven
@@ -228,7 +225,7 @@ public void execute() throws MojoFailureException {
// 9. Fail the build if the option is enabled and high priority warnings are found
if (failOnError) {
- checkForErrors(mergedReport, htmlOutputFileName);
+ failOnErrors(mergedReport);
}
// 10. Delete the temporary files
@@ -239,9 +236,10 @@ public void execute() throws MojoFailureException {
}
private void run(final String xslt, final File input, final File output, final String param, final File value) {
- FileOutputStream outputStream = null;
- try {
- getLog().debug(MessageFormat.format("{0} > {1} {2} {3} > {4}", input, xslt, param, value, output));
+ try (FileOutputStream outputStream = new FileOutputStream(output)) {
+ if (getLog().isDebugEnabled()) {
+ getLog().debug(MessageFormat.format("{0} > {1} {2} {3} > {4}", input, xslt, param, value, output));
+ }
// Process the Source into a Transformer Object
final InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(xslt);
@@ -254,24 +252,22 @@ private void run(final String xslt, final File input, final File output, final S
transformer.setParameter(param, value.toURI().toURL());
}
- outputStream = new FileOutputStream(output);
final StreamResult outputTarget = new StreamResult(outputStream);
final StreamSource xmlSource = new StreamSource(input);
// Transform the XML Source to a Result
+ Instant start = Instant.now();
transformer.transform(xmlSource, outputTarget);
+ Instant end = Instant.now();
+
+ if (getLog().isDebugEnabled()) {
+ getLog().debug(MessageFormat.format("Transformation '{0}' took {1}ms", xslt,
+ Duration.between(start, end).toMillis()));
+ }
} catch (IOException e) {
- getLog().error("IOException occcurred ", e);
+ getLog().error("IOException occurred", e);
} catch (TransformerException e) {
- getLog().error("TransformerException occcurred ", e);
- } finally {
- if (null != outputStream) {
- try {
- outputStream.close();
- } catch (final IOException e) {
- getLog().error(e.getMessage());
- }
- }
+ getLog().error("TransformerException occurred", e);
}
}
@@ -293,7 +289,7 @@ private void reportWarningsAndErrors(File mergedReport, File reportLocation) {
return;
}
- String format = String.format("Code Analysis Tool has found: \n %d error(s)! \n %d warning(s) \n %d info(s)",
+ String format = String.format("Code Analysis Tool has found: %n %d error(s)! %n %d warning(s) %n %d info(s)",
errorCount, warnCount, infoCount);
report(maxLevel(errorCount, warnCount, infoCount), format);
@@ -308,12 +304,12 @@ private void reportWarningsAndErrors(File mergedReport, File reportLocation) {
String line = messageNode.getAttribute("line");
String message = messageNode.getAttribute("message").trim();
- String logTemplate = "%s:[%s]\n%s";
+ String logTemplate = "%s:[%s]%n%s";
String log = String.format(logTemplate, fileName, line, message);
report(priority, log);
}
}
- getLog().info("Detailed report can be found at: file:///" + reportLocation);
+ getLog().info("Detailed report can be found at: " + reportLocation.toURI());
}
private String maxLevel(int errorCount, int warnCount, int infoCount) {
@@ -342,14 +338,13 @@ private int countPriority(NodeList messages, String priority) {
return count;
}
- private void checkForErrors(File secondMergeResult, File reportLocation) throws MojoFailureException {
- int numberOfErrors = selectNodes(secondMergeResult, "/sca/file/message[@priority=1]").getLength();
-
- if (numberOfErrors > 0) {
+ private void failOnErrors(File mergedReport) throws MojoFailureException {
+ int errorCount = selectNodes(mergedReport, "/sca/file/message[@priority=1]").getLength();
+ if (errorCount > 0) {
throw new MojoFailureException(String.format(
- "\n" + "Code Analysis Tool has found %d error(s)! \n"
- + "Please fix the errors and rerun the build. \n",
- selectNodes(secondMergeResult, "/sca/file/message[@priority=1]").getLength()));
+ "%n" + "Code Analysis Tool has found %d error(s)! %n"
+ + "Please fix the errors and rerun the build. %n",
+ selectNodes(mergedReport, "/sca/file/message[@priority=1]").getLength()));
}
}
@@ -373,8 +368,8 @@ private void ensureSummaryReportDirectoryExists() {
}
}
- private void generateSummaryByBundle(File htmlOutputFileName, File secondMergeResult) {
- NodeList nodes = selectNodes(secondMergeResult, "/sca/file/message");
+ private void generateSummaryByBundle(File htmlOutputFile, File mergedReport) {
+ NodeList nodes = selectNodes(mergedReport, "/sca/file/message");
int messagesNumber = nodes.getLength();
if (messagesNumber == 0) {
getLog().info("Empty report will not be appended to the summary report.");
@@ -382,7 +377,7 @@ private void generateSummaryByBundle(File htmlOutputFileName, File secondMergeRe
}
try {
- File summaryReport = new File(summaryReportDirectory, SUMMARY_BUNLES_FILE_NAME);
+ File summaryReport = new File(summaryReportDirectory, SUMMARY_BUNDLES_FILE_NAME);
if (!summaryReport.exists()) {
InputStream inputStream = Thread.currentThread().getContextClassLoader()
.getResourceAsStream(REPORT_SUBDIR + "/" + SUMMARY_TEMPLATE_FILE_NAME);
@@ -399,7 +394,7 @@ private void generateSummaryByBundle(File htmlOutputFileName, File secondMergeRe
String reportContent = FileUtils.readFileToString(summaryReport);
final String singleItem = "%s |
";
- Path absoluteIndividualReportPath = htmlOutputFileName.toPath();
+ Path absoluteIndividualReportPath = htmlOutputFile.toPath();
Path summaryReportDirectoryPath = summaryReportDirectory.toPath();
Path relativePath = summaryReportDirectoryPath.relativize(absoluteIndividualReportPath);
@@ -417,7 +412,7 @@ private void generateSummaryByBundle(File htmlOutputFileName, File secondMergeRe
}
private void generateSummaryByRules(final File htmlOutputFileName, final File mergedReport) {
- File latestMergeResult = new File(summaryReportDirectory, "old_Merge.xml");
+ File latestMergeResult = new File(summaryReportDirectory, MERGE_XML_FILE_NAME);
File latestSummaryReport = new File(summaryReportDirectory, SUMMARY_REPORT_FILE_NAME);
try {
@@ -427,10 +422,9 @@ private void generateSummaryByRules(final File htmlOutputFileName, final File me
Files.copy(mergedReport, latestMergeResult);
Files.copy(htmlOutputFileName, latestSummaryReport);
} else {
- final File tempMergedReport = new File(summaryReportDirectory, "temp_Merge.xml");
+ final File tempMergedReport = new File(summaryReportDirectory, MERGE_XML_TMP_FILE_NAME);
Files.copy(latestMergeResult, tempMergedReport);
run(MERGE_XSLT, tempMergedReport, latestMergeResult, "with", mergedReport);
- run(CREATE_HTML_XSLT, latestMergeResult, latestSummaryReport, EMPTY, null);
deleteFile(tempMergedReport);
}
} catch (IOException e) {
@@ -455,4 +449,5 @@ private NodeList selectNodes(File file, String xPathExpression) {
return new EmptyNodeList();
}
}
+
}
diff --git a/sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportUtil.java b/sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportUtil.java
new file mode 100644
index 00000000..b1e37b9a
--- /dev/null
+++ b/sat-plugin/src/main/java/org/openhab/tools/analysis/report/ReportUtil.java
@@ -0,0 +1,102 @@
+/**
+ * Copyright (c) 2010-2019 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.tools.analysis.report;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.OverlappingFileLockException;
+
+import org.apache.maven.execution.ExecutionEvent;
+import org.apache.maven.plugin.MojoExecution;
+
+/**
+ * Provides constants and utility methods used for generating reports.
+ *
+ * @author Wouter Born - Initial contribution
+ */
+final class ReportUtil {
+
+ // SAT plugin GAV parameters
+ static final String SAT_PLUGIN_GROUP_ID = "org.openhab.tools.sat";
+ static final String SAT_PLUGIN_ARTIFACT_ID = "sat-plugin";
+ static final String SAT_PLUGIN_REPORT_GOAL = "report";
+
+ // SAT plugin configuration parameter names
+ static final String DIRECTORY_PARAMETER = "summaryReportDirectory";
+ static final String HTML_GENERATION_PARAMETER = "summaryHtmlGeneration";
+ static final String HTML_GENERATION_PERIOD_PARAMETER = "summaryHtmlGenerationPeriod";
+
+ // XSLT files that are used to create the merged report, located in the resources folder
+ static final String REPORT_SUBDIR = "report";
+ static final String CREATE_HTML_XSLT = REPORT_SUBDIR + "/create_html.xslt";
+ static final String MERGE_XSLT = REPORT_SUBDIR + "/merge.xslt";
+ static final String PREPARE_PMD_XSLT = REPORT_SUBDIR + "/prepare_pmd.xslt";
+ static final String PREPARE_CHECKSTYLE_XSLT = REPORT_SUBDIR + "/prepare_checkstyle.xslt";
+ static final String PREPARE_FINDBUGS_XSLT = REPORT_SUBDIR + "/prepare_findbugs.xslt";
+
+ static final String SUMMARY_TEMPLATE_FILE_NAME = "summary.html";
+
+ // Input files that contain the reports of the different tools
+ static final String PMD_INPUT_FILE_NAME = "pmd.xml";
+ static final String CHECKSTYLE_INPUT_FILE_NAME = "checkstyle-result.xml";
+ static final String FINDBUGS_INPUT_FILE_NAME = "spotbugsXml.xml";
+
+ // Name of the file that contains the merged report
+ static final String RESULT_FILE_NAME = "report.html";
+ static final String SUMMARY_LOCK_FILE_NAME = "summary.lock";
+ static final String SUMMARY_REPORT_FILE_NAME = "summary_report.html";
+ static final String SUMMARY_BUNDLES_FILE_NAME = "summary_bundles.html";
+ static final String SUMMARY_XML_FILE_NAME = "summary.xml";
+ static final String EMPTY = "";
+
+ // Files used for merging the individual reports into the summary reports
+ static final String MERGE_LOCK_FILE_NAME = "merge.lock";
+ static final String MERGE_XML_FILE_NAME = "merge.xml";
+ static final String MERGE_XML_TMP_FILE_NAME = "merge.xml.tmp";
+
+ private ReportUtil() {
+ // Hidden utility class constructor
+ }
+
+ @SuppressWarnings("resource")
+ static FileChannel acquireFileLock(File file) throws IOException, InterruptedException {
+ FileChannel channel = new RandomAccessFile(file, "rw").getChannel();
+ try {
+ while (!Thread.currentThread().isInterrupted()) {
+ try {
+ // Blocking wait until file lock is acquired
+ channel.lock();
+ return channel;
+ } catch (OverlappingFileLockException e) {
+ // Another thread is locking the same file
+ Thread.sleep(100L);
+ }
+ }
+ } catch (InterruptedException | IOException e) {
+ channel.close();
+ throw e;
+ }
+ // Unreachable code added for completeness because exceptions should already have been thrown
+ channel.close();
+ throw new InterruptedException("Interrupted while waiting for lock on: " + file);
+ }
+
+ static boolean isReportExecution(ExecutionEvent event) {
+ MojoExecution execution = event.getMojoExecution();
+ return SAT_PLUGIN_GROUP_ID.equals(execution.getGroupId())
+ && SAT_PLUGIN_ARTIFACT_ID.equals(execution.getArtifactId())
+ && SAT_PLUGIN_REPORT_GOAL.equals(execution.getGoal());
+ }
+}
diff --git a/sat-plugin/src/main/java/org/openhab/tools/analysis/report/SummaryHtmlGeneration.java b/sat-plugin/src/main/java/org/openhab/tools/analysis/report/SummaryHtmlGeneration.java
new file mode 100644
index 00000000..f08f1d93
--- /dev/null
+++ b/sat-plugin/src/main/java/org/openhab/tools/analysis/report/SummaryHtmlGeneration.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (c) 2010-2019 Contributors to the openHAB project
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.openhab.tools.analysis.report;
+
+/**
+ * Enumerates the HTML summary generation plugin configuration parameters.
+ *
+ * @author Wouter Born - Initial contribution
+ */
+enum SummaryHtmlGeneration {
+ CONTINUOUS,
+ PERIODIC,
+ ONCE,
+ NEVER
+}
diff --git a/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/CheckstyleChecker.java b/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/CheckstyleChecker.java
index f50fc464..bb33b2df 100644
--- a/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/CheckstyleChecker.java
+++ b/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/CheckstyleChecker.java
@@ -31,10 +31,9 @@
* maven-checkstyle-
* plugin with a predefined ruleset file and configuration properties
*
- * @author Svilen Valkanov
- *
+ * @author Svilen Valkanov - Initial contribution
*/
-@Mojo(name = "checkstyle", requiresDependencyResolution = ResolutionScope.COMPILE)
+@Mojo(name = "checkstyle", requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true)
public class CheckstyleChecker extends AbstractChecker {
/**
diff --git a/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/PmdChecker.java b/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/PmdChecker.java
index bb39dbcc..0b3380ca 100644
--- a/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/PmdChecker.java
+++ b/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/PmdChecker.java
@@ -32,10 +32,9 @@
* maven-pmd-plugin with
* a predefined ruleset file and configuration properties
*
- * @author Svilen Valkanov
- *
+ * @author Svilen Valkanov - Initial contribution
*/
-@Mojo(name = "pmd", requiresDependencyResolution = ResolutionScope.COMPILE)
+@Mojo(name = "pmd", requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true)
public class PmdChecker extends AbstractChecker {
private static final String DEFAULT_RULESET_XML = "rulesets/pmd/rules.xml";
@@ -102,7 +101,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
element("targetDirectory", userProps.getProperty("pmd.custom.targetDirectory")),
element("compileSourceRoots", userProps.getProperty("pmd.custom.compileSourceRoots")),
element("rulesets", element("ruleset", defaultRulesetLocation),
- element("ruleset", customRulesetLocation)));
+ element("ruleset", customRulesetLocation)));
pmdPlugins.add(dependency("org.openhab.tools.sat.custom-checks", "pmd", plugin.getVersion()));
pmdPlugins.add(dependency("net.sourceforge.pmd", "pmd-core", PMD_VERSION));
pmdPlugins.add(dependency("net.sourceforge.pmd", "pmd-java", PMD_VERSION));
diff --git a/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/SpotBugsChecker.java b/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/SpotBugsChecker.java
index 885d83dc..e93240fb 100644
--- a/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/SpotBugsChecker.java
+++ b/sat-plugin/src/main/java/org/openhab/tools/analysis/tools/SpotBugsChecker.java
@@ -54,11 +54,9 @@
* SpotBugs is fully backward compatible with FindBugs.
*
*
- * @author Svilen Valkanov
- *
+ * @author Svilen Valkanov - Initial contribution
*/
-
-@Mojo(name = "spotbugs", requiresDependencyResolution = ResolutionScope.COMPILE)
+@Mojo(name = "spotbugs", requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true)
public class SpotBugsChecker extends AbstractChecker {
/**
@@ -85,19 +83,19 @@ public class SpotBugsChecker extends AbstractChecker {
/**
* The version of the spotbugs-maven-plugin that will be used
*/
- @Parameter(property = "maven.spotbugs.version", defaultValue = "3.1.6")
+ @Parameter(property = "maven.spotbugs.version", defaultValue = "3.1.12.2")
private String spotbugsMavenPluginVersion;
/**
* The version of the findbugs-slf4j plugin that will be used
*/
- @Parameter(property = "findbugs.slf4j.version", defaultValue = "1.2.4")
+ @Parameter(property = "findbugs.slf4j.version", defaultValue = "1.5.0")
private String findBugsSlf4jPluginVersion;
/**
* The version of the spotbugs that will be used
*/
- @Parameter(property = "spotbugs.version", defaultValue = "3.1.7")
+ @Parameter(property = "spotbugs.version", defaultValue = "3.1.12")
private String spotBugsVersion;
/**
@@ -217,7 +215,8 @@ private String getVisitorsString(String externalLocation) {
getLog().warn("Unable to find file " + resolvedPath.toString());
}
} else {
- stream = this.getClass().getClassLoader().getResourceAsStream(SpotBugsChecker.DEFAULT_VISITORS_XML); }
+ stream = this.getClass().getClassLoader().getResourceAsStream(SpotBugsChecker.DEFAULT_VISITORS_XML);
+ }
// Serialize the content
JAXBContext context;
diff --git a/sat-plugin/src/main/resources/configuration/spotbugs.properties b/sat-plugin/src/main/resources/configuration/spotbugs.properties
index 314a7945..e3e08703 100644
--- a/sat-plugin/src/main/resources/configuration/spotbugs.properties
+++ b/sat-plugin/src/main/resources/configuration/spotbugs.properties
@@ -5,7 +5,7 @@ spotbugs.effort=Min
spotbugs.xmlOutput=true
spotbugs.failOnError=false
spotbugs.report.dir=${project.build.directory}/code-analysis
-spotbugs.fork=false
+spotbugs.fork=true
outputEncoding=UTF-8
spotbugs.onlyAnalyze=org.openhab.-,org.eclipse.smarthome.-
spotbugs.nested=false
diff --git a/sat-plugin/src/test/java/org/openhab/tools/analysis/report/test/ReportUtilityTest.java b/sat-plugin/src/test/java/org/openhab/tools/analysis/report/ReportMojoTest.java
similarity index 59%
rename from sat-plugin/src/test/java/org/openhab/tools/analysis/report/test/ReportUtilityTest.java
rename to sat-plugin/src/test/java/org/openhab/tools/analysis/report/ReportMojoTest.java
index 3408e026..2fbb5bc0 100644
--- a/sat-plugin/src/test/java/org/openhab/tools/analysis/report/test/ReportUtilityTest.java
+++ b/sat-plugin/src/test/java/org/openhab/tools/analysis/report/ReportMojoTest.java
@@ -10,7 +10,13 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
-package org.openhab.tools.analysis.report.test;
+package org.openhab.tools.analysis.report;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.verify;
+import static org.openhab.tools.analysis.report.ReportUtil.RESULT_FILE_NAME;
+
+import java.io.File;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
@@ -19,40 +25,32 @@
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
-import org.openhab.tools.analysis.report.ReportUtility;
-
-import java.io.File;
-
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
/**
- * Tests for the {@link ReportUtility}
+ * Tests for the {@link ReportMojo}
*
- * @author Svilen Valkanov - Initial contributation
+ * @author Svilen Valkanov - Initial contribution
* @author Martin van Wingerden - added logging of all messages
*/
@RunWith(MockitoJUnitRunner.class)
-public class ReportUtilityTest {
+public class ReportMojoTest {
private static final String TARGET_RELATIVE_DIR = "target" + File.separator + "test-classes" + File.separator
+ "report";
private static final String TARGET_ABSOLUTE_DIR = System.getProperty("user.dir") + File.separator
+ TARGET_RELATIVE_DIR;
- private static final String RESULT_FILE_PATH = TARGET_ABSOLUTE_DIR + File.separator + ReportUtility.RESULT_FILE_NAME;
+ private static final String RESULT_FILE_PATH = TARGET_ABSOLUTE_DIR + File.separator + RESULT_FILE_NAME;
@Mock
private Log logger;
- private ReportUtility subject;
+ private ReportMojo subject;
private File resultFile = new File(RESULT_FILE_PATH);
@Before
public void setUp() throws Exception {
- subject = new ReportUtility();
+ subject = new ReportMojo();
subject.setLog(logger);
if (resultFile.exists()) {
@@ -99,16 +97,23 @@ public void assertWarningAreLoggedWhileExecuting() throws MojoFailureException {
subject.execute();
- verify(logger).warn("org.sprunck.bee.Bee.java:[31]\norg.sprunck.bee.Bee defines clone() but doesn't implement Cloneable");
+ verify(logger).warn(
+ "org.sprunck.bee.Bee.java:[31]\norg.sprunck.bee.Bee defines clone() but doesn't implement Cloneable");
verify(logger).warn("org.sprunck.bee.Bee.java:[31]\norg.sprunck.bee.Bee.clone() may return null");
- verify(logger).warn("org.sprunck.foo.Foo.java:[35]\nThe method name org.sprunck.foo.Foo.Went() doesn't start with a lower case letter");
+ verify(logger).warn(
+ "org.sprunck.foo.Foo.java:[35]\nThe method name org.sprunck.foo.Foo.Went() doesn't start with a lower case letter");
verify(logger).error("Code Analysis Tool has found: \n 2 error(s)! \n 3 warning(s) \n 3 info(s)");
- verify(logger).error("org.sprunck.bee.Bee.java:[19]\norg.sprunck.bee.Bee.toString() ignores return value of String.concat(String)");
- verify(logger).error("org.eclipse.smarthome.auth.jaas.internal.JaasAuthenticationProvider.java:[69]\nComment matches to-do format '(TODO)|(FIXME)'.");
- verify(logger).debug("org.sprunck.bee.Bee.java:[19]\nAn operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself");
- verify(logger).debug("org.sprunck.foo.Foo.java:[36]\nDo not use if statements that are always true or always false");
- verify(logger).debug("C:\\prj\\openHAB\\EclipseIDE\\git\\smarthome\\bundles\\automation\\org.eclipse.smarthome.automation.module.core\\ESH-INF\\automation\\moduletypes\\EventTriggersTypeDefinition.json:[0]\n" +
- "File does not end with a newline.");
- verify(logger).info("Detailed report can be found at: file:///" + RESULT_FILE_PATH);
+ verify(logger).error(
+ "org.sprunck.bee.Bee.java:[19]\norg.sprunck.bee.Bee.toString() ignores return value of String.concat(String)");
+ verify(logger).error(
+ "org.eclipse.smarthome.auth.jaas.internal.JaasAuthenticationProvider.java:[69]\nComment matches to-do format '(TODO)|(FIXME)'.");
+ verify(logger).debug(
+ "org.sprunck.bee.Bee.java:[19]\nAn operation on an Immutable object (String, BigDecimal or BigInteger) won't change the object itself");
+ verify(logger)
+ .debug("org.sprunck.foo.Foo.java:[36]\nDo not use if statements that are always true or always false");
+ verify(logger).debug(
+ "C:\\prj\\openHAB\\EclipseIDE\\git\\smarthome\\bundles\\automation\\org.eclipse.smarthome.automation.module.core\\ESH-INF\\automation\\moduletypes\\EventTriggersTypeDefinition.json:[0]\n"
+ + "File does not end with a newline.");
+ verify(logger).info("Detailed report can be found at: " + new File(RESULT_FILE_PATH).toURI());
}
}
diff --git a/tools/suppressions.xml b/tools/suppressions.xml
index b3ad9c2f..031c8db4 100644
--- a/tools/suppressions.xml
+++ b/tools/suppressions.xml
@@ -5,5 +5,5 @@
-
+