diff --git a/log4j-jul/src/main/java/org/apache/logging/log4j/jul/DefaultLevelConverter.java b/log4j-jul/src/main/java/org/apache/logging/log4j/jul/DefaultLevelConverter.java index 5d84de4..ffebb14 100644 --- a/log4j-jul/src/main/java/org/apache/logging/log4j/jul/DefaultLevelConverter.java +++ b/log4j-jul/src/main/java/org/apache/logging/log4j/jul/DefaultLevelConverter.java @@ -17,7 +17,11 @@ package org.apache.logging.log4j.jul; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.IdentityHashMap; +import java.util.List; import java.util.Map; import org.apache.logging.log4j.Level; @@ -31,10 +35,11 @@ private final Map julToLog4j = new IdentityHashMap<>(9); private final Map log4jToJul = new IdentityHashMap<>(10); + private final List sortedJavaLevels = new ArrayList<>(9); public DefaultLevelConverter() { // Map JUL to Log4j - mapJulToLog4j(java.util.logging.Level.OFF, Level.OFF); + mapJulToLog4j(java.util.logging.Level.ALL, Level.ALL); mapJulToLog4j(java.util.logging.Level.FINEST, LevelTranslator.FINEST); mapJulToLog4j(java.util.logging.Level.FINER, Level.TRACE); mapJulToLog4j(java.util.logging.Level.FINE, Level.DEBUG); @@ -42,9 +47,9 @@ mapJulToLog4j(java.util.logging.Level.INFO, Level.INFO); mapJulToLog4j(java.util.logging.Level.WARNING, Level.WARN); mapJulToLog4j(java.util.logging.Level.SEVERE, Level.ERROR); - mapJulToLog4j(java.util.logging.Level.ALL, Level.ALL); + mapJulToLog4j(java.util.logging.Level.OFF, Level.OFF); // Map Log4j to JUL - mapLog4jToJul(Level.OFF, java.util.logging.Level.OFF); + mapLog4jToJul(Level.ALL, java.util.logging.Level.ALL); mapLog4jToJul(LevelTranslator.FINEST, java.util.logging.Level.FINEST); mapLog4jToJul(Level.TRACE, java.util.logging.Level.FINER); mapLog4jToJul(Level.DEBUG, java.util.logging.Level.FINE); @@ -53,16 +58,50 @@ mapLog4jToJul(Level.WARN, java.util.logging.Level.WARNING); mapLog4jToJul(Level.ERROR, java.util.logging.Level.SEVERE); mapLog4jToJul(Level.FATAL, java.util.logging.Level.SEVERE); - mapLog4jToJul(Level.ALL, java.util.logging.Level.ALL); + mapLog4jToJul(Level.OFF, java.util.logging.Level.OFF); + // Sorted Java levels + sortedJavaLevels.addAll(julToLog4j.keySet()); + Collections.sort(sortedJavaLevels, new Comparator() { + + @Override + public int compare(java.util.logging.Level level1, java.util.logging.Level level2) { + return Integer.compare(level1.intValue(), level2.intValue()); + } + }); + } - + + private Level addCustomLevel(java.util.logging.Level customJavaLevel) { + long prevDist = Long.MAX_VALUE; + java.util.logging.Level prevLevel = null; + for (java.util.logging.Level mappedJavaLevel : sortedJavaLevels) { + long distance = distance(customJavaLevel, mappedJavaLevel); + if (distance > prevDist) { + return mapCustomJavaLevel(customJavaLevel, prevLevel); + } + prevDist = distance; + prevLevel = mappedJavaLevel; + } + return mapCustomJavaLevel(customJavaLevel, prevLevel); + } + + private long distance(java.util.logging.Level javaLevel, java.util.logging.Level customJavaLevel) { + return Math.abs((long) customJavaLevel.intValue() - (long) javaLevel.intValue()); + } + + private Level mapCustomJavaLevel(java.util.logging.Level customJavaLevel, java.util.logging.Level stdJavaLevel) { + final Level level = julToLog4j.get(stdJavaLevel); + julToLog4j.put(customJavaLevel, level); + return level; + } + /* * TODO consider making public. */ private void mapJulToLog4j(java.util.logging.Level julLevel, Level level) { julToLog4j.put(julLevel, level); } - + /* * TODO consider making public. */ @@ -77,6 +116,7 @@ @Override public Level toLevel(final java.util.logging.Level javaLevel) { - return julToLog4j.get(javaLevel); + final Level level = julToLog4j.get(javaLevel); + return level != null ? level : addCustomLevel(javaLevel); } } diff --git a/log4j-jul/src/test/java/org/apache/logging/log4j/jul/DefaultLevelConverterTest.java b/log4j-jul/src/test/java/org/apache/logging/log4j/jul/DefaultLevelConverterTest.java new file mode 100644 index 0000000..350fffd --- /dev/null +++ b/log4j-jul/src/test/java/org/apache/logging/log4j/jul/DefaultLevelConverterTest.java @@ -0,0 +1,144 @@ +/* + * 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. + */ +package org.apache.logging.log4j.jul; + +import org.apache.logging.log4j.Level; +import org.junit.Assert; +import org.junit.Test; + +/** + * Tests DefaultLevelConverter. + * + * @since 2.4 + */ +public class DefaultLevelConverterTest { + + static class CustomLevel extends java.util.logging.Level { + + private static final long serialVersionUID = 1L; + + static CustomLevel ALL_P_1 = new CustomLevel("ALL_P_1", java.util.logging.Level.ALL.intValue() + 1); + + static CustomLevel FINEST_P_1 = new CustomLevel("FINEST_P_1", java.util.logging.Level.FINEST.intValue() + 1); + static CustomLevel FINEST_M_1 = new CustomLevel("FINEST_M_1", java.util.logging.Level.FINEST.intValue() - 1); + + static CustomLevel FINER_P_1 = new CustomLevel("FINER_P_1", java.util.logging.Level.FINER.intValue() + 1); + static CustomLevel FINER_M_1 = new CustomLevel("FINER_M_1", java.util.logging.Level.FINER.intValue() - 1); + + static CustomLevel FINE_P_1 = new CustomLevel("FINE_P_1", java.util.logging.Level.FINE.intValue() + 1); + static CustomLevel FINE_M_1 = new CustomLevel("FINE_M_1", java.util.logging.Level.FINE.intValue() - 1); + + static CustomLevel CONFIG_P_1 = new CustomLevel("CONFIG_P_1", java.util.logging.Level.CONFIG.intValue() + 1); + static CustomLevel CONFIG_M_1 = new CustomLevel("CONFIG_M_1", java.util.logging.Level.CONFIG.intValue() - 1); + + static CustomLevel INFO_P_1 = new CustomLevel("INFO_P_1", java.util.logging.Level.INFO.intValue() + 1); + static CustomLevel INFO_M_1 = new CustomLevel("INFO_M_1", java.util.logging.Level.INFO.intValue() - 1); + + static CustomLevel WARNING_P_1 = new CustomLevel("WARNING_P_1", java.util.logging.Level.WARNING.intValue() + 1); + static CustomLevel WARNING_M_1 = new CustomLevel("WARNING_M_1", java.util.logging.Level.WARNING.intValue() - 1); + + static CustomLevel SEVERE_P_1 = new CustomLevel("SEVERE_P_1", java.util.logging.Level.SEVERE.intValue() + 1); + static CustomLevel SEVERE_M_1 = new CustomLevel("SEVERE_M_1", java.util.logging.Level.SEVERE.intValue() - 1); + + static CustomLevel OFF_M_1 = new CustomLevel("OFF_M_1", java.util.logging.Level.OFF.intValue() - 1); + + protected CustomLevel(String name, int value) { + super(name, value); + } + } + + private DefaultLevelConverter converter = new DefaultLevelConverter(); + + @Test + public void testCustomJulLevelNearAll() { + // Sanity check: + Assert.assertEquals(Level.ALL, converter.toLevel(java.util.logging.Level.ALL)); + // Test: + Assert.assertEquals(Level.ALL, converter.toLevel(CustomLevel.ALL_P_1)); + } + + @Test + public void testCustomJulLevelNearFinest() { + // Sanity check: + Assert.assertEquals(LevelTranslator.FINEST, converter.toLevel(java.util.logging.Level.FINEST)); + // Test: + Assert.assertEquals(LevelTranslator.FINEST, converter.toLevel(CustomLevel.FINEST_P_1)); + Assert.assertEquals(LevelTranslator.FINEST, converter.toLevel(CustomLevel.FINEST_M_1)); + } + + @Test + public void testCustomJulLevelNearFiner() { + // Sanity check: + Assert.assertEquals(Level.TRACE, converter.toLevel(java.util.logging.Level.FINER)); + // Test: + Assert.assertEquals(Level.TRACE, converter.toLevel(CustomLevel.FINER_P_1)); + Assert.assertEquals(Level.TRACE, converter.toLevel(CustomLevel.FINER_M_1)); + } + + @Test + public void testCustomJulLevelNearFine() { + // Sanity check: + Assert.assertEquals(Level.DEBUG, converter.toLevel(java.util.logging.Level.FINE)); + // Test: + Assert.assertEquals(Level.DEBUG, converter.toLevel(CustomLevel.FINE_P_1)); + Assert.assertEquals(Level.DEBUG, converter.toLevel(CustomLevel.FINE_M_1)); + } + + @Test + public void testCustomJulLevelNearConfig() { + // Sanity check: + Assert.assertEquals(LevelTranslator.CONFIG, converter.toLevel(java.util.logging.Level.CONFIG)); + // Test: + Assert.assertEquals(LevelTranslator.CONFIG, converter.toLevel(CustomLevel.CONFIG_P_1)); + Assert.assertEquals(LevelTranslator.CONFIG, converter.toLevel(CustomLevel.CONFIG_M_1)); + } + + @Test + public void testCustomJulLevelNearInfo() { + // Sanity check: + Assert.assertEquals(Level.INFO, converter.toLevel(java.util.logging.Level.INFO)); + // Test: + Assert.assertEquals(Level.INFO, converter.toLevel(CustomLevel.INFO_P_1)); + Assert.assertEquals(Level.INFO, converter.toLevel(CustomLevel.INFO_M_1)); + } + + @Test + public void testCustomJulLevelNearWarning() { + // Sanity check: + Assert.assertEquals(Level.WARN, converter.toLevel(java.util.logging.Level.WARNING)); + // Test: + Assert.assertEquals(Level.WARN, converter.toLevel(CustomLevel.WARNING_P_1)); + Assert.assertEquals(Level.WARN, converter.toLevel(CustomLevel.WARNING_M_1)); + } + + @Test + public void testCustomJulLevelNearSevere() { + // Sanity check: + Assert.assertEquals(Level.ERROR, converter.toLevel(java.util.logging.Level.SEVERE)); + // Test: + Assert.assertEquals(Level.ERROR, converter.toLevel(CustomLevel.SEVERE_P_1)); + Assert.assertEquals(Level.ERROR, converter.toLevel(CustomLevel.SEVERE_M_1)); + } + + @Test + public void testCustomJulLevelNearOff() { + // Sanity check: + Assert.assertEquals(Level.OFF, converter.toLevel(java.util.logging.Level.OFF)); + // Test: + Assert.assertEquals(Level.OFF, converter.toLevel(CustomLevel.OFF_M_1)); + } +}