001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 * <p>
005 * This program and the accompanying materials are dual-licensed under
006 * either the terms of the Eclipse Public License v1.0 as published by
007 * the Eclipse Foundation
008 * <p>
009 * or (per the licensee's choosing)
010 * <p>
011 * under the terms of the GNU Lesser General Public License version 2.1
012 * as published by the Free Software Foundation.
013 */
014package ch.qos.logback.classic.util;
015
016import java.net.URL;
017import java.util.Comparator;
018import java.util.List;
019
020import ch.qos.logback.classic.BasicConfigurator;
021import ch.qos.logback.classic.ClassicConstants;
022import ch.qos.logback.classic.LoggerContext;
023import ch.qos.logback.classic.joran.JoranConfigurator;
024import ch.qos.logback.classic.spi.Configurator;
025import ch.qos.logback.core.CoreConstants;
026import ch.qos.logback.core.LogbackException;
027import ch.qos.logback.core.joran.spi.JoranException;
028import ch.qos.logback.core.status.InfoStatus;
029import ch.qos.logback.core.util.EnvUtil;
030import ch.qos.logback.core.util.StatusListenerConfigHelper;
031
032// contributors
033// Ted Graham, Matt Fowles, see also http://jira.qos.ch/browse/LBCORE-32
034
035/**
036 * This class contains logback's logic for automatic configuration
037 *
038 * @author Ceki Gulcu
039 */
040public class ContextInitializer {
041
042    final public static String AUTOCONFIG_FILE = DefaultJoranConfigurator.AUTOCONFIG_FILE;
043    final public static String TEST_AUTOCONFIG_FILE = DefaultJoranConfigurator.TEST_AUTOCONFIG_FILE;
044    /**
045     * @deprecated Please use ClassicConstants.CONFIG_FILE_PROPERTY instead
046     */
047    final public static String CONFIG_FILE_PROPERTY = ClassicConstants.CONFIG_FILE_PROPERTY;
048
049    final LoggerContext loggerContext;
050
051    public ContextInitializer(LoggerContext loggerContext) {
052        this.loggerContext = loggerContext;
053    }
054
055    public void configureByResource(URL url) throws JoranException {
056        if (url == null) {
057            throw new IllegalArgumentException("URL argument cannot be null");
058        }
059        final String urlString = url.toString();
060        if (urlString.endsWith("xml")) {
061            JoranConfigurator configurator = new JoranConfigurator();
062            configurator.setContext(loggerContext);
063            configurator.doConfigure(url);
064        } else {
065            throw new LogbackException(
066                    "Unexpected filename extension of file [" + url + "]. Should be .xml");
067        }
068    }
069
070    void joranConfigureByResource(URL url) throws JoranException {
071        JoranConfigurator configurator = new JoranConfigurator();
072        configurator.setContext(loggerContext);
073        configurator.doConfigure(url);
074    }
075
076    public void autoConfig() throws JoranException {
077        autoConfig(Configurator.class.getClassLoader());
078    }
079
080    public void autoConfig(ClassLoader classLoader) throws JoranException {
081        String versionStr = EnvUtil.logbackVersion();
082        loggerContext.getStatusManager().add(new InfoStatus(CoreConstants.LOGBACK_CLASSIC_VERSION_MESSAGE + versionStr, loggerContext));
083        StatusListenerConfigHelper.installIfAsked(loggerContext);
084        List<Configurator> configuratorList = ClassicEnvUtil.loadFromServiceLoader(Configurator.class, classLoader);
085        sortByPriority(configuratorList);
086
087        for (Configurator c : configuratorList) {
088            try {
089                c.setContext(loggerContext);
090                Configurator.ExecutionStatus status = c.configure(loggerContext);
091                if (status == Configurator.ExecutionStatus.DO_NOT_INVOKE_NEXT_IF_ANY) {
092                    return;
093                }
094            } catch (Exception e) {
095                throw new LogbackException(
096                        String.format("Failed to initialize Configurator: %s using ServiceLoader",
097                                c != null ? c.getClass().getCanonicalName() : "null"),
098                        e);
099            }
100
101        }
102
103        // at this stage invoke basicConfigurator
104        BasicConfigurator basicConfigurator = new BasicConfigurator();
105        basicConfigurator.setContext(loggerContext);
106        basicConfigurator.configure(loggerContext);
107
108    }
109
110    private void sortByPriority(List<Configurator> configuratorList) {
111        configuratorList.sort(new Comparator<Configurator>() {
112            @Override
113            public int compare(Configurator o1, Configurator o2) {
114                if (o1.getClass() == o2.getClass())
115                    return 0;
116                if (o1 instanceof DefaultJoranConfigurator) {
117                    return 1;
118                }
119
120                // otherwise do not intervene
121                return 0;
122            }
123        });
124    }
125
126
127}