1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2024, 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 v1.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  
15  package ch.qos.logback.classic.tyler;
16  
17  import ch.qos.logback.classic.Level;
18  import ch.qos.logback.classic.Logger;
19  import ch.qos.logback.classic.LoggerContext;
20  import ch.qos.logback.classic.joran.JoranConfigurator;
21  import ch.qos.logback.classic.model.ConfigurationModel;
22  import ch.qos.logback.classic.util.LevelUtil;
23  import ch.qos.logback.core.Context;
24  import ch.qos.logback.core.joran.GenericXMLConfigurator;
25  import ch.qos.logback.core.model.Model;
26  import ch.qos.logback.core.model.util.PropertyModelHandlerHelper;
27  import ch.qos.logback.core.model.util.VariableSubstitutionsHelper;
28  import ch.qos.logback.core.spi.ContextAwareBase;
29  import ch.qos.logback.core.spi.ContextAwarePropertyContainer;
30  import ch.qos.logback.core.status.OnConsoleStatusListener;
31  import ch.qos.logback.core.util.OptionHelper;
32  import ch.qos.logback.core.util.StatusListenerConfigHelper;
33  import ch.qos.logback.core.util.StringUtil;
34  
35  import java.util.Map;
36  import java.util.function.Supplier;
37  
38  public class TylerConfiguratorBase extends ContextAwareBase implements ContextAwarePropertyContainer {
39  
40      public static final String SET_CONTEXT_METHOD_NAME = "setContext";
41      public static final String SET_CONTEXT_NAME_METHOD_NAME = "setContextName";
42      public static final String SETUP_LOGGER_METHOD_NAME = "setupLogger";
43      public static final String VARIABLE_SUBSTITUTIONS_HELPER_FIELD_NAME = "variableSubstitutionsHelper";
44      public static final String PROPERTY_MODEL_HANDLER_HELPER_FIELD_NAME = "propertyModelHandlerHelper";
45  
46      // initialized via #setContext
47      protected VariableSubstitutionsHelper variableSubstitutionsHelper;
48      // context set in #setContext
49      protected PropertyModelHandlerHelper propertyModelHandlerHelper = new PropertyModelHandlerHelper(this);
50  
51      protected Logger setupLogger(String loggerName, String levelString, Boolean additivity) {
52          LoggerContext loggerContext = (LoggerContext) context;
53          Logger logger = loggerContext.getLogger(loggerName);
54          if (!OptionHelper.isNullOrEmptyOrAllSpaces(levelString)) {
55              Level level = LevelUtil.levelStringToLevel(levelString);
56              logger.setLevel(level);
57          }
58          if (additivity != null) {
59              logger.setAdditive(additivity);
60          }
61          return logger;
62      }
63  
64      @Override
65      public void setContext(Context context) {
66          super.setContext(context);
67          variableSubstitutionsHelper = new VariableSubstitutionsHelper(context);
68          propertyModelHandlerHelper.setContext(context);
69      }
70  
71      protected void setContextName(String name) {
72          if (StringUtil.isNullOrEmpty(name)) {
73              addError("Cannot set context name to null or empty string");
74              return;
75          }
76          try {
77              String substName = subst(name);
78              addInfo("Setting context name to [" + substName + "]");
79              context.setName(substName);
80          } catch (IllegalStateException e) {
81              addError("Failed to rename context as [" + name + "]");
82          }
83      }
84  
85      protected void addOnConsoleStatusListener() {
86          StatusListenerConfigHelper.addOnConsoleListenerInstance(context, new OnConsoleStatusListener());
87      }
88  
89      /**
90       * Performs variable substitution.
91       *
92       * @param ref
93       * @return
94       */
95      @Override
96      public String subst(String ref) {
97          return variableSubstitutionsHelper.subst(ref);
98      }
99  
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 }