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