FileDocCategorySizeDatePackage
ClassLoaderLogManager.javaAPI DocApache Tomcat 6.0.1420035Fri Jul 20 04:20:36 BST 2007org.apache.juli

ClassLoaderLogManager

public class ClassLoaderLogManager extends LogManager
Per classloader LogManager implementation.

Fields Summary
protected final Map
classLoaderLoggers
Map containing the classloader information, keyed per classloader. A weak hashmap is used to ensure no classloader reference is leaked from application redeployment.
protected ThreadLocal
prefix
This prefix is used to allow using prefixes for the properties names of handlers and their subcomponents.
Constructors Summary
Methods Summary
public synchronized booleanaddLogger(java.util.logging.Logger logger)
Add the specified logger to the classloader local configuration.

param
logger The logger to be added


    
    // --------------------------------------------------------- Public Methods


                          
          

        final String loggerName = logger.getName();

        ClassLoader classLoader = 
            Thread.currentThread().getContextClassLoader();
        ClassLoaderLogInfo info = getClassLoaderInfo(classLoader);
        if (info.loggers.containsKey(loggerName)) {
            return false;
        }
        info.loggers.put(loggerName, logger);

        // Apply initial level for new logger
        final String levelString = getProperty(loggerName + ".level");
        if (levelString != null) {
            try {
                AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        logger.setLevel(Level.parse(levelString.trim()));
                        return null;
                    }
                });
            } catch (IllegalArgumentException e) {
                // Leave level set to null
            }
        }

        // If any parent loggers have levels definied, make sure they are
        // instantiated
        int dotIndex = loggerName.lastIndexOf('.");
        while (dotIndex >= 0) {
            final String parentName = loggerName.substring(0, dotIndex);
            if (getProperty(parentName + ".level") != null) {
                Logger.getLogger(parentName);
                break;
            }
            dotIndex = loggerName.lastIndexOf('.", dotIndex - 1);
        }

        // Find associated node
        LogNode node = info.rootNode.findNode(loggerName);
        node.logger = logger;

        // Set parent logger
        Logger parentLogger = node.findParentLogger();
        if (parentLogger != null) {
            doSetParentLogger(logger, parentLogger);
        }

        // Tell children we are their new parent
        node.setParentLogger(logger);

        // Add associated handlers, if any are defined using the .handlers property.
        // In this case, handlers of the parent logger(s) will not be used
        String handlers = getProperty(loggerName + ".handlers");
        if (handlers != null) {
            logger.setUseParentHandlers(false);
            StringTokenizer tok = new StringTokenizer(handlers, ",");
            while (tok.hasMoreTokens()) {
                String handlerName = (tok.nextToken().trim());
                Handler handler = null;
                ClassLoader current = classLoader;
                while (current != null) {
                    info = (ClassLoaderLogInfo) classLoaderLoggers.get(current);
                    if (info != null) {
                        handler = (Handler) info.handlers.get(handlerName);
                        if (handler != null) {
                            break;
                        }
                    }
                    current = current.getParent();
                }
                if (handler != null) {
                    logger.addHandler(handler);
                }
            }
        }

        // Parse useParentHandlers to set if the logger should delegate to its parent.
        // Unlike java.util.logging, the default is to not delegate if a list of handlers
        // has been specified for the logger.
        String useParentHandlersString = getProperty(loggerName + ".useParentHandlers");
        if (Boolean.valueOf(useParentHandlersString).booleanValue()) {
            logger.setUseParentHandlers(true);
        }
        
        return true;
    
protected static voiddoSetParentLogger(java.util.logging.Logger logger, java.util.logging.Logger parent)
Set parent child relationship between the two specified loggers.

param
logger
param
parent

        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                logger.setParent(parent);
                return null;
            }
        });
    
protected org.apache.juli.ClassLoaderLogManager$ClassLoaderLogInfogetClassLoaderInfo(java.lang.ClassLoader classLoader)
Retrieve the configuration associated with the specified classloader. If it does not exist, it will be created.

param
classLoader The classloader for which we will retrieve or build the configuration

        
        if (classLoader == null) {
            classLoader = ClassLoader.getSystemClassLoader();
        }
        ClassLoaderLogInfo info = (ClassLoaderLogInfo) classLoaderLoggers
                .get(classLoader);
        if (info == null) {
            final ClassLoader classLoaderParam = classLoader;
            AccessController.doPrivileged(new PrivilegedAction() {
                public Object run() {
                    try {
                        readConfiguration(classLoaderParam);
                    } catch (IOException e) {
                        // Ignore
                    }
                    return null;
                }
            });
            info = (ClassLoaderLogInfo) classLoaderLoggers.get(classLoader);
        }
        return info;
    
public synchronized java.util.logging.LoggergetLogger(java.lang.String name)
Get the logger associated with the specified name inside the classloader local configuration. If this returns null, and the call originated for Logger.getLogger, a new logger with the specified name will be instantiated and added using addLogger.

param
name The name of the logger to retrieve

        ClassLoader classLoader = Thread.currentThread()
                .getContextClassLoader();
        return (Logger) getClassLoaderInfo(classLoader).loggers.get(name);
    
public synchronized java.util.EnumerationgetLoggerNames()
Get an enumeration of the logger names currently defined in the classloader local configuration.

        ClassLoader classLoader = Thread.currentThread()
                .getContextClassLoader();
        return Collections.enumeration(getClassLoaderInfo(classLoader).loggers.keySet());
    
public java.lang.StringgetProperty(java.lang.String name)
Get the value of the specified property in the classloader local configuration.

