1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.joran.spi;
15
16 import java.util.List;
17 import java.util.Stack;
18 import java.util.function.Supplier;
19
20 import org.xml.sax.Attributes;
21 import org.xml.sax.Locator;
22
23 import ch.qos.logback.core.Context;
24 import ch.qos.logback.core.joran.action.Action;
25 import ch.qos.logback.core.joran.action.NOPAction;
26 import ch.qos.logback.core.joran.event.BodyEvent;
27 import ch.qos.logback.core.joran.event.EndEvent;
28 import ch.qos.logback.core.joran.event.SaxEvent;
29 import ch.qos.logback.core.joran.event.StartEvent;
30 import ch.qos.logback.core.spi.ContextAwareImpl;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class SaxEventInterpreter {
66 private static Action NOP_ACTION_SINGLETON = new NOPAction();
67
68 final private RuleStore ruleStore;
69 final private SaxEventInterpretationContext interpretationContext;
70 private Supplier<Action> implicitActionSupplier;
71 final private CAI_WithLocatorSupport cai;
72 private ElementPath elementPath;
73 Locator locator;
74 EventPlayer eventPlayer;
75 Context context;
76
77
78
79
80
81
82
83
84
85 Stack<Action> actionStack;
86
87
88
89
90
91 ElementPath skip = null;
92
93 public SaxEventInterpreter(Context context, RuleStore rs, ElementPath initialElementPath, List<SaxEvent> saxEvents) {
94 this.context = context;
95 this.cai = new CAI_WithLocatorSupport(context, this);
96 ruleStore = rs;
97 interpretationContext = new SaxEventInterpretationContext(context, this);
98 this.elementPath = initialElementPath;
99 actionStack = new Stack<>();
100 eventPlayer = new EventPlayer(this, saxEvents);
101 }
102
103 public EventPlayer getEventPlayer() {
104 return eventPlayer;
105 }
106
107 public ElementPath getCopyOfElementPath() {
108 return elementPath.duplicate();
109 }
110
111 public SaxEventInterpretationContext getSaxEventInterpretationContext() {
112 return interpretationContext;
113 }
114
115 public void startDocument() {
116 }
117
118 public void startElement(StartEvent se) {
119 setDocumentLocator(se.getLocator());
120 startElement(se.namespaceURI, se.localName, se.qName, se.attributes);
121 }
122
123 private void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
124
125 String tagName = getTagName(localName, qName);
126
127
128 elementPath.push(tagName);
129
130 if (skip != null) {
131
132 pushEmptyActionOntoActionStack();
133 return;
134 }
135
136 Action applicableAction = getApplicableAction(elementPath, atts);
137 if (applicableAction != null) {
138 actionStack.add(applicableAction);
139 callBeginAction(applicableAction, tagName, atts);
140 } else {
141
142 pushEmptyActionOntoActionStack();
143 String errMsg = "no applicable action for [" + tagName + "], current ElementPath is [" + elementPath + "]";
144 cai.addError(errMsg);
145 }
146 }
147
148
149
150
151 private void pushEmptyActionOntoActionStack() {
152 actionStack.push(NOP_ACTION_SINGLETON);
153 }
154
155 public void characters(BodyEvent be) {
156
157 setDocumentLocator(be.locator);
158
159 String body = be.getText();
160 Action applicableAction = actionStack.peek();
161
162 if (body != null) {
163 body = body.trim();
164 if (body.length() > 0) {
165 callBodyAction(applicableAction, body);
166 }
167 }
168 }
169
170 public void endElement(EndEvent endEvent) {
171 setDocumentLocator(endEvent.locator);
172 endElement(endEvent.namespaceURI, endEvent.localName, endEvent.qName);
173 }
174
175 private void endElement(String namespaceURI, String localName, String qName) {
176
177
178 Action applicableAction = actionStack.pop();
179
180 if (skip != null) {
181 if (skip.equals(elementPath)) {
182 skip = null;
183 }
184 } else if (applicableAction != NOP_ACTION_SINGLETON) {
185 callEndAction(applicableAction, getTagName(localName, qName));
186 }
187
188
189 elementPath.pop();
190 }
191
192 public Locator getLocator() {
193 return locator;
194 }
195
196
197 public void setDocumentLocator(Locator l) {
198 locator = l;
199 }
200
201 String getTagName(String localName, String qName) {
202 String tagName = localName;
203
204 if ((tagName == null) || (tagName.length() < 1)) {
205 tagName = qName;
206 }
207
208 return tagName;
209 }
210
211 public void setImplicitActionSupplier(Supplier<Action> actionSupplier) {
212 this.implicitActionSupplier = actionSupplier;
213 }
214
215
216
217
218 Action getApplicableAction(ElementPath elementPath, Attributes attributes) {
219 Supplier<Action> applicableActionSupplier = ruleStore.matchActions(elementPath);
220
221 if (applicableActionSupplier != null) {
222 Action applicableAction = applicableActionSupplier.get();
223 applicableAction.setContext(context);
224 return applicableAction;
225 } else {
226 Action implicitAction = implicitActionSupplier.get();
227 implicitAction.setContext(context);
228 return implicitAction;
229 }
230 }
231
232 void callBeginAction(Action applicableAction, String tagName, Attributes atts) {
233 if (applicableAction == null) {
234 return;
235 }
236
237
238
239 try {
240 applicableAction.begin(interpretationContext, tagName, atts);
241 } catch (ActionException e) {
242 skip = elementPath.duplicate();
243 cai.addError("ActionException in Action for tag [" + tagName + "]", e);
244 } catch (RuntimeException e) {
245 skip = elementPath.duplicate();
246 cai.addError("RuntimeException in Action for tag [" + tagName + "]", e);
247 }
248
249 }
250
251 private void callBodyAction(Action applicableAction, String body) {
252 if (applicableAction == null) {
253 return;
254 }
255
256 try {
257 applicableAction.body(interpretationContext, body);
258 } catch (ActionException ae) {
259 cai.addError("Exception in body() method for action [" + applicableAction + "]", ae);
260 }
261 }
262
263 private void callEndAction(Action applicableAction, String tagName) {
264 if (applicableAction == null) {
265 return;
266 }
267
268 try {
269 applicableAction.end(interpretationContext, tagName);
270 } catch (ActionException ae) {
271
272
273 cai.addError("ActionException in Action for tag [" + tagName + "]", ae);
274 } catch (RuntimeException e) {
275
276 cai.addError("RuntimeException in Action for tag [" + tagName + "]", e);
277 }
278 }
279
280 public RuleStore getRuleStore() {
281 return ruleStore;
282 }
283 }
284
285
286
287
288
289
290
291
292 class CAI_WithLocatorSupport extends ContextAwareImpl {
293
294 CAI_WithLocatorSupport(Context context, SaxEventInterpreter interpreter) {
295 super(context, interpreter);
296 }
297
298 @Override
299 protected Object getOrigin() {
300 SaxEventInterpreter i = (SaxEventInterpreter) super.getOrigin();
301 Locator locator = i.locator;
302 if (locator != null) {
303 return SaxEventInterpreter.class.getName() + "@" + locator.getLineNumber() + ":"
304 + locator.getColumnNumber();
305 } else {
306 return SaxEventInterpreter.class.getName() + "@NA:NA";
307 }
308 }
309 }