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ülcü 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}