Issue Type: Improvement Improvement
Affects Versions: 1.0.9
Assignee: Logback dev list
Created: 20/Dec/12 7:39 PM
Description: ch.qos.logback.classic.LoggerContext.getLogger() is hard to understand; it can be shortend with a little recursion. Just a suggestion. I will have to run this modified code to see whether it works, I haven't done so yet.

Additionally, a few edge cases should be checked, right?

== Original ==

-------------------
    public final Logger getLogger(final String name) {

        if (name == null) {
            throw new IllegalArgumentException("name argument cannot be null");
        }

        // if we are asking for the root logger, then let us return it without
        // wasting time
        if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
            return root;
        }

        int i = 0;
        Logger logger = root;

        // check if the desired logger exists, if it does, return it
        // without further ado.
        Logger childLogger = (Logger) loggerCache.get(name);
        // if we have the child, then let us return it without wasting time
        if (childLogger != null) {
            return childLogger;
        }

        // if the desired logger does not exist, them create all the loggers
        // in between as well (if they don't already exist)
        String childName;
        while (true) {
            int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
            if (h == -1) {
                childName = name;
            } else {
                childName = name.substring(0, h);
            }
            // move i left of the last point
            i = h + 1;
            synchronized (logger) {
                childLogger = logger.getChildByName(childName);
                if (childLogger == null) {
                    childLogger = logger.createChildByName(childName);
                    loggerCache.put(childName, childLogger);
                    incSize();
                }
            }
            logger = childLogger;
            if (h == -1) {
                return childLogger;
            }
        }
    }
-------------------

== With recursion ==


    public final Logger getLogger(final String name) {
        if (name == null) {
            throw new IllegalArgumentException("name argument cannot be null");
            // can it be empty though??
        }
        // if we are asking for the root logger, then let us return it without wasting time
        // note that this is not the empty name but "ROOT"
        if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
            return root;
        }
        // check if the desired logger exists, if it does, return it without further ado.
        {
            Logger childLogger = (Logger) loggerCache.get(name);
            if (loggerCache.get(name) != null) {
                return childLogger;
            }
        }
        // if the desired logger does not exist, then create all the loggers in between as well (if they don't exist yet)
        // this means
        // 1) splitting the "name" along the DOT/DOLLAR separators (but refusing the empty string result)
        // 2) creating all the loggers along that path if they don't exist yet
        createLoggerPathRecursively(name, "", 0, root);
    }

    /**
     * Recursively build logger path
     * On the first call, "originalName" is the full logger name, "currentName" is the empty string,
     * currentPos (the position beyond which to search for logger name components) is 0 and
     * "parentLogger" is the "root"
     */

    private void createLoggerPathRecursively(String originalName, String currentName, int currentPos, Logger parentLogger) {
        assert originalName != null;
        assert currentName != null;
        assert currentPos >= 0;
        assert parentLogger != null;
        if (currentPos >= originalName.length()) {
            throw new IllegalArgumentException("The logger name '" + originalName + "' is either empty or ends with a separator");
        }
        // find the next separator in "originalName" starting from "currentPos"
        int ix = getSeparatorIndexOf(originalName, currentPos);
        if (ix < 0) {
            // No more separators, so we are done but still need to register this last logger.
            // So let ix point past the end!
            ix = originalName.length();
        }
        String nameComponent = originalName.substring(currentPos, ix);
        // Depending on specification use one of the two below:
        String childName = currentName + CoreConstants.DOT + nameComponent; // DOTify any DOLLAR
        // String childName = originalName.substring(0, ix); // unmodified part of original
        // Accept empty components? Nope!
        if (nameComponent.isEmpty()) {
            throw new IllegalArgumentException("The logger name '" + originalName + "' has an empty component starting at position " + currentPos);
        }
        // See whether the child logger exists, if not, create it
        Logger childLogger;
        synchronized (parentLogger) {
            childLogger = parentLogger.getChildByName(childName); // does not check the childName; returns null if not found
            if (childLogger == null) {
                // Depending on taste use this (which dotifies any dollars)
                // childLogger = parentLogger.createChildByLastNamePart(nameComponent); // checks that name component has no DOT or DOLLAR
                // or this (which keeps the DOT or DOLLAR as is); this is in the original (this means that the root must have the empty name)
                childLogger = parentLogger.createChildByName(childName); // checks that name component beyond parent's name has no DOT or DOLLAR
                loggerCache.put(childName, childLogger);
                incSize();
            }
            assert childLogger != null;
        }
        // (tail)-recursive call if not done
        if (ix < originalName.length()) {
            createLoggerPathRecursively(originalName, childName, ix + 1, childLogger);
        }
    }
Project: logback
Priority: Minor Minor
Reporter: David Tonhofer
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators.
For more information on JIRA, see: http://www.atlassian.com/software/jira