17ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu/** 27ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * Copyright (c) 2004-2011 QOS.ch 388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * All rights reserved. 47ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * 588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * Permission is hereby granted, free of charge, to any person obtaining 688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * a copy of this software and associated documentation files (the 788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * "Software"), to deal in the Software without restriction, including 888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * without limitation the rights to use, copy, modify, merge, publish, 988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * distribute, sublicense, and/or sell copies of the Software, and to 1088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * permit persons to whom the Software is furnished to do so, subject to 1188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * the following conditions: 127ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * 1388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * The above copyright notice and this permission notice shall be 1488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * included in all copies or substantial portions of the Software. 157ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * 1688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 1988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 2088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 2188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 2288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 237ba0605dc97fb81bde8311510d27b3ccba170008Ceki Gulcu * 2488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu */ 2588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcupackage org.slf4j; 2688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 2788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport java.io.IOException; 2888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport java.net.URL; 292f82a78ab216cfacbc465cc48da0038a20d45d18Hendy Irawanimport java.util.Arrays; 302f82a78ab216cfacbc465cc48da0038a20d45d18Hendy Irawanimport java.util.Enumeration; 312f82a78ab216cfacbc465cc48da0038a20d45d18Hendy Irawanimport java.util.Iterator; 322f82a78ab216cfacbc465cc48da0038a20d45d18Hendy Irawanimport java.util.LinkedHashSet; 332f82a78ab216cfacbc465cc48da0038a20d45d18Hendy Irawanimport java.util.List; 342f82a78ab216cfacbc465cc48da0038a20d45d18Hendy Irawanimport java.util.Set; 352f82a78ab216cfacbc465cc48da0038a20d45d18Hendy Irawan 36d1d27b8d8748190f397b0be72c8d85722f8c5b00Ceki Gulcuimport org.slf4j.helpers.NOPLoggerFactory; 378f28a83eb4f6b81dd46e53052e17df3aaf602347Ceki Gulcuimport org.slf4j.helpers.SubstituteLogger; 3888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport org.slf4j.helpers.SubstituteLoggerFactory; 3988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport org.slf4j.helpers.Util; 4088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcuimport org.slf4j.impl.StaticLoggerBinder; 4188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 4288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu/** 4388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * The <code>LoggerFactory</code> is a utility class producing Loggers for 449f10490a05f7344f4b3ef657e8991f5d51934e2fCeki Gulcu * various logging APIs, most notably for log4j, logback and JDK 1.4 logging. 4588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * Other implementations such as {@link org.slf4j.impl.NOPLogger NOPLogger} and 4688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * {@link org.slf4j.impl.SimpleLogger SimpleLogger} are also supported. 47e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu * <p/> 48e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu * <p/> 4988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * <code>LoggerFactory</code> is essentially a wrapper around an 5088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * {@link ILoggerFactory} instance bound with <code>LoggerFactory</code> at 5188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * compile time. 52e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu * <p/> 53e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu * <p/> 5488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * Please note that all methods in <code>LoggerFactory</code> are static. 55e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu * 5626b01116722ebdd3b2471a6579f9d5a6feda83e7Ceki Gulcu * 577552796aa666c11442713cba37e7fbc339bfa020Alexander Dorokhine * @author Alexander Dorokhine 5888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu * @author Robert Elliot 5926b01116722ebdd3b2471a6579f9d5a6feda83e7Ceki Gulcu * @author Ceki Gülcü 6026b01116722ebdd3b2471a6579f9d5a6feda83e7Ceki Gulcu * 6188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu */ 6288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcupublic final class LoggerFactory { 6388c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 6431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String CODES_PREFIX = "http://www.slf4j.org/codes.html"; 6588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 6631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String NO_STATICLOGGERBINDER_URL = CODES_PREFIX + "#StaticLoggerBinder"; 6731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String MULTIPLE_BINDINGS_URL = CODES_PREFIX + "#multiple_bindings"; 6831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String NULL_LF_URL = CODES_PREFIX + "#null_LF"; 6931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String VERSION_MISMATCH = CODES_PREFIX + "#version_mismatch"; 7031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String SUBSTITUTE_LOGGER_URL = CODES_PREFIX + "#substituteLogger"; 7131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String LOGGER_NAME_MISMATCH_URL = CODES_PREFIX + "#loggerNameMismatch"; 72e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu 7331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String UNSUCCESSFUL_INIT_URL = CODES_PREFIX + "#unsuccessfulInit"; 7431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String UNSUCCESSFUL_INIT_MSG = "org.slf4j.LoggerFactory could not be successfully initialized. See also " + UNSUCCESSFUL_INIT_URL; 7588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 7631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final int UNINITIALIZED = 0; 7731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final int ONGOING_INITIALIZATION = 1; 7831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final int FAILED_INITIALIZATION = 2; 7931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final int SUCCESSFUL_INITIALIZATION = 3; 8031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final int NOP_FALLBACK_INITIALIZATION = 4; 8188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 8231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static int INITIALIZATION_STATE = UNINITIALIZED; 8331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static SubstituteLoggerFactory TEMP_FACTORY = new SubstituteLoggerFactory(); 8431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static NOPLoggerFactory NOP_FALLBACK_FACTORY = new NOPLoggerFactory(); 8588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 8631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // Support for detecting mismatched logger names. 8731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static final String DETECT_LOGGER_NAME_MISMATCH_PROPERTY = "slf4j.detectLoggerNameMismatch"; 8831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static boolean DETECT_LOGGER_NAME_MISMATCH = Boolean.getBoolean(DETECT_LOGGER_NAME_MISMATCH_PROPERTY); 8997f96c5ad52259c2e620370309cf129b7ba30f54Alexander Dorokhine 9031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 9131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * It is LoggerFactory's responsibility to track version changes and manage 9231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * the compatibility list. 9331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p/> 9431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p/> 9531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * It is assumed that all versions in the 1.6 are mutually compatible. 9631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 9731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static private final String[] API_COMPATIBILITY_LIST = new String[] { "1.6", "1.7" }; 9888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 9931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // private constructor prevents instantiation 10031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private LoggerFactory() { 10131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 10288c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 10331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 10431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * Force LoggerFactory to consider itself uninitialized. 10531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p/> 10631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p/> 10731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * This method is intended to be called by classes (in the same package) for 10831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * testing purposes. This method is internal. It can be modified, renamed or 10931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * removed at any time without notice. 11031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p/> 11131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p/> 11231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * You are strongly discouraged from calling this method in production code. 11331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 11431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static void reset() { 11531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu INITIALIZATION_STATE = UNINITIALIZED; 11631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu TEMP_FACTORY = new SubstituteLoggerFactory(); 11731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 11888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 11931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private final static void performInitialization() { 12031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu bind(); 12131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) { 12231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu versionSanityCheck(); 12331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 124d1d27b8d8748190f397b0be72c8d85722f8c5b00Ceki Gulcu } 12588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 12631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static boolean messageContainsOrgSlf4jImplStaticLoggerBinder(String msg) { 12731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (msg == null) 12831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return false; 12931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (msg.indexOf("org/slf4j/impl/StaticLoggerBinder") != -1) 13031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return true; 13131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (msg.indexOf("org.slf4j.impl.StaticLoggerBinder") != -1) 13231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return true; 13331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return false; 13431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 13567f86a636d4f8b01d7ab324b8206602c47907473Ceki Gulcu 13631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private final static void bind() { 13731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu try { 13831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Set<URL> staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet(); 13931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu reportMultipleBindingAmbiguity(staticLoggerBinderPathSet); 14031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // the next line does the binding 14131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu StaticLoggerBinder.getSingleton(); 14231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION; 14331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu reportActualBinding(staticLoggerBinderPathSet); 14431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu fixSubstitutedLoggers(); 14531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } catch (NoClassDefFoundError ncde) { 14631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu String msg = ncde.getMessage(); 14731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) { 14831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION; 14931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\"."); 15031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Defaulting to no-operation (NOP) logger implementation"); 15131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("See " + NO_STATICLOGGERBINDER_URL + " for further details."); 15231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } else { 15331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu failedBinding(ncde); 15431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu throw ncde; 15531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 15631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } catch (java.lang.NoSuchMethodError nsme) { 15731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu String msg = nsme.getMessage(); 15831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (msg != null && msg.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) { 15931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu INITIALIZATION_STATE = FAILED_INITIALIZATION; 16031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding."); 16131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Your binding is version 1.5.5 or earlier."); 16231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Upgrade your binding to version 1.6.x."); 16331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 16431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu throw nsme; 16531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } catch (Exception e) { 16631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu failedBinding(e); 16731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu throw new IllegalStateException("Unexpected initialization failure", e); 16831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 16931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 17031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 17131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu static void failedBinding(Throwable t) { 172e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu INITIALIZATION_STATE = FAILED_INITIALIZATION; 17331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Failed to instantiate SLF4J LoggerFactory", t); 17488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu } 17588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 17631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private final static void fixSubstitutedLoggers() { 17731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu List<SubstituteLogger> loggers = TEMP_FACTORY.getLoggers(); 178d1d27b8d8748190f397b0be72c8d85722f8c5b00Ceki Gulcu 17931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (loggers.isEmpty()) { 18031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return; 18131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 1824f1bf59089529a4ab386ab9270bdd58374ac36dcChetan Mehrotra 18331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("The following set of substitute loggers may have been accessed"); 18431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("during the initialization phase. Logging calls during this"); 18531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("phase were not honored. However, subsequent logging calls to these"); 18631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("loggers will work as normally expected."); 18731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("See also " + SUBSTITUTE_LOGGER_URL); 18831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu for (SubstituteLogger subLogger : loggers) { 18931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu subLogger.setDelegate(getLogger(subLogger.getName())); 19031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report(subLogger.getName()); 19131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 1924f1bf59089529a4ab386ab9270bdd58374ac36dcChetan Mehrotra 19331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu TEMP_FACTORY.clear(); 19488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu } 1954f1bf59089529a4ab386ab9270bdd58374ac36dcChetan Mehrotra 19631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private final static void versionSanityCheck() { 19731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu try { 19831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu String requested = StaticLoggerBinder.REQUESTED_API_VERSION; 19988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 20031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu boolean match = false; 20131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu for (int i = 0; i < API_COMPATIBILITY_LIST.length; i++) { 20231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (requested.startsWith(API_COMPATIBILITY_LIST[i])) { 20331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu match = true; 20431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 20531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 20631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (!match) { 20731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("The requested version " + requested + " by your slf4j binding is not compatible with " 20831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu + Arrays.asList(API_COMPATIBILITY_LIST).toString()); 20931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("See " + VERSION_MISMATCH + " for further details."); 21031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 21131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } catch (java.lang.NoSuchFieldError nsfe) { 21231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // given our large user base and SLF4J's commitment to backward 21331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // compatibility, we cannot cry here. Only for implementations 21431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // which willingly declare a REQUESTED_API_VERSION field do we 21531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // emit compatibility warnings. 21631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } catch (Throwable e) { 21731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // we should never reach here 21831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Unexpected problem occured during version sanity check", e); 21988c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu } 22088c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu } 22188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 22231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // We need to use the name of the StaticLoggerBinder class, but we can't reference 22331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // the class itself. 22431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class"; 22588c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 22631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static Set<URL> findPossibleStaticLoggerBinderPathSet() { 22731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // use Set instead of list in order to deal with bug #138 22831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // LinkedHashSet appropriate here because it preserves insertion order during iteration 22931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>(); 23031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu try { 23131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader(); 23231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Enumeration<URL> paths; 23331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (loggerFactoryClassLoader == null) { 23431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH); 23531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } else { 23631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH); 23731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 23831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu while (paths.hasMoreElements()) { 23931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu URL path = (URL) paths.nextElement(); 24031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu staticLoggerBinderPathSet.add(path); 24131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 24231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } catch (IOException ioe) { 24331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Error getting resources from path", ioe); 24431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 24531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return staticLoggerBinderPathSet; 24688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu } 247e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu 24831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static boolean isAmbiguousStaticLoggerBinderPathSet(Set<URL> staticLoggerBinderPathSet) { 24931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return staticLoggerBinderPathSet.size() > 1; 250e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu } 25188c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 25231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 25331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * Prints a warning message on the console if multiple bindings were found on the class path. 25431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * No reporting is done otherwise. 25531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 25631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 25731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static void reportMultipleBindingAmbiguity(Set<URL> staticLoggerBinderPathSet) { 25831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) { 25931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Class path contains multiple SLF4J bindings."); 26031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Iterator<URL> iterator = staticLoggerBinderPathSet.iterator(); 26131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu while (iterator.hasNext()) { 26231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu URL path = (URL) iterator.next(); 26331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Found binding in [" + path + "]"); 26431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 26531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation."); 26631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 267e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu } 268e5eb0b068d3e99fb5a39c82ce6f72e484f33e9d1Ceki Gulcu 26931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static void reportActualBinding(Set<URL> staticLoggerBinderPathSet) { 27031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (isAmbiguousStaticLoggerBinderPathSet(staticLoggerBinderPathSet)) { 27131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("Actual binding is of type [" + StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr() + "]"); 27231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 27331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 27488c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 27531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 27631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * Return a logger named according to the name parameter using the statically 27731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * bound {@link ILoggerFactory} instance. 27831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 27931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @param name The name of the logger. 28031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @return logger 28131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 28231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu public static Logger getLogger(String name) { 28331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu ILoggerFactory iLoggerFactory = getILoggerFactory(); 28431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return iLoggerFactory.getLogger(name); 28597f96c5ad52259c2e620370309cf129b7ba30f54Alexander Dorokhine } 28688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu 28731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 28831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * Return a logger named corresponding to the class passed as parameter, using 28931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * the statically bound {@link ILoggerFactory} instance. 29031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 29131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p>In case the the <code>clazz</code> parameter differs from the name of 29231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * the caller as computed internally by SLF4J, a logger name mismatch warning will be 29331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * printed but only if the <code>slf4j.detectLoggerNameMismatch</code> system property is 29431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * set to true. By default, this property is not set and no warnings will be printed 29531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * even in case of a logger name mismatch. 29631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 29731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @param clazz the returned logger will be named after clazz 29831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @return logger 29931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 30031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 30131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @see <a href="http://www.slf4j.org/codes.html#loggerNameMismatch">Detected logger name mismatch</a> 30231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 30331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu public static Logger getLogger(Class<?> clazz) { 30431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Logger logger = getLogger(clazz.getName()); 30531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (DETECT_LOGGER_NAME_MISMATCH) { 30631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Class<?> autoComputedCallingClass = Util.getCallingClass(); 30731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (nonMatchingClasses(clazz, autoComputedCallingClass)) { 30831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(), 30931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu autoComputedCallingClass.getName())); 31031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation"); 31131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 31231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 31331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return logger; 31431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 315c0f5835dcd6fdf7f9e2224211ccf8fe6b98cd7c7Ceki Gulcu 31631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu private static boolean nonMatchingClasses(Class<?> clazz, Class<?> autoComputedCallingClass) { 31731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return !autoComputedCallingClass.isAssignableFrom(clazz); 31888c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu } 31931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu 32031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu /** 32131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * Return the {@link ILoggerFactory} instance in use. 32231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p/> 32331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * <p/> 32431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * ILoggerFactory instance is bound with this class at compile time. 32531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * 32631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu * @return the ILoggerFactory instance in use 32731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu */ 32831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu public static ILoggerFactory getILoggerFactory() { 32931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu if (INITIALIZATION_STATE == UNINITIALIZED) { 33031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu INITIALIZATION_STATE = ONGOING_INITIALIZATION; 33131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu performInitialization(); 33231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 33331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu switch (INITIALIZATION_STATE) { 33431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu case SUCCESSFUL_INITIALIZATION: 33531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return StaticLoggerBinder.getSingleton().getLoggerFactory(); 33631212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu case NOP_FALLBACK_INITIALIZATION: 33731212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return NOP_FALLBACK_FACTORY; 33831212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu case FAILED_INITIALIZATION: 33931212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG); 34031212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu case ONGOING_INITIALIZATION: 34131212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // support re-entrant behavior. 34231212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106 34331212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu return TEMP_FACTORY; 34431212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu } 34531212435723e2dfd5d6716d1f6a7b0e66a1e6b38Ceki Gulcu throw new IllegalStateException("Unreachable code"); 34688c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu } 34788c4c456766193e012eb890e2208473d99b91f83Ceki Gulcu} 348