001/*
002 * Logback: the reliable, generic, fast and flexible logging framework.
003 * Copyright (C) 1999-2024, 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 */
014
015package ch.qos.logback.classic.tyler;
016
017import ch.qos.logback.classic.Level;
018import ch.qos.logback.classic.Logger;
019import ch.qos.logback.classic.LoggerContext;
020import ch.qos.logback.classic.joran.JoranConfigurator;
021import ch.qos.logback.classic.model.ConfigurationModel;
022import ch.qos.logback.classic.util.LevelUtil;
023import ch.qos.logback.core.Context;
024import ch.qos.logback.core.joran.GenericXMLConfigurator;
025import ch.qos.logback.core.model.Model;
026import ch.qos.logback.core.model.util.PropertyModelHandlerHelper;
027import ch.qos.logback.core.model.util.VariableSubstitutionsHelper;
028import ch.qos.logback.core.spi.ContextAwareBase;
029import ch.qos.logback.core.spi.ContextAwarePropertyContainer;
030import ch.qos.logback.core.status.OnConsoleStatusListener;
031import ch.qos.logback.core.util.OptionHelper;
032import ch.qos.logback.core.util.StatusListenerConfigHelper;
033import ch.qos.logback.core.util.StringUtil;
034
035import java.util.Map;
036import java.util.function.Supplier;
037
038public class TylerConfiguratorBase extends ContextAwareBase implements ContextAwarePropertyContainer {
039
040    public static final String SET_CONTEXT_METHOD_NAME = "setContext";
041    public static final String SET_CONTEXT_NAME_METHOD_NAME = "setContextName";
042    public static final String SETUP_LOGGER_METHOD_NAME = "setupLogger";
043    public static final String VARIABLE_SUBSTITUTIONS_HELPER_FIELD_NAME = "variableSubstitutionsHelper";
044    public static final String PROPERTY_MODEL_HANDLER_HELPER_FIELD_NAME = "propertyModelHandlerHelper";
045
046    // initialized via #setContext
047    protected VariableSubstitutionsHelper variableSubstitutionsHelper;
048    // context set in #setContext
049    protected PropertyModelHandlerHelper propertyModelHandlerHelper = new PropertyModelHandlerHelper(this);
050
051    protected Logger setupLogger(String loggerName, String levelString, Boolean additivity) {
052        LoggerContext loggerContext = (LoggerContext) context;
053        Logger logger = loggerContext.getLogger(loggerName);
054        if (!OptionHelper.isNullOrEmptyOrAllSpaces(levelString)) {
055            Level level = LevelUtil.levelStringToLevel(levelString);
056            logger.setLevel(level);
057        }
058        if (additivity != null) {
059            logger.setAdditive(additivity);
060        }
061        return logger;
062    }
063
064    @Override
065    public void setContext(Context context) {
066        super.setContext(context);
067        variableSubstitutionsHelper = new VariableSubstitutionsHelper(context);
068        propertyModelHandlerHelper.setContext(context);
069    }
070
071    protected void setContextName(String name) {
072        if (StringUtil.isNullOrEmpty(name)) {
073            addError("Cannot set context name to null or empty string");
074            return;
075        }
076        try {
077            String substName = subst(name);
078            addInfo("Setting context name to [" + substName + "]");
079            context.setName(substName);
080        } catch (IllegalStateException e) {
081            addError("Failed to rename context as [" + name + "]");
082        }
083    }
084
085    protected void addOnConsoleStatusListener() {
086        StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener());
087    }
088
089    /**
090     * Performs variable substitution.
091     *
092     * @param ref
093     * @return
094     */
095    @Override
096    public String subst(String ref) {
097        return variableSubstitutionsHelper.subst(ref);
098    }
099
100    @Override
101    public void addSubstitutionProperty(String key, String value) {
102        variableSubstitutionsHelper.addSubstitutionProperty(key, value);
103    }
104
105    /**
106     * If a key is found in propertiesMap then return it.
107     */
108    @Override
109    public String getProperty(String key) {
110        return variableSubstitutionsHelper.getProperty(key);
111    }
112
113    @Override
114    public Map<String, String> getCopyOfPropertyMap() {
115        return variableSubstitutionsHelper.getCopyOfPropertyMap();
116    }
117
118    public boolean isNull(String k) {
119        String val = OptionHelper.propertyLookup(k, this, context);
120        return (val == null);
121    }
122
123    /**
124     * Method used in conditional evaluation
125     *
126     * @param k  a property name
127     * @return true if the property is defined
128     * @since 1.5.4
129     */
130    public boolean isDefined(String k) {
131        String val = OptionHelper.propertyLookup(k, this, context);
132        return (val != null);
133    }
134
135    /**
136     * Shorthand for {@link #property(String)}.
137     *
138     * @param k a property name
139     * @return value of property k
140     * @since 1.5.4
141     */
142    public String p(String k) {
143        return property(k);
144    }
145
146    /**
147     * Return the value of the property named k. If the value is null, then the
148     * empty string is returned to avoid null checks.
149     *
150     * @param k property name
151     * @return the value of the property named k
152     * @since 1.5.4
153     */
154    public String property(String k) {
155        String val = OptionHelper.propertyLookup(k, this, context);
156        if (val != null)
157            return val;
158        else
159            return "";
160    }
161
162    private JoranConfigurator makeAnotherInstance() {
163        JoranConfigurator jc = new JoranConfigurator();
164        jc.setContext(context);
165        return jc;
166    }
167
168    /**
169     * Return a supplier which supplies an instance of {@link JoranConfigurator} set to
170     * the same context the context of 'this'.
171     * @since 1.5.11
172     */
173    @Override
174    public Supplier<? extends GenericXMLConfigurator> getConfiguratorSupplier() {
175        Supplier<? extends GenericXMLConfigurator> supplier = () -> this.makeAnotherInstance();
176        return supplier;
177    }
178
179    protected void processModelFromIncludedFile(Model modelFromIncludedFile) {
180        Supplier<? extends GenericXMLConfigurator > configuratorSupplier = this.getConfiguratorSupplier();
181        GenericXMLConfigurator genericXMLConfigurator = configuratorSupplier.get();
182        ConfigurationModel configururationModel = new ConfigurationModel();
183        configururationModel.addSubModel(modelFromIncludedFile);
184        genericXMLConfigurator.processModel(configururationModel);
185    }
186}