From d2510749d8c6677e8aa5db84f15a6e0075bab840 Mon Sep 17 00:00:00 2001 From: Martin Kanters Date: Fri, 27 Dec 2019 10:56:55 +0100 Subject: [PATCH] [MNG-6065] Create option --fail-on-severity --- .../slf4j/impl/MavenLoggerFactoryTest.java | 90 +++++++++++ maven-embedder/pom.xml | 8 +- .../java/org/apache/maven/cli/CLIManager.java | 3 + .../java/org/apache/maven/cli/MavenCli.java | 22 +++ .../maven/cli/event/ExecutionEventLogger.java | 28 +++- .../maven/slf4j-configuration.properties | 2 +- maven-slf4j-provider/pom.xml | 4 + .../slf4j/impl/MavenFailOnSeverityLogger.java | 142 ++++++++++++++++++ .../org/slf4j/impl/MavenLoggerFactory.java | 82 ++++++++++ .../org/slf4j/impl/MavenSimpleLogger.java | 14 +- .../org/slf4j/impl/StaticLoggerBinder.java | 4 +- maven-slf4j-wrapper/pom.xml | 44 ++++++ .../maven/logwrapper/LogLevelRecorder.java | 55 +++++++ .../logwrapper/MavenSlf4jWrapperFactory.java | 30 +--- maven-slf4j-wrapper/src/site/site.xml | 38 +++++ .../logwrapper/LogLevelRecorderTest.java | 49 ++++++ pom.xml | 14 +- 17 files changed, 586 insertions(+), 43 deletions(-) create mode 100644 apache-maven/src/test/java/org/slf4j/impl/MavenLoggerFactoryTest.java create mode 100644 maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenFailOnSeverityLogger.java create mode 100644 maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenLoggerFactory.java create mode 100644 maven-slf4j-wrapper/pom.xml create mode 100644 maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/LogLevelRecorder.java rename maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLoggerFactory.java => maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/MavenSlf4jWrapperFactory.java (54%) create mode 100644 maven-slf4j-wrapper/src/site/site.xml create mode 100644 maven-slf4j-wrapper/src/test/java/org/apache/maven/logwrapper/LogLevelRecorderTest.java diff --git a/apache-maven/src/test/java/org/slf4j/impl/MavenLoggerFactoryTest.java b/apache-maven/src/test/java/org/slf4j/impl/MavenLoggerFactoryTest.java new file mode 100644 index 0000000000..352d627044 --- /dev/null +++ b/apache-maven/src/test/java/org/slf4j/impl/MavenLoggerFactoryTest.java @@ -0,0 +1,90 @@ +package org.slf4j.impl; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.logwrapper.LogLevelRecorder; +import org.junit.Test; +import org.slf4j.Logger; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class MavenLoggerFactoryTest +{ + @Test + public void createsSimpleLogger() + { + MavenLoggerFactory mavenLoggerFactory = new MavenLoggerFactory(); + + Logger logger = mavenLoggerFactory.getLogger( "Test" ); + + assertThat( logger, instanceOf( MavenSimpleLogger.class ) ); + } + + @Test + public void loggerCachingWorks() + { + MavenLoggerFactory mavenLoggerFactory = new MavenLoggerFactory(); + + Logger logger = mavenLoggerFactory.getLogger( "Test" ); + Logger logger2 = mavenLoggerFactory.getLogger( "Test" ); + Logger differentLogger = mavenLoggerFactory.getLogger( "TestWithDifferentName" ); + + assertNotNull( logger ); + assertNotNull( differentLogger ); + assertSame( logger, logger2 ); + assertNotSame( logger, differentLogger ); + } + + @Test + public void reportsWhenFailOnSeverityThresholdHasBeenHit() + { + MavenLoggerFactory mavenLoggerFactory = new MavenLoggerFactory(); + mavenLoggerFactory.setLogLevelRecorder( new LogLevelRecorder( "ERROR" ) ); + + assertTrue( mavenLoggerFactory.getLogLevelRecorder().isPresent() ); + LogLevelRecorder logLevelRecorder = mavenLoggerFactory.getLogLevelRecorder().get(); + + MavenFailOnSeverityLogger logger = (MavenFailOnSeverityLogger) mavenLoggerFactory.getLogger( "Test" ); + assertFalse( logLevelRecorder.metThreshold() ); + + logger.warn( "This should not hit the fail threshold" ); + assertFalse( logLevelRecorder.metThreshold() ); + + logger.error( "This should hit the fail threshold" ); + assertTrue( logLevelRecorder.metThreshold() ); + + logger.warn( "This should not reset the fail threshold" ); + assertTrue( logLevelRecorder.metThreshold() ); + } + + @Test( expected = IllegalStateException.class ) + public void failOnSeverityThresholdCanOnlyBeSetOnce() + { + MavenLoggerFactory mavenLoggerFactory = new MavenLoggerFactory(); + mavenLoggerFactory.setLogLevelRecorder( new LogLevelRecorder( "WARN" ) ); + mavenLoggerFactory.setLogLevelRecorder( new LogLevelRecorder( "ERROR" ) ); + } +} diff --git a/maven-embedder/pom.xml b/maven-embedder/pom.xml index 235ae62388..f4982dac5b 100644 --- a/maven-embedder/pom.xml +++ b/maven-embedder/pom.xml @@ -74,6 +74,10 @@ under the License. org.apache.maven.shared maven-shared-utils + + org.apache.maven + maven-slf4j-wrapper + com.google.inject guice @@ -104,10 +108,6 @@ under the License. org.codehaus.mojo animal-sniffer-annotations - - org.checkerframework - checker-compat-qual - diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java index 1e95010690..ec5e1b11c0 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/CLIManager.java @@ -77,6 +77,8 @@ public class CLIManager public static final String FAIL_FAST = "ff"; + public static final String FAIL_ON_SEVERITY = "fos"; + public static final String FAIL_AT_END = "fae"; public static final String FAIL_NEVER = "fn"; @@ -128,6 +130,7 @@ public class CLIManager options.addOption( Option.builder( ALTERNATE_GLOBAL_SETTINGS ).longOpt( "global-settings" ).desc( "Alternate path for the global settings file" ).hasArg().build() ); options.addOption( Option.builder( Character.toString( ALTERNATE_USER_TOOLCHAINS ) ).longOpt( "toolchains" ).desc( "Alternate path for the user toolchains file" ).hasArg().build() ); options.addOption( Option.builder( ALTERNATE_GLOBAL_TOOLCHAINS ).longOpt( "global-toolchains" ).desc( "Alternate path for the global toolchains file" ).hasArg().build() ); + options.addOption( Option.builder( FAIL_ON_SEVERITY ).longOpt( "fail-on-severity" ).desc( "Configure which severity of logging should cause the build to fail" ).hasArgs().build() ); options.addOption( Option.builder( FAIL_FAST ).longOpt( "fail-fast" ).desc( "Stop at first failure in reactorized builds" ).build() ); options.addOption( Option.builder( FAIL_AT_END ).longOpt( "fail-at-end" ).desc( "Only fail the build afterwards; allow all non-impacted builds to continue" ).build() ); options.addOption( Option.builder( FAIL_NEVER ).longOpt( "fail-never" ).desc( "NEVER fail the build, regardless of project result" ).build() ); diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index 7d17e187d2..8653c27174 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -58,6 +58,8 @@ import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule; import org.apache.maven.extension.internal.CoreExports; import org.apache.maven.extension.internal.CoreExtensionEntry; import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.logwrapper.LogLevelRecorder; +import org.apache.maven.logwrapper.MavenSlf4jWrapperFactory; import org.apache.maven.model.building.ModelProcessor; import org.apache.maven.project.MavenProject; import org.apache.maven.properties.internal.EnvironmentUtils; @@ -542,6 +544,24 @@ public class MavenCli plexusLoggerManager = new Slf4jLoggerManager(); slf4jLogger = slf4jLoggerFactory.getLogger( this.getClass().getName() ); + + if ( cliRequest.commandLine.hasOption( CLIManager.FAIL_ON_SEVERITY ) ) + { + String logLevelThreshold = cliRequest.commandLine.getOptionValue( CLIManager.FAIL_ON_SEVERITY ); + + if ( slf4jLoggerFactory instanceof MavenSlf4jWrapperFactory ) + { + LogLevelRecorder logLevelRecorder = new LogLevelRecorder( logLevelThreshold ); + ( (MavenSlf4jWrapperFactory) slf4jLoggerFactory ).setLogLevelRecorder( logLevelRecorder ); + slf4jLogger.info( "Enabled to break the build on log level {}.", logLevelThreshold ); + } + else + { + slf4jLogger.warn( "Expected LoggerFactory to be of type '{}', but found '{}' instead. " + + "The --fail-on-severity flag will not take effect.", + MavenSlf4jWrapperFactory.class.getName(), slf4jLoggerFactory.getClass().getName() ); + } + } } private void version( CliRequest cliRequest ) @@ -1343,6 +1363,8 @@ public class MavenCli // this is the default behavior. String reactorFailureBehaviour = MavenExecutionRequest.REACTOR_FAIL_FAST; + slf4jLoggerFactory = LoggerFactory.getILoggerFactory(); + if ( commandLine.hasOption( CLIManager.NON_RECURSIVE ) ) { recursive = false; diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java b/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java index 17da65548a..f3cd8580b6 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/event/ExecutionEventLogger.java @@ -33,11 +33,14 @@ import org.apache.maven.execution.BuildSummary; import org.apache.maven.execution.ExecutionEvent; import org.apache.maven.execution.MavenExecutionResult; import org.apache.maven.execution.MavenSession; +import org.apache.maven.logwrapper.LogLevelRecorder; +import org.apache.maven.logwrapper.MavenSlf4jWrapperFactory; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.project.MavenProject; import org.apache.maven.shared.utils.logging.MessageBuilder; import org.codehaus.plexus.util.StringUtils; +import org.slf4j.ILoggerFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -46,8 +49,7 @@ import org.slf4j.LoggerFactory; * * @author Benjamin Bentmann */ -public class ExecutionEventLogger - extends AbstractExecutionListener +public class ExecutionEventLogger extends AbstractExecutionListener { private final Logger logger; @@ -133,6 +135,20 @@ public class ExecutionEventLogger logReactorSummary( event.getSession() ); } + ILoggerFactory iLoggerFactory = LoggerFactory.getILoggerFactory(); + + if ( iLoggerFactory instanceof MavenSlf4jWrapperFactory ) + { + MavenSlf4jWrapperFactory loggerFactory = (MavenSlf4jWrapperFactory) iLoggerFactory; + loggerFactory.getLogLevelRecorder() + .filter( LogLevelRecorder::metThreshold ) + .ifPresent( recorder -> + event.getSession().getResult().addException( new Exception( + "Build failed due to log statements with a higher severity than allowed. " + + "Fix the logged issues or remove flag --fail-on-severity (-fos)." ) ) + ); + } + logResult( event.getSession() ); logStats( event.getSession() ); @@ -298,16 +314,16 @@ public class ExecutionEventLogger // -------< groupId:artifactId >------- String projectKey = project.getGroupId() + ':' + project.getArtifactId(); - - final String preHeader = "--< "; + + final String preHeader = "--< "; final String postHeader = " >--"; final int headerLen = preHeader.length() + projectKey.length() + postHeader.length(); String prefix = chars( '-', Math.max( 0, ( LINE_LENGTH - headerLen ) / 2 ) ) + preHeader; - String suffix = postHeader - + chars( '-', Math.max( 0, LINE_LENGTH - headerLen - prefix.length() + preHeader.length() ) ); + String suffix = postHeader + chars( '-', + Math.max( 0, LINE_LENGTH - headerLen - prefix.length() + preHeader.length() ) ); logger.info( buffer().strong( prefix ).project( projectKey ).strong( suffix ).toString() ); diff --git a/maven-embedder/src/main/resources/META-INF/maven/slf4j-configuration.properties b/maven-embedder/src/main/resources/META-INF/maven/slf4j-configuration.properties index ff865bccab..23b18c024a 100644 --- a/maven-embedder/src/main/resources/META-INF/maven/slf4j-configuration.properties +++ b/maven-embedder/src/main/resources/META-INF/maven/slf4j-configuration.properties @@ -18,6 +18,6 @@ # key = Slf4j effective logger factory implementation # value = corresponding o.a.m.cli.logging.Slf4jConfiguration class org.slf4j.impl.SimpleLoggerFactory org.apache.maven.cli.logging.impl.Slf4jSimpleConfiguration -org.slf4j.impl.MavenSimpleLoggerFactory org.apache.maven.cli.logging.impl.Slf4jSimpleConfiguration +org.slf4j.impl.MavenLoggerFactory org.apache.maven.cli.logging.impl.Slf4jSimpleConfiguration org.apache.logging.slf4j.Log4jLoggerFactory org.apache.maven.cli.logging.impl.Log4j2Configuration ch.qos.logback.classic.LoggerContext org.apache.maven.cli.logging.impl.LogbackConfiguration diff --git a/maven-slf4j-provider/pom.xml b/maven-slf4j-provider/pom.xml index defe2dddb5..7af239cdc5 100644 --- a/maven-slf4j-provider/pom.xml +++ b/maven-slf4j-provider/pom.xml @@ -45,6 +45,10 @@ under the License. org.apache.maven.shared maven-shared-utils + + org.apache.maven + maven-slf4j-wrapper + diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenFailOnSeverityLogger.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenFailOnSeverityLogger.java new file mode 100644 index 0000000000..12c6cc24e7 --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenFailOnSeverityLogger.java @@ -0,0 +1,142 @@ +package org.slf4j.impl; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.logwrapper.LogLevelRecorder; +import org.slf4j.event.Level; + +/** + * A proxy which enhances the MavenSimpleLogger with functionality to track whether a logging threshold is hit. + * Currently only support WARN and ERROR states, since it's been used for the --fail-on-severity flag. + */ +public class MavenFailOnSeverityLogger extends MavenSimpleLogger +{ + private final LogLevelRecorder logLevelRecorder; + + MavenFailOnSeverityLogger( String name, LogLevelRecorder logLevelRecorder ) + { + super( name ); + this.logLevelRecorder = logLevelRecorder; + } + + /** + * A simple implementation which always logs messages of level WARN + * according to the format outlined above. + */ + @Override + public void warn( String msg ) + { + super.warn( msg ); + logLevelRecorder.record( Level.WARN ); + } + + /** + * Perform single parameter substitution before logging the message of level + * WARN according to the format outlined above. + */ + @Override + public void warn( String format, Object arg ) + { + super.warn( format, arg ); + logLevelRecorder.record( Level.WARN ); + } + + /** + * Perform double parameter substitution before logging the message of level + * WARN according to the format outlined above. + */ + @Override + public void warn( String format, Object arg1, Object arg2 ) + { + super.warn( format, arg1, arg2 ); + logLevelRecorder.record( Level.WARN ); + } + + /** + * Perform double parameter substitution before logging the message of level + * WARN according to the format outlined above. + */ + @Override + public void warn( String format, Object... argArray ) + { + super.warn( format, argArray ); + logLevelRecorder.record( Level.WARN ); + } + + /** Log a message of level WARN, including an exception. */ + @Override + public void warn( String msg, Throwable t ) + { + super.warn( msg, t ); + logLevelRecorder.record( Level.WARN ); + } + + /** + * A simple implementation which always logs messages of level ERROR + * according to the format outlined above. + */ + @Override + public void error( String msg ) + { + super.error( msg ); + logLevelRecorder.record( Level.ERROR ); + } + + /** + * Perform single parameter substitution before logging the message of level + * ERROR according to the format outlined above. + */ + @Override + public void error( String format, Object arg ) + { + super.error( format, arg ); + logLevelRecorder.record( Level.ERROR ); + } + + /** + * Perform double parameter substitution before logging the message of level + * ERROR according to the format outlined above. + */ + @Override + public void error( String format, Object arg1, Object arg2 ) + { + super.error( format, arg1, arg2 ); + logLevelRecorder.record( Level.ERROR ); + } + + /** + * Perform double parameter substitution before logging the message of level + * ERROR according to the format outlined above. + */ + @Override + public void error( String format, Object... argArray ) + { + super.error( format, argArray ); + logLevelRecorder.record( Level.ERROR ); + } + + /** Log a message of level ERROR, including an exception. */ + @Override + public void error( String msg, Throwable t ) + { + super.error( msg, t ); + logLevelRecorder.record( Level.ERROR ); + } +} diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenLoggerFactory.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenLoggerFactory.java new file mode 100644 index 0000000000..7ef126d12c --- /dev/null +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenLoggerFactory.java @@ -0,0 +1,82 @@ +package org.slf4j.impl; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.maven.logwrapper.LogLevelRecorder; +import org.apache.maven.logwrapper.MavenSlf4jWrapperFactory; +import org.slf4j.Logger; + +import java.util.Optional; + +/** + * LogFactory for Maven which can create a simple logger or one which, if set, fails the build on a severity threshold. + */ +public class MavenLoggerFactory extends SimpleLoggerFactory implements MavenSlf4jWrapperFactory +{ + private LogLevelRecorder logLevelRecorder = null; + + @Override + public void setLogLevelRecorder( LogLevelRecorder logLevelRecorder ) + { + if ( this.logLevelRecorder != null ) + { + throw new IllegalStateException( "LogLevelRecorder has already been set." ); + } + + this.logLevelRecorder = logLevelRecorder; + } + + @Override + public Optional getLogLevelRecorder() + { + return Optional.ofNullable( logLevelRecorder ); + } + + /** + * Return an appropriate {@link MavenSimpleLogger} instance by name. + */ + @Override + public Logger getLogger( String name ) + { + Logger simpleLogger = loggerMap.get( name ); + if ( simpleLogger != null ) + { + return simpleLogger; + } + else + { + Logger newInstance = getNewLoggingInstance( name ); + Logger oldInstance = loggerMap.putIfAbsent( name, newInstance ); + return oldInstance == null ? newInstance : oldInstance; + } + } + + private Logger getNewLoggingInstance( String name ) + { + if ( logLevelRecorder == null ) + { + return new MavenSimpleLogger( name ); + } + else + { + return new MavenFailOnSeverityLogger( name, logLevelRecorder ); + } + } +} diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java index 9366687edb..767220d9ea 100644 --- a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLogger.java @@ -19,18 +19,18 @@ package org.slf4j.impl; * under the License. */ -import static org.apache.maven.shared.utils.logging.MessageUtils.level; -import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; - import java.io.PrintStream; +import static org.apache.maven.shared.utils.logging.MessageUtils.buffer; +import static org.apache.maven.shared.utils.logging.MessageUtils.level; + /** - * Logger for Maven, that support colorization of levels and stacktraces. - * This class implements 2 methods introduced in slf4j-simple provider local copy. + * Logger for Maven, that support colorization of levels and stacktraces. This class implements 2 methods introduced in + * slf4j-simple provider local copy. + * * @since 3.5.0 */ -public class MavenSimpleLogger - extends SimpleLogger +public class MavenSimpleLogger extends SimpleLogger { MavenSimpleLogger( String name ) { diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticLoggerBinder.java b/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticLoggerBinder.java index ba01d83226..ed94c70a7c 100644 --- a/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticLoggerBinder.java +++ b/maven-slf4j-provider/src/main/java/org/slf4j/impl/StaticLoggerBinder.java @@ -40,7 +40,7 @@ public final class StaticLoggerBinder @SuppressWarnings( { "checkstyle:staticvariablename", "checkstyle:visibilitymodifier" } ) public static String REQUESTED_API_VERSION = "1.7.25"; // !final - private static final String LOGGER_FACTORY_CLASS_STR = MavenSimpleLoggerFactory.class.getName(); + private static final String LOGGER_FACTORY_CLASS_STR = MavenLoggerFactory.class.getName(); /** * The unique instance of this class. @@ -58,7 +58,7 @@ public final class StaticLoggerBinder */ private StaticLoggerBinder() { - loggerFactory = new MavenSimpleLoggerFactory(); + loggerFactory = new MavenLoggerFactory(); } /** diff --git a/maven-slf4j-wrapper/pom.xml b/maven-slf4j-wrapper/pom.xml new file mode 100644 index 0000000000..746c328226 --- /dev/null +++ b/maven-slf4j-wrapper/pom.xml @@ -0,0 +1,44 @@ + + + + + + 4.0.0 + + + org.apache.maven + maven + 3.7.0-SNAPSHOT + + + maven-slf4j-wrapper + + Maven SLF4J Wrapper + + This modules provides an ILoggerFactory interface which avoids a cyclic dependency between maven-embedder and maven-slf4j-provider. + + + + + org.slf4j + slf4j-api + + + \ No newline at end of file diff --git a/maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/LogLevelRecorder.java b/maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/LogLevelRecorder.java new file mode 100644 index 0000000000..9fa4b51307 --- /dev/null +++ b/maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/LogLevelRecorder.java @@ -0,0 +1,55 @@ +package org.apache.maven.logwrapper; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.slf4j.event.Level; + +/** + * Responsible for keeping state of whether the threshold of the --fail-on-severity flag has been hit. + */ +public class LogLevelRecorder +{ + private final Level logThreshold; + private boolean metThreshold = false; + + public LogLevelRecorder( String threshold ) + { + Level level = Level.valueOf( threshold ); + if ( level.toInt() < Level.WARN.toInt() ) + { + throw new IllegalArgumentException( "Logging severity thresholds can only be set to WARN or ERROR" ); + } + + logThreshold = level; + } + + public void record( Level logLevel ) + { + if ( !metThreshold && logLevel.toInt() >= logThreshold.toInt() ) + { + metThreshold = true; + } + } + + public boolean metThreshold() + { + return metThreshold; + } +} diff --git a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLoggerFactory.java b/maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/MavenSlf4jWrapperFactory.java similarity index 54% rename from maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLoggerFactory.java rename to maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/MavenSlf4jWrapperFactory.java index 4adfdbe059..e2063b73a3 100644 --- a/maven-slf4j-provider/src/main/java/org/slf4j/impl/MavenSimpleLoggerFactory.java +++ b/maven-slf4j-wrapper/src/main/java/org/apache/maven/logwrapper/MavenSlf4jWrapperFactory.java @@ -1,4 +1,4 @@ -package org.slf4j.impl; +package org.apache.maven.logwrapper; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,29 +19,15 @@ package org.slf4j.impl; * under the License. */ -import org.slf4j.Logger; +import org.slf4j.ILoggerFactory; + +import java.util.Optional; /** - * MavenSimpleLoggerFactory + * Wrapper for creating loggers which can have a log level threshold. */ -public class MavenSimpleLoggerFactory - extends SimpleLoggerFactory +public interface MavenSlf4jWrapperFactory extends ILoggerFactory { - /** - * Return an appropriate {@link MavenSimpleLogger} instance by name. - */ - public Logger getLogger( String name ) - { - Logger simpleLogger = loggerMap.get( name ); - if ( simpleLogger != null ) - { - return simpleLogger; - } - else - { - Logger newInstance = new MavenSimpleLogger( name ); - Logger oldInstance = loggerMap.putIfAbsent( name, newInstance ); - return oldInstance == null ? newInstance : oldInstance; - } - } + void setLogLevelRecorder( LogLevelRecorder logLevelRecorder ); + Optional getLogLevelRecorder(); } diff --git a/maven-slf4j-wrapper/src/site/site.xml b/maven-slf4j-wrapper/src/site/site.xml new file mode 100644 index 0000000000..e475330c40 --- /dev/null +++ b/maven-slf4j-wrapper/src/site/site.xml @@ -0,0 +1,38 @@ + + + + + + + ${project.scm.url} + + + + + + + + + + + + + \ No newline at end of file diff --git a/maven-slf4j-wrapper/src/test/java/org/apache/maven/logwrapper/LogLevelRecorderTest.java b/maven-slf4j-wrapper/src/test/java/org/apache/maven/logwrapper/LogLevelRecorderTest.java new file mode 100644 index 0000000000..69b2853624 --- /dev/null +++ b/maven-slf4j-wrapper/src/test/java/org/apache/maven/logwrapper/LogLevelRecorderTest.java @@ -0,0 +1,49 @@ +package org.apache.maven.logwrapper; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.junit.Test; +import org.slf4j.event.Level; + +import static org.junit.Assert.assertTrue; + +public class LogLevelRecorderTest +{ + @Test + public void createsLogLevelRecorder() + { + LogLevelRecorder logLevelRecorder = new LogLevelRecorder( "WARN" ); + logLevelRecorder.record( Level.ERROR ); + + assertTrue( logLevelRecorder.metThreshold() ); + } + + @Test( expected = IllegalArgumentException.class ) + public void failsOnLowerThanWarn () + { + new LogLevelRecorder( "INFO" ); + } + + @Test( expected = IllegalArgumentException.class ) + public void failsOnUnknownLogLevel () + { + new LogLevelRecorder( "SEVERE" ); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 3e73b2fb0b..21c05abf5b 100644 --- a/pom.xml +++ b/pom.xml @@ -92,6 +92,7 @@ under the License. maven-resolver-provider maven-repository-metadata maven-slf4j-provider + maven-slf4j-wrapper maven-embedder maven-compat apache-maven @@ -157,7 +158,13 @@ under the License. Mike Mol (MNG-6665) - Martin Kanters (MNG-6665) + Martin Kanters (MNG-6665, MNG-6065) + + + Luc Klaassen (MNG-6065) + + + Wouter Aarts (MNG-6065) @@ -232,6 +239,11 @@ under the License. maven-slf4j-provider ${project.version} + + org.apache.maven + maven-slf4j-wrapper + ${project.version} +