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.core.joran;
15  
16  import ch.qos.logback.core.joran.action.*;
17  import ch.qos.logback.core.joran.conditional.*;
18  import ch.qos.logback.core.joran.sanity.AppenderWithinAppenderSanityChecker;
19  import ch.qos.logback.core.joran.sanity.SanityChecker;
20  import ch.qos.logback.core.joran.spi.ElementSelector;
21  import ch.qos.logback.core.joran.spi.RuleStore;
22  import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
23  import ch.qos.logback.core.joran.spi.SaxEventInterpreter;
24  import ch.qos.logback.core.model.*;
25  import ch.qos.logback.core.model.processor.*;
26  import ch.qos.logback.core.spi.ContextAware;
27  
28  // Based on 310985 revision 310985 as attested by http://tinyurl.com/8njps
29  // see also http://tinyurl.com/c2rp5
30  
31  /**
32   * A JoranConfiguratorBase lays most of the groundwork for concrete
33   * configurators derived from it. Concrete configurators only need to implement
34   * the {@link #addElementSelectorAndActionAssociations} method.
35   * <p>
36   * A JoranConfiguratorBase instance should not be used more than once to
37   * configure a Context.
38   *
39   * @author Ceki G&uuml;lc&uuml;
40   */
41  abstract public class JoranConfiguratorBase<E> extends GenericXMLConfigurator {
42  
43      @Override
44      protected void addElementSelectorAndActionAssociations(RuleStore rs) {
45  
46          // is "*/variable" referenced in the docs?
47          rs.addRule(new ElementSelector("*/variable"), PropertyAction::new);
48          rs.addRule(new ElementSelector("*/property"),  PropertyAction::new);
49          // substitutionProperty is deprecated
50          rs.addRule(new ElementSelector("*/substitutionProperty"),  PropertyAction::new);
51  
52          rs.addRule(new ElementSelector("configuration/import"), ImportAction::new);
53          
54  
55          rs.addRule(new ElementSelector("configuration/timestamp"),  TimestampAction::new);
56          rs.addRule(new ElementSelector("configuration/shutdownHook"),  ShutdownHookAction::new);
57          rs.addRule(new ElementSelector("configuration/sequenceNumberGenerator"),  SequenceNumberGeneratorAction::new);
58          rs.addRule(new ElementSelector("configuration/serializeModel"),  SerializeModelAction::new);
59  
60          rs.addRule(new ElementSelector("configuration/define"),  DefinePropertyAction::new);
61          rs.addRule(new ElementSelector("configuration/evaluator"),  EventEvaluatorAction::new);
62  
63          // the contextProperty pattern is deprecated. It is undocumented
64          // and will be dropped in future versions of logback
65          rs.addRule(new ElementSelector("configuration/contextProperty"),  ContextPropertyAction::new);
66  
67          rs.addRule(new ElementSelector("configuration/conversionRule"),  ConversionRuleAction::new);
68  
69          rs.addRule(new ElementSelector("configuration/statusListener"),  StatusListenerAction::new);
70  
71          rs.addRule(new ElementSelector("*/appender"),  AppenderAction::new);
72          rs.addRule(new ElementSelector("configuration/appender/appender-ref"),  AppenderRefAction::new);
73          rs.addRule(new ElementSelector("configuration/newRule"),  NewRuleAction::new);
74  
75          rs.addRule(new ElementSelector("*/param"),  ParamAction::new);
76  
77          // add if-then-else support
78          rs.addRule(new ElementSelector("*/condition"), ByPropertiesConditionAction::new);
79          rs.addRule(new ElementSelector("*/if"),  IfAction::new);
80          rs.addTransparentPathPart("if");
81          rs.addRule(new ElementSelector("*/if/then"),  ThenAction::new);
82          rs.addTransparentPathPart("then");
83          rs.addRule(new ElementSelector("*/if/else"),  ElseAction::new);
84          rs.addTransparentPathPart("else");
85          
86          rs.addRule(new ElementSelector("*/appender/sift"),  SiftAction::new);
87          rs.addTransparentPathPart("sift");
88          
89          
90      }
91  
92      /**
93       * Perform sanity check and issue warning if necessary.
94       *
95       * @param topModel
96       */
97      protected void sanityCheck(Model topModel) {
98          performCheck(new AppenderWithinAppenderSanityChecker(), topModel);
99      }
100 
101     protected void performCheck(SanityChecker sc, Model model) {
102         if(sc instanceof ContextAware)
103             ((ContextAware) sc).setContext(context);
104         sc.check(model);
105     }
106 
107     @Override
108     protected void setImplicitRuleSupplier(SaxEventInterpreter interpreter) {
109         interpreter.setImplicitActionSupplier(  ImplicitModelAction::new );
110     }
111 
112     @Override
113     public void buildModelInterpretationContext() {
114         super.buildModelInterpretationContext();
115         modelInterpretationContext.createAppenderBags();
116     }
117 
118     public SaxEventInterpretationContext getInterpretationContext() {
119         return saxEventInterpreter.getSaxEventInterpretationContext();
120     }
121 
122     @Override
123     protected void addModelHandlerAssociations(DefaultProcessor defaultProcessor) {
124         // Please note that code previously here moved to ModelClassToModelHandlerLinkerBase
125     }
126 
127 }