diff --git a/maven-plugin-api/src/main/java/org/apache/maven/monitor/logging/DefaultLog.java b/maven-plugin-api/src/main/java/org/apache/maven/monitor/logging/DefaultLog.java index 1ed64ecaa9e3..3242cd53d1f1 100644 --- a/maven-plugin-api/src/main/java/org/apache/maven/monitor/logging/DefaultLog.java +++ b/maven-plugin-api/src/main/java/org/apache/maven/monitor/logging/DefaultLog.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.plugin.logging.AbstractLog; import org.apache.maven.plugin.logging.Log; import org.codehaus.plexus.logging.Logger; @@ -28,7 +29,7 @@ * @deprecated Use SLF4J directly */ @Deprecated -public class DefaultLog +public class DefaultLog extends AbstractLog implements Log { diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/AbstractLog.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/AbstractLog.java new file mode 100644 index 000000000000..1ef64e197838 --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/AbstractLog.java @@ -0,0 +1,116 @@ +package org.apache.maven.plugin.logging; + +/* + * 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 java.util.function.Supplier; + +/** + * Abstract class providing some defaults shareable implementation of some Log methods. + */ +public abstract class AbstractLog implements Log +{ + /** + * @see org.apache.maven.plugin.logging.Log#debug(Supplier) + */ + public void debug( Supplier messageSupplier ) + { + if ( isDebugEnabled() ) + { + debug( messageSupplier.get() ); + } + } + + /** + * @see org.apache.maven.plugin.logging.Log#debug(Supplier, Throwable) + */ + public void debug( Supplier messageSupplier, Throwable error ) + { + if ( isDebugEnabled() ) + { + debug( messageSupplier.get(), error ); + } + } + + /** + * @see org.apache.maven.plugin.logging.Log#info(Supplier) + */ + public void info( Supplier messageSupplier ) + { + if ( isInfoEnabled() ) + { + info( messageSupplier.get() ); + } + } + + /** + * @see org.apache.maven.plugin.logging.Log#info(Supplier, Throwable) + */ + public void info( Supplier messageSupplier, Throwable error ) + { + if ( isInfoEnabled() ) + { + info( messageSupplier.get(), error ); + } + } + + /** + * @see org.apache.maven.plugin.logging.Log#warn(Supplier) + */ + public void warn( Supplier messageSupplier ) + { + if ( isWarnEnabled() ) + { + warn( messageSupplier.get() ); + } + } + + /** + * @see org.apache.maven.plugin.logging.Log#warn(Supplier, Throwable) + */ + public void warn( Supplier messageSupplier, Throwable error ) + { + if ( isWarnEnabled() ) + { + warn( messageSupplier.get(), error ); + } + } + + /** + * @see org.apache.maven.plugin.logging.Log#error(Supplier) + */ + public void error( Supplier messageSupplier ) + { + if ( isErrorEnabled() ) + { + error( messageSupplier.get() ); + } + } + + /** + * @see org.apache.maven.plugin.logging.Log#error(Supplier, Throwable) + */ + public void error( Supplier messageSupplier, Throwable error ) + { + if ( isErrorEnabled() ) + { + error( messageSupplier.get(), error ); + } + } +} diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/Log.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/Log.java index 04d85bd960cc..5f33faf03bf5 100644 --- a/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/Log.java +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/Log.java @@ -19,6 +19,8 @@ * under the License. */ +import java.util.function.Supplier; + /** * This interface supplies the API for providing feedback to the user from the Mojo, using standard * Maven channels.
@@ -63,6 +65,23 @@ public interface Log */ void debug( Throwable error ); + /** + * Send a message to the user in the debug error level by computing the message + * only when needed. The supplier will be called only if @see #isDebugEnabled() is true. + * + * @param messageSupplier a non null Supplier of the message to use + */ + void debug( Supplier messageSupplier ); + + /** + * Send a message to the user in the debug error level by computing the message + * only when needed. The supplier will be called only if @see #isDebugEnabled() is true. + * + * @param messageSupplier a non null Supplier of the message to use + * @param error the error that occurred and for which the log applies + */ + void debug( Supplier messageSupplier, Throwable error ); + /** * @return true if the info error level is enabled */ @@ -92,6 +111,23 @@ public interface Log */ void info( Throwable error ); + /** + * Send a message to the user in the info error level by computing the message + * only when needed. The supplier will be called only if @see #isInfoEnabled() is true. + * + * @param messageSupplier a non null Supplier of the message to use + */ + void info( Supplier messageSupplier ); + + /** + * Send a message to the user in the info error level by computing the message + * only when needed. The supplier will be called only if @see #isInfoEnabled() is true. + * + * @param messageSupplier a non null Supplier of the message to use + * @param error the error that occurred and for which the log applies + */ + void info( Supplier messageSupplier, Throwable error ); + /** * @return true if the warn error level is enabled */ @@ -121,6 +157,23 @@ public interface Log */ void warn( Throwable error ); + /** + * Send a message to the user in the warn error level by computing the message + * only when needed. The supplier will be called only if @see #isWarnEnabled() is true. + * + * @param messageSupplier a non null Supplier of the message to use + */ + void warn( Supplier messageSupplier ); + + /** + * Send a message to the user in the warn error level by computing the message + * only when needed. The supplier will be called only if @see #isWarnEnabled() is true. + * + * @param messageSupplier a non null Supplier of the message to use + * @param error the error that occurred and for which the log applies + */ + void warn( Supplier messageSupplier, Throwable error ); + /** * @return true if the error error level is enabled */ @@ -149,4 +202,21 @@ public interface Log * @param error */ void error( Throwable error ); + + /** + * Send a message to the user in the error error level by computing the message + * only when needed. The supplier will be called only if @see #isErrorEnabled() is true. + * + * @param messageSupplier a non null Supplier of the message to use + */ + void error( Supplier messageSupplier ); + + /** + * Send a message to the user in the error error level by computing the message + * only when needed. The supplier will be called only if @see #isErrorEnabled() is true. + * + * @param messageSupplier a non null Supplier of the message to use + * @param error the error that occurred and for which the log applies + */ + void error( Supplier messageSupplier, Throwable error ); } diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/SystemStreamLog.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/SystemStreamLog.java index f0fc6189d57f..5b8b277fce60 100644 --- a/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/SystemStreamLog.java +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/logging/SystemStreamLog.java @@ -30,7 +30,7 @@ * @deprecated Use SLF4J directly */ @Deprecated -public class SystemStreamLog +public class SystemStreamLog extends AbstractLog implements Log { /** diff --git a/maven-plugin-api/src/test/java/org/apache/maven/monitor/logging/DefaultLogTest.java b/maven-plugin-api/src/test/java/org/apache/maven/monitor/logging/DefaultLogTest.java new file mode 100644 index 000000000000..a384be1b0eae --- /dev/null +++ b/maven-plugin-api/src/test/java/org/apache/maven/monitor/logging/DefaultLogTest.java @@ -0,0 +1,78 @@ +package org.apache.maven.monitor.logging; + +/* + * 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.plugin.logging.CountingCallsSupplier; +import org.apache.maven.plugin.logging.Log; +import org.codehaus.plexus.logging.Logger; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DefaultLogTest +{ + private static final String EXPECTED_MESSAGE = "expected message"; + + @Test + public void testLazyMessageIsEvaluatedForActiveLogLevels() + { + CountingCallsSupplier messageSupplier = CountingCallsSupplier.of(EXPECTED_MESSAGE); + + Throwable fakeError = new RuntimeException(); + + Log logger = new DefaultLog(new NoOpLogger(Logger.LEVEL_DEBUG)); + + logger.debug(messageSupplier); + logger.info(messageSupplier); + logger.warn(messageSupplier); + logger.error(messageSupplier); + + logger.debug(messageSupplier, fakeError); + logger.info(messageSupplier, fakeError); + logger.warn(messageSupplier, fakeError); + logger.error(messageSupplier, fakeError); + + // all log calls should have lead to a supplier call + assertEquals(8, messageSupplier.getNumberOfCalls(), "wrong number of calls to the message supplier"); + } + + @Test + public void testLazyMessageIsNotEvaluatedForNonActiveLogLevels() + { + CountingCallsSupplier messageSupplier = CountingCallsSupplier.of(EXPECTED_MESSAGE); + + Throwable fakeError = new RuntimeException(); + + Log logger = new DefaultLog(new NoOpLogger(Logger.LEVEL_DISABLED)); + + logger.debug(messageSupplier); + logger.info(messageSupplier); + logger.warn(messageSupplier); + logger.error(messageSupplier); + + logger.debug(messageSupplier, fakeError); + logger.info(messageSupplier, fakeError); + logger.warn(messageSupplier, fakeError); + logger.error(messageSupplier, fakeError); + + // no log calls should have lead to any supplier call + assertEquals(0, messageSupplier.getNumberOfCalls(), "wrong number of calls to the message supplier"); + } +} diff --git a/maven-plugin-api/src/test/java/org/apache/maven/monitor/logging/NoOpLogger.java b/maven-plugin-api/src/test/java/org/apache/maven/monitor/logging/NoOpLogger.java new file mode 100644 index 000000000000..515474205f7f --- /dev/null +++ b/maven-plugin-api/src/test/java/org/apache/maven/monitor/logging/NoOpLogger.java @@ -0,0 +1,70 @@ +package org.apache.maven.monitor.logging; + +/* + * 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.codehaus.plexus.logging.AbstractLogger; +import org.codehaus.plexus.logging.Logger; + +/** + * Custom implementation for tests purpose. + */ +public class NoOpLogger extends AbstractLogger + implements Logger { + + public NoOpLogger(int threshold) + { + super(threshold, "NoOp"); + } + + @Override + public void debug(String message, Throwable throwable) + { + // no-op + } + + @Override + public void info(String message, Throwable throwable) + { + // no-op + } + + @Override + public void warn(String message, Throwable throwable) + { + // no-op + } + + @Override + public void error(String message, Throwable throwable) + { + // no-op + } + + @Override + public void fatalError(String message, Throwable throwable) + { + // no-op + } + + @Override + public Logger getChildLogger(String name) { + return this; + } +} diff --git a/maven-plugin-api/src/test/java/org/apache/maven/plugin/logging/CountingCallsSupplier.java b/maven-plugin-api/src/test/java/org/apache/maven/plugin/logging/CountingCallsSupplier.java new file mode 100644 index 000000000000..b604561a73af --- /dev/null +++ b/maven-plugin-api/src/test/java/org/apache/maven/plugin/logging/CountingCallsSupplier.java @@ -0,0 +1,55 @@ +package org.apache.maven.plugin.logging; + +/* + * 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 java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Supplier; + +/** + * A custom Supplier implementation allowing to count how many times a constant value is delivered. + * @param the type of the value to deliver + */ +public class CountingCallsSupplier implements Supplier { + private final T value; + private final AtomicInteger counter; + + private CountingCallsSupplier(T valueToSupply) + { + this.value = valueToSupply; + this.counter = new AtomicInteger(0); + } + + @Override + public T get() + { + counter.incrementAndGet(); + return value; + } + + public int getNumberOfCalls() + { + return counter.get(); + } + + public static CountingCallsSupplier of( T value ) + { + return new CountingCallsSupplier<>( value ); + } +} diff --git a/maven-plugin-api/src/test/java/org/apache/maven/plugin/logging/SystemStreamLogTest.java b/maven-plugin-api/src/test/java/org/apache/maven/plugin/logging/SystemStreamLogTest.java new file mode 100644 index 000000000000..e38ec1728f63 --- /dev/null +++ b/maven-plugin-api/src/test/java/org/apache/maven/plugin/logging/SystemStreamLogTest.java @@ -0,0 +1,59 @@ +package org.apache.maven.plugin.logging; + +/* + * 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.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Tests for {@link SystemStreamLog} + */ +public class SystemStreamLogTest +{ + private static final String EXPECTED_MESSAGE = "expected message"; + + /* + * As SystemStreamLog log levels are hardcoded (only info/warn/error are active), this test checks that + * a message supplier is really called/executed when logging at those levels. + */ + @Test + public void testLazyMessageIsEvaluatedForActiveLogLevelsOnly() + { + CountingCallsSupplier messageSupplier = CountingCallsSupplier.of(EXPECTED_MESSAGE); + + Throwable fakeError = new RuntimeException(); + + Log logger = new SystemStreamLog(); + + logger.debug(messageSupplier); + logger.info(messageSupplier); + logger.warn(messageSupplier); + logger.error(messageSupplier); + + logger.debug(messageSupplier, fakeError); + logger.info(messageSupplier, fakeError); + logger.warn(messageSupplier, fakeError); + logger.error(messageSupplier, fakeError); + + // calls at debug log level should have not lead to a Supplier call + assertEquals(6, messageSupplier.getNumberOfCalls(), "wrong number of calls to the message supplier"); + } +}