org.apache.log4j.DTLoggerFactory.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.log4j.DTLoggerFactory.java

Source

/**
 * 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 org.apache.log4j;

import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentMap;
import java.util.regex.Pattern;

import javax.annotation.Nonnull;

import org.apache.log4j.spi.LoggerFactory;
import org.apache.log4j.spi.LoggerRepository;
import org.apache.log4j.spi.RepositorySelector;

import com.google.common.base.Function;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

/**
 * An implementation of {@link LoggerFactory}
 *
 * @since 1.0.2
 */
public class DTLoggerFactory implements LoggerFactory {
    public static final String DT_LOGGERS_LEVEL = "dt.loggers.level";

    private static DTLoggerFactory SINGLETON;

    public static synchronized DTLoggerFactory getInstance() {
        if (SINGLETON == null) {
            SINGLETON = new DTLoggerFactory();
        }
        return SINGLETON;
    }

    private final ConcurrentMap<String, Logger> loggerMap;
    private final Map<String, Level> patternLevel;

    public ImmutableMap<String, String> getPatternLevels() {
        return ImmutableMap.copyOf(Maps.transformValues(patternLevel, new Function<Level, String>() {
            @Override
            public String apply(Level input) {
                return input == null ? "" : input.toString();
            }
        }));
    }

    private final Map<String, Pattern> patterns;
    private boolean initialized = false;

    private DTLoggerFactory() {
        loggerMap = Maps.newConcurrentMap();
        patternLevel = Maps.newHashMap();
        patterns = Maps.newHashMap();
    }

    public synchronized void initialize() {
        if (!initialized) {
            LOG.debug("initializing DT Logger Factory");
            new RepositorySelectorImpl().initialize();
            String loggersLevel = System.getProperty(DT_LOGGERS_LEVEL);
            if (!Strings.isNullOrEmpty(loggersLevel)) {
                Map<String, String> targetChanges = Maps.newHashMap();
                String[] targets = loggersLevel.split(",");
                for (String target : targets) {
                    String[] parts = target.split(":");
                    targetChanges.put(parts[0], parts[1]);
                }
                changeLoggersLevel(targetChanges);
            }
            initialized = true;
        } else {
            LOG.warn("DT Logger Factory already initialized.");
        }
    }

    public synchronized void changeLoggersLevel(@Nonnull Map<String, String> targetChanges) {
        /*remove existing patterns which are subsets of new patterns. for eg. if x.y.z.* will be removed if
        there is x.y.* in the target changes.
        */
        for (Map.Entry<String, String> changeEntry : targetChanges.entrySet()) {
            Iterator<Map.Entry<String, Pattern>> patternsIterator = patterns.entrySet().iterator();
            while ((patternsIterator.hasNext())) {
                Map.Entry<String, Pattern> entry = patternsIterator.next();
                String finer = entry.getKey();
                String wider = changeEntry.getKey();
                if (finer.length() < wider.length()) {
                    continue;
                }
                boolean remove = false;
                for (int i = 0; i < wider.length(); i++) {
                    if (wider.charAt(i) == '*') {
                        remove = true;
                        break;
                    }
                    if (wider.charAt(i) != finer.charAt(i)) {
                        break;
                    } else if (i == wider.length() - 1) {
                        remove = true;
                    }
                }
                if (remove) {
                    patternsIterator.remove();
                    patternLevel.remove(finer);
                }
            }
        }
        for (Map.Entry<String, String> loggerEntry : targetChanges.entrySet()) {
            String target = loggerEntry.getKey();
            patternLevel.put(target, Level.toLevel(loggerEntry.getValue()));
            patterns.put(target, Pattern.compile(target));
        }

        if (!patternLevel.isEmpty()) {
            @SuppressWarnings("unchecked")
            Enumeration<Logger> loggerEnumeration = LogManager.getCurrentLoggers();
            while (loggerEnumeration.hasMoreElements()) {
                Logger classLogger = loggerEnumeration.nextElement();
                Level oldLevel = classLogger.getLevel();
                Level newLevel = getLevelFor(classLogger.getName());
                if (newLevel != null && (oldLevel == null || !newLevel.equals(oldLevel))) {
                    LOG.info("changing level of " + classLogger.getName() + " to " + newLevel);
                    classLogger.setLevel(newLevel);
                }
            }
        }
    }

    @Override
    public Logger makeNewLoggerInstance(String name) {
        Logger newInstance = new Logger(name);
        Level level = getLevelFor(name);
        if (level != null) {
            newInstance.setLevel(level);
        }
        loggerMap.put(name, newInstance);
        return newInstance;
    }

    private synchronized Level getLevelFor(String name) {
        if (patternLevel.isEmpty()) {
            return null;
        }
        String longestPatternKey = null;
        for (String partternKey : patternLevel.keySet()) {
            Pattern pattern = patterns.get(partternKey);
            if (pattern.matcher(name).matches()
                    && (longestPatternKey == null || longestPatternKey.length() < partternKey.length())) {
                longestPatternKey = partternKey;
            }
        }
        if (longestPatternKey != null) {
            return patternLevel.get(longestPatternKey);
        }
        return null;
    }

    public synchronized ImmutableMap<String, String> getClassesMatching(@Nonnull String searchKey) {
        Pattern searchPattern = Pattern.compile(searchKey);
        Map<String, String> matchedClasses = Maps.newHashMap();
        @SuppressWarnings("unchecked")
        Enumeration<Logger> loggerEnumeration = LogManager.getCurrentLoggers();
        while (loggerEnumeration.hasMoreElements()) {
            Logger logger = loggerEnumeration.nextElement();
            if (searchPattern.matcher(logger.getName()).matches()) {
                Level level = logger.getLevel();
                matchedClasses.put(logger.getName(), level == null ? "" : level.toString());
            }
        }
        return ImmutableMap.copyOf(matchedClasses);
    }

    private static class RepositorySelectorImpl implements RepositorySelector {

        private boolean initialized;
        private Logger guard;
        private Hierarchy hierarchy;

        private RepositorySelectorImpl() {
            initialized = false;
        }

        private void initialize() {
            if (!initialized) {
                LOG.debug("initializing logger repository selector impl");
                guard = LogManager.getRootLogger();
                LogManager.setRepositorySelector(this, guard);
                hierarchy = new LoggerRepositoryImpl(guard);
                initialized = true;
            }
        }

        @Override
        public LoggerRepository getLoggerRepository() {
            return hierarchy;
        }
    }

    private static class LoggerRepositoryImpl extends Hierarchy {
        /**
         * Create a new logger hierarchy.
         *
         * @param root The root of the new hierarchy.
         */
        private LoggerRepositoryImpl(Logger root) {
            super(root);
        }

        @Override
        public Logger getLogger(String name) {
            return super.getLogger(name, DTLoggerFactory.getInstance());
        }
    }

    private static final Logger LOG = LogManager.getLogger(DTLoggerFactory.class);
}