Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import java.util.Properties;
import java.util.function.Consumer;
import java.util.function.UnaryOperator;
import java.util.logging.Handler;

import org.apache.maven.api.Constants;
import org.apache.maven.api.ProtoSession;
Expand Down Expand Up @@ -124,6 +125,8 @@ public final int invoke(InvokerRequest invokerRequest) {
Properties oldProps = new Properties();
oldProps.putAll(System.getProperties());
ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
// activateLogging() replaces them with SLF4JBridgeHandler, whose classes live in Maven's realm
Handler[] oldRootLoggerHandlers = java.util.logging.Logger.getLogger("").getHandlers();
try (C context = createContext(invokerRequest)) {
if (contextConsumer != null) {
contextConsumer.accept(context);
Expand All @@ -147,6 +150,22 @@ public final int invoke(InvokerRequest invokerRequest) {
} finally {
Thread.currentThread().setContextClassLoader(oldCL);
System.setProperties(oldProps);
restoreRootLoggerHandlers(oldRootLoggerHandlers);
}
}

/**
* Puts back the handlers the {@code java.util.logging} root logger had before the invocation. When Maven runs inside
* another JVM, the root logger belongs to that JVM, and a {@code SLF4JBridgeHandler} left on it would route the
* host's logging to Maven and fail once Maven's class realm is closed.
*/
private static void restoreRootLoggerHandlers(Handler[] handlers) {
java.util.logging.Logger root = java.util.logging.Logger.getLogger("");
for (Handler handler : root.getHandlers()) {
root.removeHandler(handler);
}
for (Handler handler : handlers) {
root.addHandler(handler);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
import java.nio.file.Path;
import java.util.List;
import java.util.Map;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;

import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
Expand All @@ -37,6 +39,7 @@
import org.junit.jupiter.api.io.CleanupMode;
import org.junit.jupiter.api.io.TempDir;

import static org.junit.jupiter.api.Assertions.assertArrayEquals;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
Expand Down Expand Up @@ -66,6 +69,37 @@ void defaultFs(
invoke(cwd, userHome, List.of("verify"), List.of());
}

/**
* The invocation replaces the handlers of the {@code java.util.logging} root logger with {@code SLF4JBridgeHandler};
* they must be back afterwards, as the root logger belongs to the JVM Maven runs in (GH-13362).
*/
@Test
void restoresJavaUtilLoggingRootHandlers(
@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path cwd,
@TempDir(cleanup = CleanupMode.ON_SUCCESS) Path userHome)
throws Exception {
java.util.logging.Logger root = java.util.logging.Logger.getLogger("");
Handler[] original = root.getHandlers();
Handler marker = new ConsoleHandler();
for (Handler handler : original) {
root.removeHandler(handler);
}
root.addHandler(marker);
try {
invoke(cwd, userHome, List.of("validate"), List.of());

assertArrayEquals(new Handler[] {marker}, root.getHandlers());
} finally {
root.removeHandler(marker);
for (Handler handler : root.getHandlers()) {
root.removeHandler(handler);
}
for (Handler handler : original) {
root.addHandler(handler);
}
}
}

@Disabled("Enable it when fully moved to NIO2 with Path/Filesystem (ie MavenExecutionRequest)")
@Test
void jimFs() throws Exception {
Expand Down
Loading