001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
004 *
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 *
009 *   or (per the licensee's choosing)
010 *
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.joran;
015
016import ch.qos.logback.classic.joran.action.ConfigurationAction;
017import ch.qos.logback.classic.joran.action.ConsolePluginAction;
018import ch.qos.logback.classic.joran.action.ContextNameAction;
019import ch.qos.logback.classic.joran.action.InsertFromJNDIAction;
020import ch.qos.logback.classic.joran.action.LevelAction;
021import ch.qos.logback.classic.joran.action.LoggerAction;
022import ch.qos.logback.classic.joran.action.LoggerContextListenerAction;
023import ch.qos.logback.classic.joran.action.ReceiverAction;
024import ch.qos.logback.classic.joran.action.RootLoggerAction;
025import ch.qos.logback.classic.joran.sanity.IfNestedWithinSecondPhaseElementSC;
026import ch.qos.logback.classic.model.processor.ConfigurationModelHandlerFull;
027import ch.qos.logback.classic.model.processor.LogbackClassicDefaultNestedComponentRules;
028import ch.qos.logback.classic.spi.ILoggingEvent;
029import ch.qos.logback.core.joran.GenericXMLConfigurator;
030import ch.qos.logback.core.joran.JoranConfiguratorBase;
031import ch.qos.logback.core.joran.action.AppenderRefAction;
032import ch.qos.logback.core.joran.action.IncludeAction;
033import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry;
034import ch.qos.logback.core.joran.spi.ElementSelector;
035import ch.qos.logback.core.joran.spi.RuleStore;
036import ch.qos.logback.core.model.Model;
037import ch.qos.logback.core.model.processor.DefaultProcessor;
038import ch.qos.logback.core.model.processor.ModelInterpretationContext;
039
040/**
041 * JoranConfigurator class adds rules specific to logback-classic.
042 *
043 * @author Ceki Gülcü
044 */
045public class JoranConfigurator extends JoranConfiguratorBase<ILoggingEvent> {
046
047
048
049    @Override
050    public void addElementSelectorAndActionAssociations(RuleStore rs) {
051        // add parent rules
052        super.addElementSelectorAndActionAssociations(rs);
053
054        rs.addRule(new ElementSelector("configuration"), () -> new ConfigurationAction());
055
056        rs.addRule(new ElementSelector("configuration/contextName"), () -> new ContextNameAction());
057        rs.addRule(new ElementSelector("configuration/contextListener"), () -> new LoggerContextListenerAction());
058        rs.addRule(new ElementSelector("configuration/insertFromJNDI"), () -> new InsertFromJNDIAction());
059
060        rs.addRule(new ElementSelector("configuration/logger"), () -> new LoggerAction());
061        rs.addRule(new ElementSelector("configuration/logger/level"), () -> new LevelAction());
062
063        rs.addRule(new ElementSelector("configuration/root"), () -> new RootLoggerAction());
064        rs.addRule(new ElementSelector("configuration/root/level"), () -> new LevelAction());
065        rs.addRule(new ElementSelector("configuration/logger/appender-ref"), () -> new AppenderRefAction());
066        rs.addRule(new ElementSelector("configuration/root/appender-ref"), () -> new AppenderRefAction());
067
068        rs.addRule(new ElementSelector("configuration/include"), () -> new IncludeAction());
069
070        rs.addRule(new ElementSelector("configuration/consolePlugin"), () -> new ConsolePluginAction());
071
072        rs.addRule(new ElementSelector("configuration/receiver"), () -> new ReceiverAction());
073
074    }
075
076
077    @Override
078    protected void sanityCheck(Model topModel) {
079        super.sanityCheck(topModel);
080        performCheck(new IfNestedWithinSecondPhaseElementSC(), topModel);
081    }
082
083    @Override
084    protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) {
085        LogbackClassicDefaultNestedComponentRules.addDefaultNestedComponentRegistryRules(registry);
086    }
087
088    private JoranConfigurator makeAnotherInstance() {
089        JoranConfigurator jc = new JoranConfigurator();
090        jc.setContext(context);
091        return jc;
092    }
093
094    public void buildModelInterpretationContext() {
095        super.buildModelInterpretationContext();
096        this.modelInterpretationContext.setConfiguratorSupplier(  () -> this.makeAnotherInstance() );
097    }
098
099    @Override
100    protected void addModelHandlerAssociations(DefaultProcessor defaultProcessor) {
101        ModelClassToModelHandlerLinker m = new ModelClassToModelHandlerLinker(context);
102        m.setConfigurationModelHandlerFactoryMethod(ConfigurationModelHandlerFull::makeInstance2);
103        m.link(defaultProcessor);
104    }
105
106
107    // The final filters in the two filter chain are rather crucial.
108    // They ensure that only Models attached to the firstPhaseFilter will
109    // be handled in the first phase and all models not previously handled
110    // in the second phase will be handled in a catch-all fallback case.
111    private void sealModelFilters(DefaultProcessor defaultProcessor) {
112        defaultProcessor.getPhaseOneFilter().denyAll();
113        defaultProcessor.getPhaseTwoFilter().allowAll();
114    }
115
116}