1 /* 2 * Copyright (c) 2004-2013 QOS.ch 3 * All rights reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 package org.slf4j.impl; 26 27 import org.slf4j.ILoggerFactory; 28 import org.slf4j.Logger; 29 30 import java.util.concurrent.ConcurrentHashMap; 31 import java.util.concurrent.ConcurrentMap; 32 33 /** 34 * AndroidLoggerFactory is an implementation of {@link ILoggerFactory} returning 35 * the appropriately named {@link AndroidLoggerFactory} instance. 36 * 37 * @author Andrey Korzhevskiy <a.korzhevskiy@gmail.com> 38 */ 39 class AndroidLoggerFactory implements ILoggerFactory { 40 static final String ANONYMOUS_TAG = "null"; 41 static final int TAG_MAX_LENGTH = 23; 42 43 private final ConcurrentMap<String, Logger> loggerMap = new ConcurrentHashMap<String, Logger>(); 44 45 /** 46 * Return an appropriate {@link AndroidLoggerAdapter} instance by name. 47 */ getLogger(String name)48 public Logger getLogger(String name) { 49 String tag = loggerNameToTag(name); 50 Logger logger = loggerMap.get(tag); 51 if (logger == null) { 52 Logger newInstance = new AndroidLoggerAdapter(tag); 53 Logger oldInstance = loggerMap.putIfAbsent(tag, newInstance); 54 logger = oldInstance == null ? newInstance : oldInstance; 55 } 56 return logger; 57 } 58 59 /** 60 * Tag names cannot be longer than {@value #TAG_MAX_LENGTH} characters on Android platform. 61 * 62 * Returns the short logger tag (up to {@value #TAG_MAX_LENGTH} characters) for the given logger name. 63 * Traditionally loggers are named by fully-qualified Java classes; this 64 * method attempts to return a concise identifying part of such names. 65 * 66 * See also: 67 * android/system/core/include/cutils/property.h 68 * android/frameworks/base/core/jni/android_util_Log.cpp 69 * dalvik.system.DalvikLogging 70 * 71 */ loggerNameToTag(String loggerName)72 static String loggerNameToTag(String loggerName) { 73 // Anonymous logger 74 if (loggerName == null) { 75 return ANONYMOUS_TAG; 76 } 77 78 int length = loggerName.length(); 79 if (length <= TAG_MAX_LENGTH) { 80 return loggerName; 81 } 82 83 int tagLength = 0; 84 int lastTokenIndex = 0; 85 int lastPeriodIndex; 86 StringBuilder tagName = new StringBuilder(TAG_MAX_LENGTH + 3); 87 while ((lastPeriodIndex = loggerName.indexOf('.', lastTokenIndex)) != -1) { 88 tagName.append(loggerName.charAt(lastTokenIndex)); 89 // token of one character appended as is otherwise truncate it to one character 90 int tokenLength = lastPeriodIndex - lastTokenIndex; 91 if (tokenLength > 1) { 92 tagName.append('*'); 93 } 94 tagName.append('.'); 95 lastTokenIndex = lastPeriodIndex + 1; 96 97 // check if name is already too long 98 tagLength = tagName.length(); 99 if (tagLength > TAG_MAX_LENGTH) { 100 return getSimpleName(loggerName); 101 } 102 } 103 104 // Either we had no useful dot location at all 105 // or last token would exceed TAG_MAX_LENGTH 106 int tokenLength = length - lastTokenIndex; 107 if (tagLength == 0 || (tagLength + tokenLength) > TAG_MAX_LENGTH) { 108 return getSimpleName(loggerName); 109 } 110 111 // last token (usually class name) appended as is 112 tagName.append(loggerName, lastTokenIndex, length); 113 return tagName.toString(); 114 } 115 getSimpleName(String loggerName)116 private static String getSimpleName(String loggerName) { 117 // Take leading part and append '*' to indicate that it was truncated 118 int length = loggerName.length(); 119 int lastPeriodIndex = loggerName.lastIndexOf('.'); 120 return lastPeriodIndex != -1 && length - (lastPeriodIndex + 1) <= TAG_MAX_LENGTH 121 ? loggerName.substring(lastPeriodIndex + 1) 122 : '*' + loggerName.substring(length - TAG_MAX_LENGTH + 1); 123 } 124 }