001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2022, 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.core.joran;
015
016import ch.qos.logback.core.joran.action.*;
017import ch.qos.logback.core.joran.conditional.ElseAction;
018import ch.qos.logback.core.joran.conditional.IfAction;
019import ch.qos.logback.core.joran.conditional.ThenAction;
020import ch.qos.logback.core.joran.sanity.AppenderWithinAppenderSanityChecker;
021import ch.qos.logback.core.joran.sanity.SanityChecker;
022import ch.qos.logback.core.joran.spi.ElementSelector;
023import ch.qos.logback.core.joran.spi.RuleStore;
024import ch.qos.logback.core.joran.spi.SaxEventInterpretationContext;
025import ch.qos.logback.core.joran.spi.SaxEventInterpreter;
026import ch.qos.logback.core.model.*;
027import ch.qos.logback.core.model.processor.*;
028import ch.qos.logback.core.spi.ContextAware;
029
030// Based on 310985 revision 310985 as attested by http://tinyurl.com/8njps
031// see also http://tinyurl.com/c2rp5
032
033/**
034 * A JoranConfiguratorBase lays most of the groundwork for concrete
035 * configurators derived from it. Concrete configurators only need to implement
036 * the {@link #addElementSelectorAndActionAssociations} method.
037 * <p>
038 * A JoranConfiguratorBase instance should not be used more than once to
039 * configure a Context.
040 *
041 * @author Ceki G&uuml;lc&uuml;
042 */
043abstract public class JoranConfiguratorBase<E> extends GenericXMLConfigurator {
044
045    @Override
046    protected void addElementSelectorAndActionAssociations(RuleStore rs) {
047
048        // is "*/variable" referenced in the docs?
049        rs.addRule(new ElementSelector("*/variable"), PropertyAction::new);
050        rs.addRule(new ElementSelector("*/property"),  PropertyAction::new);
051        // substitutionProperty is deprecated
052        rs.addRule(new ElementSelector("*/substitutionProperty"),  PropertyAction::new);
053
054        rs.addRule(new ElementSelector("configuration/import"), ImportAction::new);
055        
056
057        rs.addRule(new ElementSelector("configuration/timestamp"),  TimestampAction::new);
058        rs.addRule(new ElementSelector("configuration/shutdownHook"),  ShutdownHookAction::new);
059        rs.addRule(new ElementSelector("configuration/sequenceNumberGenerator"),  SequenceNumberGeneratorAction::new);
060        rs.addRule(new ElementSelector("configuration/serializeModel"),  SerializeModelAction::new);
061
062        rs.addRule(new ElementSelector("configuration/define"),  DefinePropertyAction::new);
063        rs.addRule(new ElementSelector("configuration/evaluator"),  EventEvaluatorAction::new);
064
065        // the contextProperty pattern is deprecated. It is undocumented
066        // and will be dropped in future versions of logback
067        rs.addRule(new ElementSelector("configuration/contextProperty"),  ContextPropertyAction::new);
068
069        rs.addRule(new ElementSelector("configuration/conversionRule"),  ConversionRuleAction::new);
070
071        rs.addRule(new ElementSelector("configuration/statusListener"),  StatusListenerAction::new);
072
073        rs.addRule(new ElementSelector("*/appender"),  AppenderAction::new);
074        rs.addRule(new ElementSelector("configuration/appender/appender-ref"),  AppenderRefAction::new);
075        rs.addRule(new ElementSelector("configuration/newRule"),  NewRuleAction::new);
076
077        rs.addRule(new ElementSelector("*/param"),  ParamAction::new);
078
079        // add if-then-else support
080        rs.addRule(new ElementSelector("*/if"),  IfAction::new);
081        rs.addTransparentPathPart("if");
082        rs.addRule(new ElementSelector("*/if/then"),  ThenAction::new);
083        rs.addTransparentPathPart("then");
084        rs.addRule(new ElementSelector("*/if/else"),  ElseAction::new);
085        rs.addTransparentPathPart("else");
086        
087        rs.addRule(new ElementSelector("*/appender/sift"),  SiftAction::new);
088        rs.addTransparentPathPart("sift");
089        
090        
091    }
092
093    /**
094     * Perform sanity check and issue warning if necessary.
095     *
096     * @param topModel
097     */
098    protected void sanityCheck(Model topModel) {
099        performCheck(new AppenderWithinAppenderSanityChecker(), topModel);
100    }
101
102    protected void performCheck(SanityChecker sc, Model model) {
103        if(sc instanceof ContextAware)
104            ((ContextAware) sc).setContext(context);
105        sc.check(model);
106    }
107
108    @Override
109    protected void setImplicitRuleSupplier(SaxEventInterpreter interpreter) {
110        interpreter.setImplicitActionSupplier(  ImplicitModelAction::new );
111    }
112
113    @Override
114    public void buildModelInterpretationContext() {
115        super.buildModelInterpretationContext();
116        modelInterpretationContext.createAppenderBags();
117    }
118
119    public SaxEventInterpretationContext getInterpretationContext() {
120        return saxEventInterpreter.getSaxEventInterpretationContext();
121    }
122
123    @Override
124    protected void addModelHandlerAssociations(DefaultProcessor defaultProcessor) {
125        // Please note that code previously here moved to ModelClassToModelHandlerLinkerBase
126    }
127
128}