| /* |
| * 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 java.util.logging; |
| |
| import dalvik.system.DalvikLogHandler; |
| import dalvik.system.DalvikLogging; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.MissingResourceException; |
| import java.util.ResourceBundle; |
| import java.util.concurrent.CopyOnWriteArrayList; |
| |
| /** |
| * Loggers are used to log records to a variety of destinations such as log files or |
| * the console. They use instances of {@link Handler} to actually do the destination-specific |
| * operations. |
| * |
| * <p>Client applications can get named loggers by calling the {@code getLogger} |
| * methods. They can also get anonymous loggers by calling the |
| * {@code getAnonymousLogger} methods. Named loggers are organized in a |
| * namespace hierarchy managed by a log manager. The naming convention is |
| * usually the Java package naming convention. Anonymous loggers do not belong to any namespace. |
| * |
| * <p>Developers should use named loggers to enable logging to be controlled on a |
| * per-{@code Logger} granularity. The recommended idiom is to create and assign the logger to |
| * a {@code static final} field. This ensures that there's always a strong reference to the logger, |
| * preventing it from being garbage collected. In particular, {@link LogManager#addLogger(Logger)} |
| * will <i>not</i> keep your logger live. |
| * |
| * <p>Loggers "inherit" log level setting from their parent if their own level is |
| * set to {@code null}. This is also true for the resource bundle. The logger's |
| * resource bundle is used to localize the log messages if no resource bundle |
| * name is given when a log method is called. If {@code getUseParentHandlers()} |
| * returns {@code true}, loggers also inherit their parent's handlers. In this |
| * context, "inherit" only means that "behavior" is inherited. The internal |
| * field values will not change, for example, {@code getLevel()} still returns |
| * {@code null}. |
| * <p> |
| * When loading a given resource bundle, the logger first tries to use the |
| * context {@code ClassLoader}. If that fails, it tries the system {@code ClassLoader}. And if |
| * that still fails, it searches up the class stack and uses each class's |
| * {@code ClassLoader} to try to locate the resource bundle. |
| * <p> |
| * Some log methods accept log requests that do not specify the source class and |
| * source method. In these cases, the logging framework will automatically infer |
| * the calling class and method, but this is not guaranteed to be accurate. |
| * <p> |
| * Once a {@code LogRecord} object has been passed into the logging framework, |
| * it is owned by the logging framework and the client applications should not |
| * use it any longer. |
| * <p> |
| * All methods of this class are thread-safe. |
| * |
| * @see LogManager |
| */ |
| public class Logger { |
| |
| /** A handler for use when no handler optimization is possible. */ |
| private static final DalvikLogHandler GENERAL_LOG_HANDLER = new DalvikLogHandler() { |
| public void publish(Logger source, String tag, Level level, String message) { |
| LogRecord record = new LogRecord(level, message); |
| record.setLoggerName(source.name); |
| source.setResourceBundle(record); |
| source.log(record); |
| } |
| }; |
| |
| /** |
| * The name of the global logger. Before using this, see the discussion of how to use |
| * {@code Logger} in the class documentation. |
| * @since 1.6 |
| */ |
| public static final String GLOBAL_LOGGER_NAME = "global"; |
| |
| /** |
| * The global logger is provided as convenience for casual use. |
| * @deprecated deadlock-prone. Use {@code Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)} as |
| * a direct replacement, but see the discussion of how to use {@code Logger} in the class |
| * documentation. |
| */ |
| @Deprecated |
| public static final Logger global = new Logger(GLOBAL_LOGGER_NAME, null); |
| |
| /** |
| * When converting the concurrent collection of handlers to an array, we |
| * always pass a zero-length array to avoid size miscalculations. Passing |
| * properly-sized arrays is non-atomic, and risks a null element in the |
| * result. |
| */ |
| private static final Handler[] EMPTY_HANDLERS_ARRAY = new Handler[0]; |
| |
| /** The name of this logger. */ |
| private volatile String name; |
| |
| /** The parent logger of this logger. */ |
| Logger parent; |
| |
| /** The logging level of this logger, or null if none is set. */ |
| volatile Level levelObjVal; |
| |
| /** |
| * The effective logging level of this logger. In order of preference this |
| * is the first applicable of: |
| * <ol> |
| * <li>the int value of this logger's {@link #levelObjVal} |
| * <li>the logging level of the parent |
| * <li>the default level ({@link Level#INFO}) |
| * </ol> |
| */ |
| volatile int levelIntVal = Level.INFO.intValue(); |
| |
| /** The filter. */ |
| private Filter filter; |
| |
| /** |
| * The resource bundle used to localize logging messages. If null, no |
| * localization will be performed. |
| */ |
| private volatile String resourceBundleName; |
| |
| /** The loaded resource bundle according to the specified name. */ |
| private volatile ResourceBundle resourceBundle; |
| |
| /** |
| * The handlers attached to this logger. Eagerly initialized and |
| * concurrently modified. |
| */ |
| private final List<Handler> handlers = new CopyOnWriteArrayList<Handler>(); |
| |
| /** True to notify the parent's handlers of each log message. */ |
| private boolean notifyParentHandlers = true; |
| |
| /** |
| * Indicates whether this logger is named. Only {@link #getAnonymousLogger |
| * anonymous loggers} are unnamed. |
| */ |
| private boolean isNamed = true; |
| |
| /** |
| * Child loggers. Should be accessed only while synchronized on {@code |
| * LogManager.getLogManager()}. |
| */ |
| final List<Logger> children = new ArrayList<Logger>(); |
| |
| /** the tag used for optimized logging. Derived from the logger name. */ |
| private final String androidTag; |
| |
| /** Handler delegate for either optimized or standard logging. */ |
| private volatile DalvikLogHandler dalvikLogHandler = GENERAL_LOG_HANDLER; |
| |
| /** |
| * We've optimized for the common case: logging to a single handler that |
| * implements {@link DalvikLogHandler}. This is how Android framework |
| * applications are configured by default. |
| * |
| * <p>This optimization has been measured to show a 2.75x improvement in |
| * throughput in the common case: 154ns vs. 56ns per message on a Cortex-A8. |
| * Direct use of {@code android.util.Log} takes 29ns per message. |
| * |
| * <p>Each time the handler configuration changes, either directly or |
| * indirectly, it's necessary to either turn on or off this optimization. |
| * When the optimization is off, {@link #dalvikLogHandler} is assigned to |
| * {@link #GENERAL_LOG_HANDLER} which can satisfy arbitrary configuration. |
| * When the optimization is possible, {@link #dalvikLogHandler} is assigned |
| * to the user's efficient implementation. In pratice this is usually the |
| * {@code com.android.internal.logging.AndroidHandler}. |
| */ |
| void updateDalvikLogHandler() { |
| DalvikLogHandler newLogHandler = GENERAL_LOG_HANDLER; |
| |
| Logger parent = this.parent; |
| |
| if (getClass() != Logger.class) { |
| /* |
| * Do nothing. Subclasses aren't eligible for the optimization |
| * because they may override methods like getHandlers() or |
| * log(LogRecord). |
| */ |
| |
| } else if (parent == null) { |
| // we use an iterator rather than size()+get() for safe concurrency |
| Iterator<Handler> h = handlers.iterator(); |
| if (h.hasNext()) { |
| Handler firstHandler = h.next(); |
| if (!h.hasNext() && firstHandler instanceof DalvikLogHandler) { |
| /* |
| * At this point, we're eligible for the optimization. We've |
| * satisfied these constraints: |
| * 1. This is not a subclass of logger |
| * 2. This is a root logger (no parent) |
| * 3. There is exactly one handler installed |
| * 4. That handler is a DalvikLogHandler |
| */ |
| newLogHandler = (DalvikLogHandler) firstHandler; |
| } |
| } |
| } else if (handlers.isEmpty() && notifyParentHandlers) { |
| /* |
| * At this point, we're eligible for the optimization if our parent |
| * logger is eligible. We've satisfied these constraints: |
| * 1. This is not a subclass of logger |
| * 2. our parent exists |
| * 3. we have no handlers of our own |
| * 4. we notify our parent's handlers |
| */ |
| newLogHandler = parent.dalvikLogHandler; |
| } |
| |
| if (newLogHandler == this.dalvikLogHandler) { |
| return; |
| } |
| |
| this.dalvikLogHandler = newLogHandler; |
| |
| for (Logger logger : children) { |
| logger.updateDalvikLogHandler(); |
| } |
| } |
| |
| /** |
| * Constructs a {@code Logger} object with the supplied name and resource |
| * bundle name; {@code notifiyParentHandlers} is set to {@code true}. |
| * <p> |
| * Notice : Loggers use a naming hierarchy. Thus "z.x.y" is a child of "z.x". |
| * |
| * @param name |
| * the name of this logger, may be {@code null} for anonymous |
| * loggers. |
| * @param resourceBundleName |
| * the name of the resource bundle used to localize logging |
| * messages, may be {@code null}. |
| * @throws MissingResourceException |
| * if the specified resource bundle can not be loaded. |
| */ |
| protected Logger(String name, String resourceBundleName) { |
| this.name = name; |
| initResourceBundle(resourceBundleName); |
| this.androidTag = DalvikLogging.loggerNameToTag(name); |
| updateDalvikLogHandler(); |
| } |
| |
| /** |
| * Load the specified resource bundle, use privileged code. |
| * |
| * @param resourceBundleName |
| * the name of the resource bundle to load, cannot be {@code null}. |
| * @return the loaded resource bundle. |
| * @throws MissingResourceException |
| * if the specified resource bundle can not be loaded. |
| */ |
| static ResourceBundle loadResourceBundle(String resourceBundleName) { |
| // try context class loader to load the resource |
| ClassLoader cl = Thread.currentThread().getContextClassLoader(); |
| if (cl != null) { |
| try { |
| return ResourceBundle.getBundle(resourceBundleName, Locale.getDefault(), cl); |
| } catch (MissingResourceException ignored) { |
| // Failed to load using context class loader, ignore |
| } |
| } |
| // try system class loader to load the resource |
| cl = ClassLoader.getSystemClassLoader(); |
| if (cl != null) { |
| try { |
| return ResourceBundle.getBundle(resourceBundleName, Locale.getDefault(), cl); |
| } catch (MissingResourceException ignored) { |
| // Failed to load using system class loader, ignore |
| } |
| } |
| throw new MissingResourceException("Failed to load the specified resource bundle \"" + |
| resourceBundleName + "\"", resourceBundleName, null); |
| } |
| |
| /** |
| * Gets an anonymous logger to use internally in a thread. Anonymous loggers |
| * are not registered in the log manager's namespace. No security checks |
| * will be performed when updating an anonymous logger's control settings. |
| * <p> |
| * The anonymous loggers' parent is set to be the root logger. This way it |
| * inherits the default logging level and handlers from the root logger. |
| * |
| * @return a new instance of anonymous logger. |
| */ |
| public static Logger getAnonymousLogger() { |
| return getAnonymousLogger(null); |
| } |
| |
| /** |
| * Gets an anonymous logger to use internally in a thread. Anonymous loggers |
| * are not registered in the log manager's namespace. No security checks |
| * will be performed when updating an anonymous logger's control settings. |
| * <p> |
| * The anonymous loggers' parent is set to be the root logger. This way it |
| * inherits default logging level and handlers from the root logger. |
| * |
| * @param resourceBundleName |
| * the name of the resource bundle used to localize log messages. |
| * @return a new instance of anonymous logger. |
| * @throws MissingResourceException |
| * if the specified resource bundle can not be loaded. |
| */ |
| public static Logger getAnonymousLogger(String resourceBundleName) { |
| Logger result = new Logger(null, resourceBundleName); |
| result.isNamed = false; |
| LogManager logManager = LogManager.getLogManager(); |
| logManager.setParent(result, logManager.getLogger("")); |
| return result; |
| } |
| |
| /** |
| * Initializes this logger's resource bundle. |
| * |
| * @throws IllegalArgumentException if this logger's resource bundle already |
| * exists and is different from the resource bundle specified. |
| */ |
| private synchronized void initResourceBundle(String resourceBundleName) { |
| String current = this.resourceBundleName; |
| |
| if (current != null) { |
| if (current.equals(resourceBundleName)) { |
| return; |
| } else { |
| throw new IllegalArgumentException("Resource bundle name '" + resourceBundleName + "' is inconsistent with the existing '" + current + "'"); |
| } |
| } |
| |
| if (resourceBundleName != null) { |
| this.resourceBundle = loadResourceBundle(resourceBundleName); |
| this.resourceBundleName = resourceBundleName; |
| } |
| } |
| |
| /** |
| * Gets a named logger. The returned logger may already exist or may be |
| * newly created. In the latter case, its level will be set to the |
| * configured level according to the {@code LogManager}'s properties. |
| * |
| * @param name |
| * the name of the logger to get, cannot be {@code null}. |
| * @return a named logger. |
| * @throws MissingResourceException |
| * If the specified resource bundle can not be loaded. |
| */ |
| public static Logger getLogger(String name) { |
| return LogManager.getLogManager().getOrCreate(name, null); |
| } |
| |
| /** |
| * Gets a named logger associated with the supplied resource bundle. The |
| * resource bundle will be used to localize logging messages. |
| * |
| * @param name |
| * the name of the logger to get, cannot be {@code null}. |
| * @param resourceBundleName |
| * the name of the resource bundle, may be {@code null}. |
| * @throws IllegalArgumentException |
| * if the logger identified by {@code name} is associated with a |
| * resource bundle and its name is not equal to |
| * {@code resourceBundleName}. |
| * @throws MissingResourceException |
| * if the name of the resource bundle cannot be found. |
| * @return a named logger. |
| */ |
| public static Logger getLogger(String name, String resourceBundleName) { |
| Logger result = LogManager.getLogManager() |
| .getOrCreate(name, resourceBundleName); |
| result.initResourceBundle(resourceBundleName); |
| return result; |
| } |
| |
| /** |
| * Returns the global {@code Logger}. |
| * @since 1.7 |
| * @hide 1.7 |
| */ |
| public static Logger getGlobal() { |
| return global; |
| } |
| |
| /** |
| * Adds a handler to this logger. The {@code name} will be fed with log |
| * records received by this logger. |
| * |
| * @param handler |
| * the handler object to add, cannot be {@code null}. |
| */ |
| public void addHandler(Handler handler) { |
| if (handler == null) { |
| throw new NullPointerException("handler == null"); |
| } |
| // Anonymous loggers can always add handlers |
| if (this.isNamed) { |
| LogManager.getLogManager().checkAccess(); |
| } |
| this.handlers.add(handler); |
| updateDalvikLogHandler(); |
| } |
| |
| /** |
| * Set the logger's manager and initializes its configuration from the |
| * manager's properties. |
| */ |
| void setManager(LogManager manager) { |
| String levelProperty = manager.getProperty(name + ".level"); |
| if (levelProperty != null) { |
| try { |
| manager.setLevelRecursively(Logger.this, Level.parse(levelProperty)); |
| } catch (IllegalArgumentException invalidLevel) { |
| invalidLevel.printStackTrace(); |
| } |
| } |
| |
| String handlersPropertyName = name.isEmpty() ? "handlers" : name + ".handlers"; |
| String handlersProperty = manager.getProperty(handlersPropertyName); |
| if (handlersProperty != null) { |
| for (String handlerName : handlersProperty.split(",|\\s")) { |
| if (handlerName.isEmpty()) { |
| continue; |
| } |
| |
| final Handler handler; |
| try { |
| handler = (Handler) LogManager.getInstanceByClass(handlerName); |
| } catch (Exception invalidHandlerName) { |
| invalidHandlerName.printStackTrace(); |
| continue; |
| } |
| |
| try { |
| String level = manager.getProperty(handlerName + ".level"); |
| if (level != null) { |
| handler.setLevel(Level.parse(level)); |
| } |
| } catch (Exception invalidLevel) { |
| invalidLevel.printStackTrace(); |
| } |
| |
| handlers.add(handler); |
| } |
| } |
| |
| updateDalvikLogHandler(); |
| } |
| |
| /** |
| * Gets all the handlers associated with this logger. |
| * |
| * @return an array of all the handlers associated with this logger. |
| */ |
| public Handler[] getHandlers() { |
| return handlers.toArray(EMPTY_HANDLERS_ARRAY); |
| } |
| |
| /** |
| * Removes a handler from this logger. If the specified handler does not |
| * exist then this method has no effect. |
| * |
| * @param handler |
| * the handler to be removed. |
| */ |
| public void removeHandler(Handler handler) { |
| // Anonymous loggers can always remove handlers |
| if (this.isNamed) { |
| LogManager.getLogManager().checkAccess(); |
| } |
| if (handler == null) { |
| return; |
| } |
| this.handlers.remove(handler); |
| updateDalvikLogHandler(); |
| } |
| |
| /** |
| * Gets the filter used by this logger. |
| * |
| * @return the filter used by this logger, may be {@code null}. |
| */ |
| public Filter getFilter() { |
| return this.filter; |
| } |
| |
| /** |
| * Sets the filter used by this logger. |
| * |
| * @param newFilter |
| * the filter to set, may be {@code null}. |
| */ |
| public void setFilter(Filter newFilter) { |
| // Anonymous loggers can always set the filter |
| if (this.isNamed) { |
| LogManager.getLogManager().checkAccess(); |
| } |
| filter = newFilter; |
| } |
| |
| /** |
| * Gets the logging level of this logger. A {@code null} level indicates |
| * that this logger inherits its parent's level. |
| * |
| * @return the logging level of this logger. |
| */ |
| public Level getLevel() { |
| return levelObjVal; |
| } |
| |
| /** |
| * Sets the logging level for this logger. A {@code null} level indicates |
| * that this logger will inherit its parent's level. |
| * |
| * @param newLevel |
| * the logging level to set. |
| */ |
| public void setLevel(Level newLevel) { |
| // Anonymous loggers can always set the level |
| LogManager logManager = LogManager.getLogManager(); |
| if (this.isNamed) { |
| logManager.checkAccess(); |
| } |
| logManager.setLevelRecursively(this, newLevel); |
| } |
| |
| /** |
| * Gets the flag which indicates whether to use the handlers of this |
| * logger's parent to publish incoming log records, potentially recursively |
| * up the namespace. |
| * |
| * @return {@code true} if set to use parent's handlers, {@code false} |
| * otherwise. |
| */ |
| public boolean getUseParentHandlers() { |
| return this.notifyParentHandlers; |
| } |
| |
| /** |
| * Sets the flag which indicates whether to use the handlers of this |
| * logger's parent, potentially recursively up the namespace. |
| * |
| * @param notifyParentHandlers |
| * the new flag indicating whether to use the parent's handlers. |
| */ |
| public void setUseParentHandlers(boolean notifyParentHandlers) { |
| // Anonymous loggers can always set the useParentHandlers flag |
| if (this.isNamed) { |
| LogManager.getLogManager().checkAccess(); |
| } |
| this.notifyParentHandlers = notifyParentHandlers; |
| updateDalvikLogHandler(); |
| } |
| |
| /** |
| * Gets the nearest parent of this logger in the namespace, a {@code null} |
| * value will be returned if called on the root logger. |
| * |
| * @return the parent of this logger in the namespace. |
| */ |
| public Logger getParent() { |
| return parent; |
| } |
| |
| /** |
| * Sets the parent of this logger in the namespace. This method should be |
| * used by the {@code LogManager} object only. |
| * |
| * @param parent |
| * the parent logger to set. |
| */ |
| public void setParent(Logger parent) { |
| if (parent == null) { |
| throw new NullPointerException("parent == null"); |
| } |
| |
| // even anonymous loggers are checked |
| LogManager logManager = LogManager.getLogManager(); |
| logManager.checkAccess(); |
| logManager.setParent(this, parent); |
| } |
| |
| /** |
| * Gets the name of this logger, {@code null} for anonymous loggers. |
| * |
| * @return the name of this logger. |
| */ |
| public String getName() { |
| return this.name; |
| } |
| |
| /** |
| * Gets the loaded resource bundle used by this logger to localize logging |
| * messages. If the value is {@code null}, the parent's resource bundle will be |
| * inherited. |
| * |
| * @return the loaded resource bundle used by this logger. |
| */ |
| public ResourceBundle getResourceBundle() { |
| return this.resourceBundle; |
| } |
| |
| /** |
| * Gets the name of the loaded resource bundle used by this logger to |
| * localize logging messages. If the value is {@code null}, the parent's resource |
| * bundle name will be inherited. |
| * |
| * @return the name of the loaded resource bundle used by this logger. |
| */ |
| public String getResourceBundleName() { |
| return this.resourceBundleName; |
| } |
| |
| /** |
| * This method is for compatibility. Tests written to the reference |
| * implementation API imply that the isLoggable() method is not called |
| * directly. This behavior is important because subclass may override |
| * isLoggable() method, so that affect the result of log methods. |
| */ |
| private boolean internalIsLoggable(Level l) { |
| int effectiveLevel = levelIntVal; |
| if (effectiveLevel == Level.OFF.intValue()) { |
| // always return false if the effective level is off |
| return false; |
| } |
| return l.intValue() >= effectiveLevel; |
| } |
| |
| /** |
| * Determines whether this logger will actually log messages of the |
| * specified level. The effective level used to do the determination may be |
| * inherited from its parent. The default level is {@code Level.INFO}. |
| * |
| * @param l |
| * the level to check. |
| * @return {@code true} if this logger will actually log this level, |
| * otherwise {@code false}. |
| */ |
| public boolean isLoggable(Level l) { |
| return internalIsLoggable(l); |
| } |
| |
| /** |
| * Sets the resource bundle and its name for a supplied LogRecord object. |
| * This method first tries to use this logger's resource bundle if any, |
| * otherwise try to inherit from this logger's parent, recursively up the |
| * namespace. |
| */ |
| private void setResourceBundle(LogRecord record) { |
| for (Logger p = this; p != null; p = p.parent) { |
| String resourceBundleName = p.resourceBundleName; |
| if (resourceBundleName != null) { |
| record.setResourceBundle(p.resourceBundle); |
| record.setResourceBundleName(resourceBundleName); |
| return; |
| } |
| } |
| } |
| |
| /** |
| * Logs a message indicating that a method has been entered. A log record |
| * with log level {@code Level.FINER}, log message "ENTRY", the specified |
| * source class name and source method name is submitted for logging. |
| * |
| * @param sourceClass |
| * the calling class name. |
| * @param sourceMethod |
| * the method name. |
| */ |
| public void entering(String sourceClass, String sourceMethod) { |
| if (!internalIsLoggable(Level.FINER)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(Level.FINER, "ENTRY"); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message indicating that a method has been entered. A log record |
| * with log level {@code Level.FINER}, log message "ENTRY", the specified |
| * source class name, source method name and one parameter is submitted for |
| * logging. |
| * |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param param |
| * the parameter for the method call. |
| */ |
| public void entering(String sourceClass, String sourceMethod, Object param) { |
| if (!internalIsLoggable(Level.FINER)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(Level.FINER, "ENTRY" + " {0}"); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setParameters(new Object[] { param }); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message indicating that a method has been entered. A log record |
| * with log level {@code Level.FINER}, log message "ENTRY", the specified |
| * source class name, source method name and array of parameters is |
| * submitted for logging. |
| * |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param params |
| * an array of parameters for the method call. |
| */ |
| public void entering(String sourceClass, String sourceMethod, |
| Object[] params) { |
| if (!internalIsLoggable(Level.FINER)) { |
| return; |
| } |
| |
| String msg = "ENTRY"; |
| if (params != null) { |
| StringBuilder msgBuffer = new StringBuilder("ENTRY"); |
| for (int i = 0; i < params.length; i++) { |
| msgBuffer.append(" {").append(i).append("}"); |
| } |
| msg = msgBuffer.toString(); |
| } |
| LogRecord record = new LogRecord(Level.FINER, msg); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setParameters(params); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message indicating that a method is exited. A log record with log |
| * level {@code Level.FINER}, log message "RETURN", the specified source |
| * class name and source method name is submitted for logging. |
| * |
| * @param sourceClass |
| * the calling class name. |
| * @param sourceMethod |
| * the method name. |
| */ |
| public void exiting(String sourceClass, String sourceMethod) { |
| if (!internalIsLoggable(Level.FINER)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(Level.FINER, "RETURN"); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message indicating that a method is exited. A log record with log |
| * level {@code Level.FINER}, log message "RETURN", the specified source |
| * class name, source method name and return value is submitted for logging. |
| * |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param result |
| * the return value of the method call. |
| */ |
| public void exiting(String sourceClass, String sourceMethod, Object result) { |
| if (!internalIsLoggable(Level.FINER)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(Level.FINER, "RETURN" + " {0}"); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setParameters(new Object[] { result }); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message indicating that an exception is thrown. A log record with |
| * log level {@code Level.FINER}, log message "THROW", the specified source |
| * class name, source method name and the {@code Throwable} object is |
| * submitted for logging. |
| * |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param thrown |
| * the {@code Throwable} object. |
| */ |
| public void throwing(String sourceClass, String sourceMethod, |
| Throwable thrown) { |
| if (!internalIsLoggable(Level.FINER)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(Level.FINER, "THROW"); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setThrown(thrown); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of level {@code Level.SEVERE}; the message is transmitted |
| * to all subscribed handlers. |
| * |
| * @param msg |
| * the message to log. |
| */ |
| public void severe(String msg) { |
| log(Level.SEVERE, msg); |
| } |
| |
| /** |
| * Logs a message of level {@code Level.WARNING}; the message is |
| * transmitted to all subscribed handlers. |
| * |
| * @param msg |
| * the message to log. |
| */ |
| public void warning(String msg) { |
| log(Level.WARNING, msg); |
| } |
| |
| /** |
| * Logs a message of level {@code Level.INFO}; the message is transmitted |
| * to all subscribed handlers. |
| * |
| * @param msg |
| * the message to log. |
| */ |
| public void info(String msg) { |
| log(Level.INFO, msg); |
| } |
| |
| /** |
| * Logs a message of level {@code Level.CONFIG}; the message is transmitted |
| * to all subscribed handlers. |
| * |
| * @param msg |
| * the message to log. |
| */ |
| public void config(String msg) { |
| log(Level.CONFIG, msg); |
| } |
| |
| /** |
| * Logs a message of level {@code Level.FINE}; the message is transmitted |
| * to all subscribed handlers. |
| * |
| * @param msg |
| * the message to log. |
| */ |
| public void fine(String msg) { |
| log(Level.FINE, msg); |
| } |
| |
| /** |
| * Logs a message of level {@code Level.FINER}; the message is transmitted |
| * to all subscribed handlers. |
| * |
| * @param msg |
| * the message to log. |
| */ |
| public void finer(String msg) { |
| log(Level.FINER, msg); |
| } |
| |
| /** |
| * Logs a message of level {@code Level.FINEST}; the message is transmitted |
| * to all subscribed handlers. |
| * |
| * @param msg |
| * the message to log. |
| */ |
| public void finest(String msg) { |
| log(Level.FINEST, msg); |
| } |
| |
| /** |
| * Logs a message of the specified level. The message is transmitted to all |
| * subscribed handlers. |
| * |
| * @param logLevel |
| * the level of the specified message. |
| * @param msg |
| * the message to log. |
| */ |
| public void log(Level logLevel, String msg) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| dalvikLogHandler.publish(this, androidTag, logLevel, msg); |
| } |
| |
| /** |
| * Logs a message of the specified level with the supplied parameter. The |
| * message is then transmitted to all subscribed handlers. |
| * |
| * @param logLevel |
| * the level of the given message. |
| * @param msg |
| * the message to log. |
| * @param param |
| * the parameter associated with the event that is logged. |
| */ |
| public void log(Level logLevel, String msg, Object param) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| record.setLoggerName(this.name); |
| record.setParameters(new Object[] { param }); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the specified level with the supplied parameter array. |
| * The message is then transmitted to all subscribed handlers. |
| * |
| * @param logLevel |
| * the level of the given message |
| * @param msg |
| * the message to log. |
| * @param params |
| * the parameter array associated with the event that is logged. |
| */ |
| public void log(Level logLevel, String msg, Object[] params) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| record.setLoggerName(this.name); |
| record.setParameters(params); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the specified level with the supplied {@code Throwable} |
| * object. The message is then transmitted to all subscribed handlers. |
| * |
| * @param logLevel |
| * the level of the given message. |
| * @param msg |
| * the message to log. |
| * @param thrown |
| * the {@code Throwable} object associated with the event that is |
| * logged. |
| */ |
| public void log(Level logLevel, String msg, Throwable thrown) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| record.setLoggerName(this.name); |
| record.setThrown(thrown); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a given log record. Only records with a logging level that is equal |
| * or greater than this logger's level will be submitted to this logger's |
| * handlers for logging. If {@code getUseParentHandlers()} returns {@code |
| * true}, the log record will also be submitted to the handlers of this |
| * logger's parent, potentially recursively up the namespace. |
| * <p> |
| * Since all other log methods call this method to actually perform the |
| * logging action, subclasses of this class can override this method to |
| * catch all logging activities. |
| * </p> |
| * |
| * @param record |
| * the log record to be logged. |
| */ |
| public void log(LogRecord record) { |
| if (!internalIsLoggable(record.getLevel())) { |
| return; |
| } |
| |
| // apply the filter if any |
| Filter f = filter; |
| if (f != null && !f.isLoggable(record)) { |
| return; |
| } |
| |
| /* |
| * call the handlers of this logger, throw any exception that occurs |
| */ |
| Handler[] allHandlers = getHandlers(); |
| for (Handler element : allHandlers) { |
| element.publish(record); |
| } |
| // call the parent's handlers if set useParentHandlers |
| Logger temp = this; |
| Logger theParent = temp.parent; |
| while (theParent != null && temp.getUseParentHandlers()) { |
| Handler[] ha = theParent.getHandlers(); |
| for (Handler element : ha) { |
| element.publish(record); |
| } |
| temp = theParent; |
| theParent = temp.parent; |
| } |
| } |
| |
| /** |
| * Logs a message of the given level with the specified source class name |
| * and source method name. |
| * |
| * @param logLevel |
| * the level of the given message. |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param msg |
| * the message to be logged. |
| */ |
| public void logp(Level logLevel, String sourceClass, String sourceMethod, |
| String msg) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the given level with the specified source class name, |
| * source method name and parameter. |
| * |
| * @param logLevel |
| * the level of the given message |
| * @param sourceClass |
| * the source class name |
| * @param sourceMethod |
| * the source method name |
| * @param msg |
| * the message to be logged |
| * @param param |
| * the parameter associated with the event that is logged. |
| */ |
| public void logp(Level logLevel, String sourceClass, String sourceMethod, |
| String msg, Object param) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setParameters(new Object[] { param }); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the given level with the specified source class name, |
| * source method name and parameter array. |
| * |
| * @param logLevel |
| * the level of the given message. |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param msg |
| * the message to be logged. |
| * @param params |
| * the parameter array associated with the event that is logged. |
| */ |
| public void logp(Level logLevel, String sourceClass, String sourceMethod, |
| String msg, Object[] params) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setParameters(params); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the given level with the specified source class name, |
| * source method name and {@code Throwable} object. |
| * |
| * @param logLevel |
| * the level of the given message. |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param msg |
| * the message to be logged. |
| * @param thrown |
| * the {@code Throwable} object. |
| */ |
| public void logp(Level logLevel, String sourceClass, String sourceMethod, |
| String msg, Throwable thrown) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setThrown(thrown); |
| setResourceBundle(record); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the given level with the specified source class name |
| * and source method name, using the given resource bundle to localize the |
| * message. If {@code bundleName} is null, the empty string or not valid then |
| * the message is not localized. |
| * |
| * @param logLevel |
| * the level of the given message. |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param bundleName |
| * the name of the resource bundle used to localize the message. |
| * @param msg |
| * the message to be logged. |
| */ |
| public void logrb(Level logLevel, String sourceClass, String sourceMethod, |
| String bundleName, String msg) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| if (bundleName != null) { |
| try { |
| record.setResourceBundle(loadResourceBundle(bundleName)); |
| } catch (MissingResourceException e) { |
| // ignore |
| } |
| record.setResourceBundleName(bundleName); |
| } |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the given level with the specified source class name, |
| * source method name and parameter, using the given resource bundle to |
| * localize the message. If {@code bundleName} is null, the empty string |
| * or not valid then the message is not localized. |
| * |
| * @param logLevel |
| * the level of the given message. |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param bundleName |
| * the name of the resource bundle used to localize the message. |
| * @param msg |
| * the message to be logged. |
| * @param param |
| * the parameter associated with the event that is logged. |
| */ |
| public void logrb(Level logLevel, String sourceClass, String sourceMethod, |
| String bundleName, String msg, Object param) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| if (bundleName != null) { |
| try { |
| record.setResourceBundle(loadResourceBundle(bundleName)); |
| } catch (MissingResourceException e) { |
| // ignore |
| } |
| record.setResourceBundleName(bundleName); |
| } |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setParameters(new Object[] { param }); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the given level with the specified source class name, |
| * source method name and parameter array, using the given resource bundle |
| * to localize the message. If {@code bundleName} is null, the empty string |
| * or not valid then the message is not localized. |
| * |
| * @param logLevel |
| * the level of the given message. |
| * @param sourceClass |
| * the source class name. |
| * @param sourceMethod |
| * the source method name. |
| * @param bundleName |
| * the name of the resource bundle used to localize the message. |
| * @param msg |
| * the message to be logged. |
| * @param params |
| * the parameter array associated with the event that is logged. |
| */ |
| public void logrb(Level logLevel, String sourceClass, String sourceMethod, |
| String bundleName, String msg, Object[] params) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| if (bundleName != null) { |
| try { |
| record.setResourceBundle(loadResourceBundle(bundleName)); |
| } catch (MissingResourceException e) { |
| // ignore |
| } |
| record.setResourceBundleName(bundleName); |
| } |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setParameters(params); |
| log(record); |
| } |
| |
| /** |
| * Logs a message of the given level with the specified source class name, |
| * source method name and {@code Throwable} object, using the given resource |
| * bundle to localize the message. If {@code bundleName} is null, the empty |
| * string or not valid then the message is not localized. |
| * |
| * @param logLevel |
| * the level of the given message |
| * @param sourceClass |
| * the source class name |
| * @param sourceMethod |
| * the source method name |
| * @param bundleName |
| * the name of the resource bundle used to localize the message. |
| * @param msg |
| * the message to be logged. |
| * @param thrown |
| * the {@code Throwable} object. |
| */ |
| public void logrb(Level logLevel, String sourceClass, String sourceMethod, |
| String bundleName, String msg, Throwable thrown) { |
| if (!internalIsLoggable(logLevel)) { |
| return; |
| } |
| |
| LogRecord record = new LogRecord(logLevel, msg); |
| if (bundleName != null) { |
| try { |
| record.setResourceBundle(loadResourceBundle(bundleName)); |
| } catch (MissingResourceException e) { |
| // ignore |
| } |
| record.setResourceBundleName(bundleName); |
| } |
| record.setLoggerName(this.name); |
| record.setSourceClassName(sourceClass); |
| record.setSourceMethodName(sourceMethod); |
| record.setThrown(thrown); |
| log(record); |
| } |
| |
| void reset() { |
| levelObjVal = null; |
| levelIntVal = Level.INFO.intValue(); |
| |
| for (Handler handler : handlers) { |
| try { |
| if (handlers.remove(handler)) { |
| handler.close(); |
| } |
| } catch (Exception ignored) { |
| } |
| } |
| |
| updateDalvikLogHandler(); |
| } |
| } |