001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017 018package org.apache.logging.log4j.jul; 019 020import java.util.ArrayList; 021import java.util.Collections; 022import java.util.Comparator; 023import java.util.IdentityHashMap; 024import java.util.List; 025import java.util.Map; 026import java.util.concurrent.ConcurrentHashMap; 027import java.util.concurrent.ConcurrentMap; 028 029import org.apache.logging.log4j.Level; 030 031/** 032 * Default implementation of LevelConverter strategy. 033 * <p> 034 * Since 2.4, supports custom JUL levels by mapping them to their closest mapped neighbour. 035 * </p> 036 * 037 * @since 2.1 038 */ 039public class DefaultLevelConverter implements LevelConverter { 040 041 static final class JulLevelComparator implements Comparator<java.util.logging.Level> { 042 @Override 043 public int compare(final java.util.logging.Level level1, final java.util.logging.Level level2) { 044 return Integer.compare(level1.intValue(), level2.intValue()); 045 } 046 } 047 048 private final ConcurrentMap<java.util.logging.Level, Level> julToLog4j = new ConcurrentHashMap<>(9); 049 private final Map<Level, java.util.logging.Level> log4jToJul = new IdentityHashMap<>(10); 050 private final List<java.util.logging.Level> sortedJulLevels = new ArrayList<>(9); 051 052 public DefaultLevelConverter() { 053 // Map JUL to Log4j 054 mapJulToLog4j(java.util.logging.Level.ALL, Level.ALL); 055 mapJulToLog4j(java.util.logging.Level.FINEST, LevelTranslator.FINEST); 056 mapJulToLog4j(java.util.logging.Level.FINER, Level.TRACE); 057 mapJulToLog4j(java.util.logging.Level.FINE, Level.DEBUG); 058 mapJulToLog4j(java.util.logging.Level.CONFIG, LevelTranslator.CONFIG); 059 mapJulToLog4j(java.util.logging.Level.INFO, Level.INFO); 060 mapJulToLog4j(java.util.logging.Level.WARNING, Level.WARN); 061 mapJulToLog4j(java.util.logging.Level.SEVERE, Level.ERROR); 062 mapJulToLog4j(java.util.logging.Level.OFF, Level.OFF); 063 // Map Log4j to JUL 064 mapLog4jToJul(Level.ALL, java.util.logging.Level.ALL); 065 mapLog4jToJul(LevelTranslator.FINEST, java.util.logging.Level.FINEST); 066 mapLog4jToJul(Level.TRACE, java.util.logging.Level.FINER); 067 mapLog4jToJul(Level.DEBUG, java.util.logging.Level.FINE); 068 mapLog4jToJul(LevelTranslator.CONFIG, java.util.logging.Level.CONFIG); 069 mapLog4jToJul(Level.INFO, java.util.logging.Level.INFO); 070 mapLog4jToJul(Level.WARN, java.util.logging.Level.WARNING); 071 mapLog4jToJul(Level.ERROR, java.util.logging.Level.SEVERE); 072 mapLog4jToJul(Level.FATAL, java.util.logging.Level.SEVERE); 073 mapLog4jToJul(Level.OFF, java.util.logging.Level.OFF); 074 // Sorted Java levels 075 sortedJulLevels.addAll(julToLog4j.keySet()); 076 Collections.sort(sortedJulLevels, new JulLevelComparator()); 077 078 } 079 080 private long distance(final java.util.logging.Level javaLevel, final java.util.logging.Level customJavaLevel) { 081 return Math.abs((long) customJavaLevel.intValue() - (long) javaLevel.intValue()); 082 } 083 084 /* 085 * TODO consider making public for advanced configuration. 086 */ 087 private void mapJulToLog4j(final java.util.logging.Level julLevel, final Level level) { 088 julToLog4j.put(julLevel, level); 089 } 090 091 /* 092 * TODO consider making public for advanced configuration. 093 */ 094 private void mapLog4jToJul(final Level level, final java.util.logging.Level julLevel) { 095 log4jToJul.put(level, julLevel); 096 } 097 098 private Level nearestLevel(final java.util.logging.Level customJavaLevel) { 099 long prevDist = Long.MAX_VALUE; 100 java.util.logging.Level prevLevel = null; 101 for (final java.util.logging.Level mappedJavaLevel : sortedJulLevels) { 102 final long distance = distance(customJavaLevel, mappedJavaLevel); 103 if (distance > prevDist) { 104 return julToLog4j.get(prevLevel); 105 } 106 prevDist = distance; 107 prevLevel = mappedJavaLevel; 108 } 109 return julToLog4j.get(prevLevel); 110 } 111 112 @Override 113 public java.util.logging.Level toJavaLevel(final Level level) { 114 return log4jToJul.get(level); 115 } 116 117 @Override 118 public Level toLevel(final java.util.logging.Level javaLevel) { 119 if (javaLevel == null) { 120 return null; 121 } 122 final Level level = julToLog4j.get(javaLevel); 123 if (level != null) { 124 return level; 125 } 126 final Level nearestLevel = nearestLevel(javaLevel); 127 julToLog4j.put(javaLevel, nearestLevel); 128 return nearestLevel; 129 } 130}