001/* 002 * Copyright 2023 the original author or authors. 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package de.cuioss.test.juli; 017 018import static de.cuioss.tools.string.MoreStrings.isEmpty; 019 020import java.util.Arrays; 021import java.util.List; 022import java.util.Map.Entry; 023import java.util.Optional; 024import java.util.logging.ConsoleHandler; 025import java.util.logging.Handler; 026import java.util.logging.LogManager; 027import java.util.logging.Logger; 028 029import lombok.experimental.UtilityClass; 030 031/** 032 * Central entry point for handling {@link TestLogHandler} 033 * 034 * 035 * @author Oliver Wolff 036 * 037 */ 038@UtilityClass 039@SuppressWarnings("java:S4792") // owolff: Changing the logger is the actual idea of this type, not 040 // a security issue 041public class TestLoggerFactory { 042 043 private static final StaticLoggerConfigurator configuration = new StaticLoggerConfigurator(); 044 045 private static final ConsoleHandlerModifier CONSOLE_HANDLER = new ConsoleHandlerModifier(); 046 047 /** 048 * Adds a {@link TestLogHandler} instance to jul's root logger. This method is 049 * reentrant, it ensures the {@link TestLogHandler} is installed only once 050 */ 051 public static void install() { 052 if (getTestHandlerOption().isEmpty()) { 053 CONSOLE_HANDLER.saveLevel(); 054 getRootLogger().addHandler(new TestLogHandler()); 055 } 056 } 057 058 /** 059 * Removes previously installed {@link TestLogHandler} instance and restores the 060 * previously stored {@link ConsoleHandler#getLevel()}. See also 061 * {@link #install()}. 062 */ 063 public static void uninstall() { 064 CONSOLE_HANDLER.restoreLevel(); 065 var testHandlerOption = getTestHandlerOption(); 066 testHandlerOption.ifPresent(testLogHandler -> getRootLogger().removeHandler(testLogHandler)); 067 } 068 069 /** 070 * Configures the logger sub-system according to the configuration found within 071 * {@link System#getProperties()} and / or the file "cui_logger.properties" 072 * usually located directly in "src/test/resources". 073 */ 074 public static void configureLogger() { 075 // Set Root logger 076 var rootLevel = configuration.getRootLevel(); 077 rootLevel.setAsRootLevel(); 078 CONSOLE_HANDLER.adjustLevel(rootLevel); 079 // Set concrete logger 080 for (Entry<String, TestLogLevel> entry : configuration.getConfiguredLogger().entrySet()) { 081 entry.getValue().addLogger(entry.getKey()); 082 } 083 } 084 085 private static Logger getRootLogger() { 086 return LogManager.getLogManager().getLogger(""); 087 } 088 089 private static List<Handler> getHandler() { 090 return Arrays.asList(getRootLogger().getHandlers()); 091 } 092 093 /** 094 * @return the configured {@link TestLogHandler} 095 * @throws AssertionError in case no {@link TestLogHandler} could be found. This 096 * is usually the case if {@link #install()} was not 097 * called prior to this request 098 */ 099 public static TestLogHandler getTestHandler() { 100 return getTestHandlerOption().orElseThrow( 101 () -> new AssertionError("Unable to access de.cuioss.test.juli.TestLogHandler. Used properly?")); 102 } 103 104 /** 105 * @return the configured {@link TestLogHandler} if present 106 */ 107 public static Optional<TestLogHandler> getTestHandlerOption() { 108 for (Handler handler : getHandler()) { 109 if (handler instanceof TestLogHandler logHandler) { 110 return Optional.of(logHandler); 111 } 112 } 113 return Optional.empty(); 114 } 115 116 /** 117 * Convenient method for setting a Log-Level in context of the given 118 * {@link TestLogLevel} 119 * 120 * @param logLevel to be set 121 * @param loggerName if it is {@code null} or empty it will set the root-logger 122 * for the actual Log-Level 123 */ 124 public static void addLogger(TestLogLevel logLevel, String loggerName) { 125 CONSOLE_HANDLER.adjustLevel(logLevel); 126 if (isEmpty(loggerName)) { 127 Logger.getLogger("").setLevel(logLevel.getJuliLevel()); 128 } 129 Logger.getLogger(loggerName).setLevel(logLevel.getJuliLevel()); 130 } 131}