This code has been running for some time in a modified package and works nicely:

    private static int getSeparatorIndexOf(String name, int fromIndex) {
        int i = name.indexOf(CoreConstants.DOT, fromIndex);
        int j = name.indexOf(CoreConstants.DOLLAR, fromIndex);
        if (i < 0) {
            return j;
        } else if (j < 0) {
            return i;
        } else {
            return (i < j) ? i : j;
        }
    }

    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 = 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
        return 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 Logger 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()) {
            return createLoggerPathRecursively(originalName, childName, ix + 1, childLogger);
        }
        else {
            return childLogger;
        }
    }
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