param
name The property name

        ClassLoader classLoader = Thread.currentThread()
            .getContextClassLoader();
        String prefix = (String) this.prefix.get();
        if (prefix != null) {
            name = prefix + name;
        }
        ClassLoaderLogInfo info = getClassLoaderInfo(classLoader);
        String result = info.props.getProperty(name);
        // If the property was not found, and the current classloader had no 
        // configuration (property list is empty), look for the parent classloader
        // properties.
        if ((result == null) && (info.props.isEmpty())) {
            ClassLoader current = classLoader.getParent();
            while (current != null) {
                info = (ClassLoaderLogInfo) classLoaderLoggers.get(current);
                if (info != null) {
                    result = info.props.getProperty(name);
                    if ((result != null) || (!info.props.isEmpty())) {
                        break;
                    }
                }
                current = current.getParent();
            }
            if (result == null) {
                result = super.getProperty(name);
            }
        }
        // Simple property replacement (mostly for folder names)
        if (result != null) {
            result = replace(result);
        }
        return result;
    
public voidreadConfiguration()

        
        checkAccess();
        
        readConfiguration(Thread.currentThread().getContextClassLoader());
        
    
public voidreadConfiguration(java.io.InputStream is)

        
        checkAccess();
        reset();

        readConfiguration(is, Thread.currentThread().getContextClassLoader());
    
    
protected voidreadConfiguration(java.lang.ClassLoader classLoader)
Read configuration for the specified classloader.

param
classLoader
throws
IOException Errot

        
        InputStream is = null;
        // Special case for URL classloaders which are used in containers: 
        // only look in the local repositories to avoid redefining loggers 20 times
        if ((classLoader instanceof URLClassLoader) 
                && (((URLClassLoader) classLoader).findResource("logging.properties") != null)) {
            is = classLoader.getResourceAsStream("logging.properties");
        }
        if ((is == null) && (classLoader == ClassLoader.getSystemClassLoader())) {
            String configFileStr = System.getProperty("java.util.logging.config.file");
            if (configFileStr != null) {
                try {
                    is = new FileInputStream(replace(configFileStr));
                } catch (IOException e) {
                    // Ignore
                }
            }
            // Try the default JVM configuration
            if (is == null) {
                File defaultFile = new File(new File(System.getProperty("java.home"), "lib"), 
                    "logging.properties");
                try {
                    is = new FileInputStream(defaultFile);
                } catch (IOException e) {
                    // Critical problem, do something ...
                }
            }
        }
        
        Logger localRootLogger = new RootLogger();
        if (is == null) {
            // Retrieve the root logger of the parent classloader instead
            ClassLoader current = classLoader.getParent();
            ClassLoaderLogInfo info = null;
            while (current != null && info == null) {
                info = getClassLoaderInfo(current);
                current = current.getParent();
            }
            if (info != null) {
                localRootLogger.setParent(info.rootNode.logger);
            }
        }
        ClassLoaderLogInfo info = 
            new ClassLoaderLogInfo(new LogNode(null, localRootLogger));
        classLoaderLoggers.put(classLoader, info);
        
        if (is != null) {
            readConfiguration(is, classLoader);
        }
        addLogger(localRootLogger);
        
    
protected voidreadConfiguration(java.io.InputStream is, java.lang.ClassLoader classLoader)
Load specified configuration.

param
is InputStream to the properties file
param
classLoader for which the configuration will be loaded
throws
IOException If something wrong happens during loading

        
        ClassLoaderLogInfo info = 
            (ClassLoaderLogInfo) classLoaderLoggers.get(classLoader);
        
        try {
            info.props.load(is);
        } catch (IOException e) {
            // Report error
            System.err.println("Configuration error");
            e.printStackTrace();
        } finally {
            try {
                is.close();
            } catch (Throwable t) {}
        }
        
        // Create handlers for the root logger of this classloader
        String rootHandlers = info.props.getProperty(".handlers");
        String handlers = info.props.getProperty("handlers");
        Logger localRootLogger = info.rootNode.logger;
        if (handlers != null) {
            StringTokenizer tok = new StringTokenizer(handlers, ",");
            while (tok.hasMoreTokens()) {
                String handlerName = (tok.nextToken().trim());
                String handlerClassName = handlerName;
                String prefix = "";
                if (handlerClassName.length() <= 0) {
                    continue;
                }
                // Parse and remove a prefix (prefix start with a digit, such as 
                // "10WebappFooHanlder.")
                if (Character.isDigit(handlerClassName.charAt(0))) {
                    int pos = handlerClassName.indexOf('.");
                    if (pos >= 0) {
                        prefix = handlerClassName.substring(0, pos + 1);
                        handlerClassName = handlerClassName.substring(pos + 1);
                    }
                }
                try {
                    this.prefix.set(prefix);
                    Handler handler = 
                        (Handler) classLoader.loadClass(handlerClassName).newInstance();
                    // The specification strongly implies all configuration should be done 
                    // during the creation of the handler object.
                    // This includes setting level, filter, formatter and encoding.
                    this.prefix.set(null);
                    info.handlers.put(handlerName, handler);
                    if (rootHandlers == null) {
                        localRootLogger.addHandler(handler);
                    }
                } catch (Exception e) {
                    // Report error
                    System.err.println("Handler error");
                    e.printStackTrace();
                }
            }
            
        }
        
    
protected java.lang.Stringreplace(java.lang.String str)
System property replacement in the given string.

param
str The original string
return
the modified string

        String result = str;
        if (result.startsWith("${")) {
            int pos = result.indexOf('}");
            if (pos != -1) {
                String propName = result.substring(2, pos);
                String replacement = System.getProperty(propName);
                if (replacement != null) {
                    result = replacement + result.substring(pos + 1);
                }
            }
        }
        return result;