1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v2.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.classic.joran;
15  
16  import ch.qos.logback.classic.joran.action.*;
17  import ch.qos.logback.classic.joran.sanity.IfNestedWithinSecondPhaseElementSC;
18  import ch.qos.logback.classic.model.processor.ConfigurationModelHandlerFull;
19  import ch.qos.logback.classic.model.processor.LogbackClassicDefaultNestedComponentRules;
20  import ch.qos.logback.classic.spi.ILoggingEvent;
21  import ch.qos.logback.core.joran.JoranConfiguratorBase;
22  import ch.qos.logback.core.joran.action.AppenderRefAction;
23  import ch.qos.logback.core.joran.action.IncludeAction;
24  import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry;
25  import ch.qos.logback.core.joran.spi.ElementSelector;
26  import ch.qos.logback.core.joran.spi.RuleStore;
27  import ch.qos.logback.core.model.Model;
28  import ch.qos.logback.core.model.processor.DefaultProcessor;
29  
30  /**
31   * JoranConfigurator class adds rules specific to logback-classic.
32   *
33   * @author Ceki Gülcü
34   */
35  public class JoranConfigurator extends JoranConfiguratorBase<ILoggingEvent> {
36  
37  
38  
39      @Override
40      public void addElementSelectorAndActionAssociations(RuleStore rs) {
41          // add parent rules
42          super.addElementSelectorAndActionAssociations(rs);
43  
44          rs.addRule(new ElementSelector("configuration"), () -> new ConfigurationAction());
45  
46          rs.addRule(new ElementSelector("configuration/contextName"), () -> new ContextNameAction());
47          rs.addRule(new ElementSelector("configuration/contextListener"), () -> new LoggerContextListenerAction());
48          rs.addRule(new ElementSelector("configuration/insertFromJNDI"), () -> new InsertFromJNDIAction());
49  
50          rs.addRule(new ElementSelector("configuration/logger"), () -> new LoggerAction());
51          rs.addRule(new ElementSelector("configuration/logger/level"), () -> new LevelAction());
52  
53          rs.addRule(new ElementSelector("configuration/root"), () -> new RootLoggerAction());
54          rs.addRule(new ElementSelector("configuration/root/level"), () -> new LevelAction());
55          rs.addRule(new ElementSelector("configuration/logger/appender-ref"), () -> new AppenderRefAction());
56          rs.addRule(new ElementSelector("configuration/root/appender-ref"), () -> new AppenderRefAction());
57  
58          rs.addRule(new ElementSelector("configuration/include"), () -> new IncludeAction());
59          rs.addRule(new ElementSelector("configuration/propertiesConfigurator"), () -> new PropertiesConfiguratorAction());
60  
61          rs.addRule(new ElementSelector("configuration/consolePlugin"), () -> new ConsolePluginAction());
62  
63      }
64  
65  
66      @Override
67      protected void sanityCheck(Model topModel) {
68          super.sanityCheck(topModel);
69          performCheck(new IfNestedWithinSecondPhaseElementSC(), topModel);
70      }
71  
72      @Override
73      protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) {
74          LogbackClassicDefaultNestedComponentRules.addDefaultNestedComponentRegistryRules(registry);
75      }
76  
77      private JoranConfigurator makeAnotherInstance() {
78          JoranConfigurator jc = new JoranConfigurator();
79          jc.setContext(context);
80          return jc;
81      }
82  
83      public void buildModelInterpretationContext() {
84          super.buildModelInterpretationContext();
85          this.modelInterpretationContext.setConfiguratorSupplier(  () -> this.makeAnotherInstance() );
86      }
87  
88      @Override
89      protected void addModelHandlerAssociations(DefaultProcessor defaultProcessor) {
90          ModelClassToModelHandlerLinker m = new ModelClassToModelHandlerLinker(context);
91          m.setConfigurationModelHandlerFactoryMethod(ConfigurationModelHandlerFull::makeInstance);
92          m.link(defaultProcessor);
93      }
94  
95  
96      // The final filters in the two filter chain are rather crucial.
97      // They ensure that only Models attached to the firstPhaseFilter will
98      // be handled in the first phase and all models not previously handled
99      // 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 }