1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.model.processor;
15
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.HashMap;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Properties;
22 import java.util.Stack;
23 import java.util.function.Supplier;
24
25 import ch.qos.logback.core.Appender;
26 import ch.qos.logback.core.Context;
27 import ch.qos.logback.core.joran.GenericXMLConfigurator;
28 import ch.qos.logback.core.joran.JoranConfiguratorBase;
29 import ch.qos.logback.core.joran.JoranConstants;
30 import ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry;
31 import ch.qos.logback.core.joran.util.beans.BeanDescriptionCache;
32 import ch.qos.logback.core.model.Model;
33 import ch.qos.logback.core.model.util.VariableSubstitutionsHelper;
34 import ch.qos.logback.core.spi.AppenderAttachable;
35 import ch.qos.logback.core.spi.ContextAwareBase;
36 import ch.qos.logback.core.spi.ContextAwarePropertyContainer;
37 import ch.qos.logback.core.spi.PropertyContainer;
38
39 public class ModelInterpretationContext extends ContextAwareBase implements ContextAwarePropertyContainer {
40
41 Stack<Object> objectStack;
42 Stack<Model> modelStack;
43
44
45
46
47
48
49
50
51 Supplier<? extends GenericXMLConfigurator> configuratorSupplier;
52
53
54 Map<String, Object> objectMap;
55 protected VariableSubstitutionsHelper variableSubstitutionsHelper;
56 protected Map<String, String> importMap;
57
58 final private BeanDescriptionCache beanDescriptionCache;
59 final DefaultNestedComponentRegistry defaultNestedComponentRegistry = new DefaultNestedComponentRegistry();
60 List<DependencyDefinition> dependencyDefinitionList = new ArrayList<>();
61 final List<String> startedDependees = new ArrayList<>();
62
63 Object configuratorHint;
64
65 Model topModel;
66
67 public ModelInterpretationContext(Context context) {
68 this(context, null);
69 }
70
71 public ModelInterpretationContext(Context context, Object configuratorHint) {
72 this.context = context;
73 this.configuratorHint = configuratorHint;
74 this.objectStack = new Stack<>();
75 this.modelStack = new Stack<>();
76 this.beanDescriptionCache = new BeanDescriptionCache(context);
77 objectMap = new HashMap<>(5);
78 variableSubstitutionsHelper = new VariableSubstitutionsHelper(context);
79 importMap = new HashMap<>(5);
80 }
81
82 public ModelInterpretationContext(ModelInterpretationContext otherMic) {
83 this(otherMic.context, otherMic.configuratorHint);
84 importMap = new HashMap<>(otherMic.importMap);
85 variableSubstitutionsHelper = new VariableSubstitutionsHelper(context, otherMic.getCopyOfPropertyMap());
86 defaultNestedComponentRegistry.duplicate(otherMic.getDefaultNestedComponentRegistry());
87 createAppenderBags();
88 }
89
90 public Map<String, Object> getObjectMap() {
91 return objectMap;
92 }
93
94 public void createAppenderBags() {
95 objectMap.put(JoranConstants.APPENDER_BAG, new HashMap<String, Appender<?>>());
96 objectMap.put(JoranConstants.APPENDER_REF_BAG, new HashMap<String, AppenderAttachable<?>>());
97 }
98
99 public Model getTopModel() {
100 return topModel;
101 }
102
103 public void setTopModel(Model topModel) {
104 this.topModel = topModel;
105 }
106
107
108
109 public void pushModel(Model m) {
110 modelStack.push(m);
111 }
112
113 public Model peekModel() {
114 return modelStack.peek();
115 }
116
117 public boolean isModelStackEmpty() {
118 return modelStack.isEmpty();
119 }
120
121 public Model popModel() {
122 return modelStack.pop();
123 }
124
125
126
127 public Stack<Object> getObjectStack() {
128 return objectStack;
129 }
130
131 public boolean isObjectStackEmpty() {
132 return objectStack.isEmpty();
133 }
134
135 public Object peekObject() {
136 return objectStack.peek();
137 }
138
139 public void pushObject(Object o) {
140 objectStack.push(o);
141 }
142
143 public Object popObject() {
144 return objectStack.pop();
145 }
146
147 public Object getObject(int i) {
148 return objectStack.get(i);
149 }
150
151
152
153 public Object getConfiguratorHint() {
154 return configuratorHint;
155 }
156
157 public void setConfiguratorHint(Object configuratorHint) {
158 this.configuratorHint = configuratorHint;
159 }
160
161 public BeanDescriptionCache getBeanDescriptionCache() {
162 return beanDescriptionCache;
163 }
164
165 public String subst(String ref) {
166
167 String substituted = variableSubstitutionsHelper.subst(ref);
168 if(ref != null && !ref.equals(substituted)) {
169 addInfo("value \""+substituted+"\" substituted for \""+ref+"\"");
170 }
171 return substituted;
172 }
173
174
175 public DefaultNestedComponentRegistry getDefaultNestedComponentRegistry() {
176 return defaultNestedComponentRegistry;
177 }
178
179
180
181 public void addDependencyDefinition(DependencyDefinition dd) {
182 dependencyDefinitionList.add(dd);
183 }
184
185 public List<DependencyDefinition> getDependencyDefinitions() {
186 return Collections.unmodifiableList(dependencyDefinitionList);
187 }
188
189 public List<String> getDependeeNamesForModel(Model model) {
190 List<String> dependencyList = new ArrayList<>();
191 for (DependencyDefinition dd : dependencyDefinitionList) {
192 if (dd.getDepender() == model) {
193 dependencyList.add(dd.getDependee());
194 }
195 }
196 return dependencyList;
197 }
198
199 public boolean hasDependers(String dependeeName) {
200
201 if (dependeeName == null || dependeeName.trim().length() == 0) {
202 new IllegalArgumentException("Empty dependeeName name not allowed here");
203 }
204
205 for (DependencyDefinition dd : dependencyDefinitionList) {
206 if (dd.dependee.equals(dependeeName))
207 return true;
208 }
209
210 return false;
211 }
212
213
214 public void markStartOfNamedDependee(String name) {
215 startedDependees.add(name);
216 }
217
218 public boolean isNamedDependeeStarted(String name) {
219 return startedDependees.contains(name);
220 }
221
222
223
224
225
226
227
228 @Override
229 public void addSubstitutionProperty(String key, String value) {
230 variableSubstitutionsHelper.addSubstitutionProperty(key, value);
231 }
232
233
234
235
236
237 public String getProperty(String key) {
238 return variableSubstitutionsHelper.getProperty(key);
239 }
240
241 @Override
242 public Map<String, String> getCopyOfPropertyMap() {
243 return variableSubstitutionsHelper.getCopyOfPropertyMap();
244 }
245
246
247
248
249
250
251
252
253
254
255
256 public void addImport(String stem, String fqcn) {
257 importMap.put(stem, fqcn);
258 }
259
260 public Map<String, String> getImportMapCopy() {
261 return new HashMap<>(importMap);
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276 public String getImport(String stem) {
277 if (stem == null)
278 return null;
279
280 String result = importMap.get(stem);
281 if (result == null)
282 return stem;
283 else
284 return result;
285 }
286
287
288
289
290
291
292 @Override
293 public Supplier<? extends GenericXMLConfigurator> getConfiguratorSupplier() {
294 return this.configuratorSupplier;
295 }
296
297
298
299
300
301 public void setConfiguratorSupplier(Supplier<? extends GenericXMLConfigurator> configuratorSupplier) {
302 this.configuratorSupplier = configuratorSupplier;
303 }
304 }