1   /*
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2026, 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 v2.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.core.boolex;
16  
17  import ch.qos.logback.core.model.processor.ModelInterpretationContext;
18  import ch.qos.logback.core.spi.ContextAwareBase;
19  import ch.qos.logback.core.spi.PropertyContainer;
20  import ch.qos.logback.core.util.OptionHelper;
21  
22  import static ch.qos.logback.core.CoreConstants.EMPTY_STRING;
23  
24  /**
25   * <p>Abstract base class provides some scaffolding. It is intended to ease migration
26   * from <b>legacy</b> conditional processing in configuration files
27   * (e.g. &lt;if>, &lt;then&gt;, &lt;else>) using the Janino library. Nevertheless,
28   * it should also be useful in newly written code.</p>
29   *
30   * <p>Properties are looked up in the following order:</p>
31   *
32   * <ol>
33   *  <li>In the local property container, usually the {@link ModelInterpretationContext} </li>
34   *  <li>in the logger context</li>
35   *  <li>system properties</li>
36   *  <li>environment variables</li>
37   * </ol>
38   *
39   * @author Ceki G&uuml;lc&uuml;
40   * @see OptionHelper#propertyLookup(String, PropertyContainer, PropertyContainer)
41   * @since 1.5.20
42   */
43  abstract public class PropertyConditionBase extends ContextAwareBase implements PropertyCondition {
44  
45      /**
46       * Indicates whether this evaluator has been started.
47       */
48      boolean started;
49      /**
50       * <p>The local property container used for property lookups.</p>
51       *
52       * <p>Local properties correspond to the properties in the embedding
53       * configurator, i.e. usually the {@link ModelInterpretationContext} instance.</p>
54       */
55      PropertyContainer localPropertyContainer;
56  
57      /**
58       * Returns the local property container used by this evaluator.
59       *
60       * <p>Local properties correspond to the properties in the embedding
61       * configurator, i.e. usually the {@link ModelInterpretationContext} instance.</p>
62       *
63       * @return the local property container
64       */
65      @Override
66      public PropertyContainer getLocalPropertyContainer() {
67          return localPropertyContainer;
68      }
69  
70      /**
71       * Sets the local property container for this evaluator.
72       *
73       * <p>Local properties correspond to the properties in the embedding
74       * configurator, i.e. usually the {@link ModelInterpretationContext} instance.</p>
75       *
76       * @param aLocalPropertyContainer the local property container to set
77       */
78      @Override
79      public void setLocalPropertyContainer(PropertyContainer aLocalPropertyContainer) {
80          this.localPropertyContainer = aLocalPropertyContainer;
81      }
82  
83      /**
84       * Checks if the property with the given key is null.
85       *
86       * <p>The property is looked up via the
87       * {@link OptionHelper#propertyLookup(String, PropertyContainer, PropertyContainer)} method.
88       * See above for the lookup order.</p>
89       *
90       * @param k the property key
91       * @return true if the property is null, false otherwise
92       */
93      public boolean isNull(String k) {
94          String val = OptionHelper.propertyLookup(k, localPropertyContainer, getContext());
95          return (val == null);
96      }
97  
98      /**
99       * Checks if the property with the given key is defined (not null).
100      *
101      * <p>The property is looked up via the
102      * {@link OptionHelper#propertyLookup(String, PropertyContainer, PropertyContainer)} method.
103      * See above for the lookup order.</p>
104      *
105      * @param k the property key
106      * @return true if the property is defined, false otherwise
107      */
108     public boolean isDefined(String k) {
109         String val = OptionHelper.propertyLookup(k, localPropertyContainer, getContext());
110         return (val != null);
111     }
112 
113     /**
114      * Retrieves the property value for the given key, returning an empty string if null.
115      * This is a shorthand for {@link #property(String)}.
116      *
117      * @param k the property key
118      * @return the property value or an empty string
119      */
120     public String p(String k) {
121         return property(k);
122     }
123 
124     /**
125      * Retrieves the property value for the given key, returning an empty string if null.
126      *
127      * <p>The property is looked up via the
128      * {@link OptionHelper#propertyLookup(String, PropertyContainer, PropertyContainer)} method.
129      * See above for the lookup order.</p>
130      *
131      * @param k the property key
132      * @return the property value or an empty string
133      */
134     public String property(String k) {
135         String val = OptionHelper.propertyLookup(k, localPropertyContainer, getContext());
136         if (val != null)
137             return val;
138         else
139             return EMPTY_STRING;
140     }
141 
142     /**
143      * Compare the resolved property value with the provided expected value.
144      *
145      * <p>The property is looked up via the
146      * {@link OptionHelper#propertyLookup(String, PropertyContainer, PropertyContainer)} method.
147      * See above for the lookup order.</p>
148      *
149      * <p>Returns {@code true} if the resolved property value is equal to {@code val}
150      * according to {@link String#equals(Object)}. If the resolved property value or {@code val} is null,
151      * then false is returned.</p>
152      *
153      * @param propertyKey the property key to look up
154      * @param value       expected string value to compare against; must be non-null
155      * @return {@code true} if the resolved property equals {@code value},
156      * {@code false} otherwise or if either the resolved property or {@code value} is null.
157      * @since 1.5.24
158      */
159     public boolean propertyEquals(String propertyKey, String value) {
160         String actual = OptionHelper.propertyLookup(propertyKey, localPropertyContainer, getContext());
161         if (actual == null || value == null) {
162             return false;
163         }
164         return actual.equals(value);
165     }
166 
167 
168     /**
169      * Determine whether the resolved property value contains the given substring.
170      * <p>
171      *
172      * <p>The property is looked up via the
173      * {@link OptionHelper#propertyLookup(String, PropertyContainer, PropertyContainer)} method.
174      * See above for the lookup order.</p>
175      *
176      * <p>This method returns {@code true} if the resolved property value's
177      * {@link String#contains(CharSequence)} returns {@code true} for the supplied
178      * {@code inclusion}. False is returned if either the resolved property value or
179      * {@code inclusion} parameter is null.</p>
180      *
181      * @param k         the property key to look up
182      * @param inclusion substring to search for in the resolved property value; must be non-null
183      * @return {@code true} if the property value contains {@code inclusion}, false otherwise or
184      * if either the resolved property value or {@code inclusion} is null
185      *
186      * @since 1.5.24
187      */
188     public boolean propertyContains(String k, String inclusion) {
189         String actual = OptionHelper.propertyLookup(k, localPropertyContainer, getContext());
190         if (actual == null || inclusion == null)
191             return false;
192 
193         return actual.contains(inclusion);
194     }
195 
196     /**
197      * Checks if this evaluator has been started.
198      *
199      * @return true if started, false otherwise
200      */
201     public boolean isStarted() {
202         return started;
203     }
204 
205     /**
206      * Starts this evaluator.
207      */
208     public void start() {
209         started = true;
210     }
211 
212     /**
213      * Stops this evaluator.
214      */
215     public void stop() {
216         started = false;
217     }
218 }