001/**
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2015, 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.classic.joran;
015
016import ch.qos.logback.classic.joran.action.ConfigurationAction;
017import ch.qos.logback.classic.joran.action.ConsolePluginAction;
018import ch.qos.logback.classic.joran.action.ContextNameAction;
019import ch.qos.logback.classic.joran.action.InsertFromJNDIAction;
020import ch.qos.logback.classic.joran.action.JMXConfiguratorAction;
021import ch.qos.logback.classic.joran.action.LevelAction;
022import ch.qos.logback.classic.joran.action.LoggerAction;
023import ch.qos.logback.classic.joran.action.LoggerContextListenerAction;
024import ch.qos.logback.classic.joran.action.ReceiverAction;
025import ch.qos.logback.classic.joran.action.RootLoggerAction;
026import ch.qos.logback.classic.model.ConfigurationModel;
027import ch.qos.logback.classic.model.ContextNameModel;
028import ch.qos.logback.classic.model.LevelModel;
029import ch.qos.logback.classic.model.LoggerContextListenerModel;
030import ch.qos.logback.classic.model.LoggerModel;
031import ch.qos.logback.classic.model.RootLoggerModel;
032import ch.qos.logback.classic.model.processor.ConfigurationModelHandler;
033import ch.qos.logback.classic.model.processor.ContextNameModelHandler;
034import ch.qos.logback.classic.model.processor.LevelModelHandler;
035import ch.qos.logback.classic.model.processor.LoggerContextListenerModelHandler;
036import ch.qos.logback.classic.model.processor.LoggerModelHandler;
037import ch.qos.logback.classic.model.processor.RootLoggerModelHandler;
038import ch.qos.logback.classic.spi.ILoggingEvent;
039import ch.qos.logback.classic.spi.PlatformInfo;
040import ch.qos.logback.classic.util.DefaultNestedComponentRules;
041import ch.qos.logback.core.Context;
042import ch.qos.logback.core.joran.JoranConfiguratorBase;
043import ch.qos.logback.core.joran.action.AppenderRefAction;
044import ch.qos.logback.core.joran.action.IncludeAction;
045import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry;
046import ch.qos.logback.core.joran.spi.ElementSelector;
047import ch.qos.logback.core.joran.spi.RuleStore;
048import ch.qos.logback.core.model.AppenderModel;
049import ch.qos.logback.core.model.AppenderRefModel;
050import ch.qos.logback.core.model.DefineModel;
051import ch.qos.logback.core.model.EventEvaluatorModel;
052import ch.qos.logback.core.model.ImplicitModel;
053import ch.qos.logback.core.model.ImportModel;
054import ch.qos.logback.core.model.IncludeModel;
055import ch.qos.logback.core.model.Model;
056import ch.qos.logback.core.model.ParamModel;
057import ch.qos.logback.core.model.PropertyModel;
058import ch.qos.logback.core.model.ShutdownHookModel;
059import ch.qos.logback.core.model.TimestampModel;
060import ch.qos.logback.core.model.conditional.ElseModel;
061import ch.qos.logback.core.model.conditional.IfModel;
062import ch.qos.logback.core.model.conditional.ThenModel;
063import ch.qos.logback.core.model.processor.AppenderModelHandler;
064import ch.qos.logback.core.model.processor.AppenderRefDependencyAnalyser;
065import ch.qos.logback.core.model.processor.AppenderRefModelHandler;
066import ch.qos.logback.core.model.processor.ChainedModelFilter;
067import ch.qos.logback.core.model.processor.DefaultProcessor;
068import ch.qos.logback.core.model.processor.ModelInterpretationContext;
069import ch.qos.logback.core.model.processor.RefContainerDependencyAnalyser;
070
071/**
072 * JoranConfigurator class adds rules specific to logback-classic.
073 *
074 * @author Ceki Gülcü
075 */
076public class JoranConfigurator extends JoranConfiguratorBase<ILoggingEvent> {
077
078    @Override
079    public void addInstanceRules(RuleStore rs) {
080        // add parent rules
081        super.addInstanceRules(rs);
082
083        rs.addRule(new ElementSelector("configuration"), () -> new ConfigurationAction());
084
085        rs.addRule(new ElementSelector("configuration/contextName"), () -> new ContextNameAction());
086        rs.addRule(new ElementSelector("configuration/contextListener"), () -> new LoggerContextListenerAction());
087        rs.addRule(new ElementSelector("configuration/insertFromJNDI"), () -> new InsertFromJNDIAction());
088
089        rs.addRule(new ElementSelector("configuration/logger"), () -> new LoggerAction());
090        rs.addRule(new ElementSelector("configuration/logger/level"), () -> new LevelAction());
091
092        rs.addRule(new ElementSelector("configuration/root"), () -> new RootLoggerAction());
093        rs.addRule(new ElementSelector("configuration/root/level"), () -> new LevelAction());
094        rs.addRule(new ElementSelector("configuration/logger/appender-ref"), () -> new AppenderRefAction());
095        rs.addRule(new ElementSelector("configuration/root/appender-ref"), () -> new AppenderRefAction());
096        
097        if (PlatformInfo.hasJMXObjectName()) {
098            rs.addRule(new ElementSelector("configuration/jmxConfigurator"), () -> new JMXConfiguratorAction());
099        }
100        rs.addRule(new ElementSelector("configuration/include"), () -> new IncludeAction());
101
102        rs.addRule(new ElementSelector("configuration/consolePlugin"), () -> new ConsolePluginAction());
103
104        rs.addRule(new ElementSelector("configuration/receiver"), () -> new ReceiverAction());
105
106    }
107
108    @Override
109    protected void addDefaultNestedComponentRegistryRules(DefaultNestedComponentRegistry registry) {
110        DefaultNestedComponentRules.addDefaultNestedComponentRegistryRules(registry);
111    }
112
113    @Override
114    protected DefaultProcessor buildDefaultProcessor(Context context, ModelInterpretationContext mic) {
115        DefaultProcessor defaultProcessor = super.buildDefaultProcessor(context, mic);
116        defaultProcessor.addHandler(ConfigurationModel.class, ConfigurationModelHandler::makeInstance);
117        defaultProcessor.addHandler(ContextNameModel.class, ContextNameModelHandler::makeInstance);
118        defaultProcessor.addHandler(LoggerContextListenerModel.class, LoggerContextListenerModelHandler::makeInstance);
119
120        defaultProcessor.addHandler(AppenderModel.class, AppenderModelHandler::makeInstance);
121        defaultProcessor.addHandler(AppenderRefModel.class, AppenderRefModelHandler::makeInstance);
122        defaultProcessor.addHandler(RootLoggerModel.class, RootLoggerModelHandler::makeInstance);
123        defaultProcessor.addHandler(LoggerModel.class, LoggerModelHandler::makeInstance);
124        defaultProcessor.addHandler(LevelModel.class, LevelModelHandler::makeInstance);
125
126        defaultProcessor.addAnalyser(LoggerModel.class, new RefContainerDependencyAnalyser(context, LoggerModel.class));
127
128        defaultProcessor.addAnalyser(RootLoggerModel.class,
129                new RefContainerDependencyAnalyser(context, RootLoggerModel.class));
130
131        defaultProcessor.addAnalyser(AppenderModel.class,
132                new RefContainerDependencyAnalyser(context, AppenderModel.class));
133
134        defaultProcessor.addAnalyser(AppenderRefModel.class, new AppenderRefDependencyAnalyser(context));
135
136        injectModelFilters(defaultProcessor);
137
138        return defaultProcessor;
139    }
140
141    private void injectModelFilters(DefaultProcessor defaultProcessor) {
142        @SuppressWarnings("unchecked")
143        Class<? extends Model>[] importModelClasses = new Class[] { ImportModel.class };
144
145        @SuppressWarnings("unchecked")
146        Class<? extends Model>[] variableDefinitionModelClasses = new Class[] { ContextNameModel.class,
147                DefineModel.class, PropertyModel.class, TimestampModel.class, ParamModel.class };
148
149        @SuppressWarnings("unchecked")
150        Class<? extends Model>[] implicitModelClasses = new Class[] { ImplicitModel.class };
151
152        @SuppressWarnings("unchecked")
153        Class<? extends Model>[] otherFirstPhaseModelClasses = new Class[] { ConfigurationModel.class,
154                EventEvaluatorModel.class, LoggerContextListenerModel.class, ShutdownHookModel.class,
155                IncludeModel.class, IfModel.class, ThenModel.class, ElseModel.class};
156
157        // MOTE: AppenderModelHandler is delayed to second phase
158
159        ChainedModelFilter fistPhaseDefintionFilter = new ChainedModelFilter();
160        for (Class<? extends Model> modelClass : importModelClasses)
161            fistPhaseDefintionFilter.allow(modelClass);
162        for (Class<? extends Model> modelClass : variableDefinitionModelClasses)
163            fistPhaseDefintionFilter.allow(modelClass);
164        for (Class<? extends Model> modelClass : otherFirstPhaseModelClasses)
165            fistPhaseDefintionFilter.allow(modelClass);
166        for (Class<? extends Model> modelClass : implicitModelClasses)
167            fistPhaseDefintionFilter.allow(modelClass);
168
169        fistPhaseDefintionFilter.denyAll();
170        defaultProcessor.setPhaseOneFilter(fistPhaseDefintionFilter);
171
172        ChainedModelFilter secondPhaseDefinitionFilter = new ChainedModelFilter();
173        secondPhaseDefinitionFilter.allowAll();
174
175        defaultProcessor.setPhaseTwoFilter(secondPhaseDefinitionFilter);
176
177    }
178
179}