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