1
14 package ch.qos.logback.core.joran.spi;
15
16 import java.util.ArrayList;
17 import java.util.Iterator;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Stack;
21 import java.util.Vector;
22
23 import org.xml.sax.Attributes;
24 import org.xml.sax.Locator;
25
26 import ch.qos.logback.core.Context;
27 import ch.qos.logback.core.joran.action.Action;
28 import ch.qos.logback.core.joran.action.ImplicitAction;
29 import ch.qos.logback.core.joran.event.BodyEvent;
30 import ch.qos.logback.core.joran.event.EndEvent;
31 import ch.qos.logback.core.joran.event.StartEvent;
32 import ch.qos.logback.core.spi.ContextAwareImpl;
33
34
67 public class Interpreter {
68 private static List<Action> EMPTY_LIST = new Vector<Action>(0);
69
70 final private RuleStore ruleStore;
71 final private InterpretationContext interpretationContext;
72 final private ArrayList<ImplicitAction> implicitActions;
73 final private CAI_WithLocatorSupport cai;
74 private ElementPath elementPath;
75 Locator locator;
76 EventPlayer eventPlayer;
77
78
86 Stack<List<Action>> actionListStack;
87
88
92 ElementPath skip = null;
93
94 public Interpreter(Context context, RuleStore rs, ElementPath initialElementPath) {
95 this.cai = new CAI_WithLocatorSupport(context, this);
96 ruleStore = rs;
97 interpretationContext = new InterpretationContext(context, this);
98 implicitActions = new ArrayList<ImplicitAction>(3);
99 this.elementPath = initialElementPath;
100 actionListStack = new Stack<List<Action>>();
101 eventPlayer = new EventPlayer(this);
102 }
103
104 public EventPlayer getEventPlayer() {
105 return eventPlayer;
106 }
107
108 public void setInterpretationContextPropertiesMap(Map<String, String> propertiesMap) {
109 interpretationContext.setPropertiesMap(propertiesMap);
110 }
111
112
115 public InterpretationContext getExecutionContext() {
116 return getInterpretationContext();
117 }
118
119 public InterpretationContext getInterpretationContext() {
120 return interpretationContext;
121 }
122
123 public void startDocument() {
124 }
125
126 public void startElement(StartEvent se) {
127 setDocumentLocator(se.getLocator());
128 startElement(se.namespaceURI, se.localName, se.qName, se.attributes);
129 }
130
131 private void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
132
133 String tagName = getTagName(localName, qName);
134 elementPath.push(tagName);
135
136 if (skip != null) {
137
138 pushEmptyActionList();
139 return;
140 }
141
142 List<Action> applicableActionList = getApplicableActionList(elementPath, atts);
143 if (applicableActionList != null) {
144 actionListStack.add(applicableActionList);
145 callBeginAction(applicableActionList, tagName, atts);
146 } else {
147
148 pushEmptyActionList();
149 String errMsg = "no applicable action for [" + tagName + "], current ElementPath is [" + elementPath + "]";
150 cai.addError(errMsg);
151 }
152 }
153
154
157 private void pushEmptyActionList() {
158 actionListStack.add(EMPTY_LIST);
159 }
160
161 public void characters(BodyEvent be) {
162
163 setDocumentLocator(be.locator);
164
165 String body = be.getText();
166 List<Action> applicableActionList = actionListStack.peek();
167
168 if (body != null) {
169 body = body.trim();
170 if (body.length() > 0) {
171
172 callBodyAction(applicableActionList, body);
173 }
174 }
175 }
176
177 public void endElement(EndEvent endEvent) {
178 setDocumentLocator(endEvent.locator);
179 endElement(endEvent.namespaceURI, endEvent.localName, endEvent.qName);
180 }
181
182 private void endElement(String namespaceURI, String localName, String qName) {
183
184
185
186 List<Action> applicableActionList = (List<Action>) actionListStack.pop();
187
188 if (skip != null) {
189 if (skip.equals(elementPath)) {
190 skip = null;
191 }
192 } else if (applicableActionList != EMPTY_LIST) {
193 callEndAction(applicableActionList, getTagName(localName, qName));
194 }
195
196
197 elementPath.pop();
198 }
199
200 public Locator getLocator() {
201 return locator;
202 }
203
204 public void setDocumentLocator(Locator l) {
205 locator = l;
206 }
207
208 String getTagName(String localName, String qName) {
209 String tagName = localName;
210
211 if ((tagName == null) || (tagName.length() < 1)) {
212 tagName = qName;
213 }
214
215 return tagName;
216 }
217
218 public void addImplicitAction(ImplicitAction ia) {
219 implicitActions.add(ia);
220 }
221
222
227 List<Action> lookupImplicitAction(ElementPath elementPath, Attributes attributes, InterpretationContext ec) {
228 int len = implicitActions.size();
229
230 for (int i = 0; i < len; i++) {
231 ImplicitAction ia = (ImplicitAction) implicitActions.get(i);
232
233 if (ia.isApplicable(elementPath, attributes, ec)) {
234 List<Action> actionList = new ArrayList<Action>(1);
235 actionList.add(ia);
236
237 return actionList;
238 }
239 }
240
241 return null;
242 }
243
244
247 List<Action> getApplicableActionList(ElementPath elementPath, Attributes attributes) {
248 List<Action> applicableActionList = ruleStore.matchActions(elementPath);
249
250
251 if (applicableActionList == null) {
252 applicableActionList = lookupImplicitAction(elementPath, attributes, interpretationContext);
253 }
254
255 return applicableActionList;
256 }
257
258 void callBeginAction(List<Action> applicableActionList, String tagName, Attributes atts) {
259 if (applicableActionList == null) {
260 return;
261 }
262
263 Iterator<Action> i = applicableActionList.iterator();
264 while (i.hasNext()) {
265 Action action = (Action) i.next();
266
267
268 try {
269 action.begin(interpretationContext, tagName, atts);
270 } catch (ActionException e) {
271 skip = elementPath.duplicate();
272 cai.addError("ActionException in Action for tag [" + tagName + "]", e);
273 } catch (RuntimeException e) {
274 skip = elementPath.duplicate();
275 cai.addError("RuntimeException in Action for tag [" + tagName + "]", e);
276 }
277 }
278 }
279
280 private void callBodyAction(List<Action> applicableActionList, String body) {
281 if (applicableActionList == null) {
282 return;
283 }
284 Iterator<Action> i = applicableActionList.iterator();
285
286 while (i.hasNext()) {
287 Action action = i.next();
288 try {
289 action.body(interpretationContext, body);
290 } catch (ActionException ae) {
291 cai.addError("Exception in end() methd for action [" + action + "]", ae);
292 }
293 }
294 }
295
296 private void callEndAction(List<Action> applicableActionList, String tagName) {
297 if (applicableActionList == null) {
298 return;
299 }
300
301
302 Iterator<Action> i = applicableActionList.iterator();
303
304 while (i.hasNext()) {
305 Action action = i.next();
306
307
308 try {
309 action.end(interpretationContext, tagName);
310 } catch (ActionException ae) {
311
312
313 cai.addError("ActionException in Action for tag [" + tagName + "]", ae);
314 } catch (RuntimeException e) {
315
316 cai.addError("RuntimeException in Action for tag [" + tagName + "]", e);
317 }
318 }
319 }
320
321 public RuleStore getRuleStore() {
322 return ruleStore;
323 }
324 }
325
326
333 class CAI_WithLocatorSupport extends ContextAwareImpl {
334
335 CAI_WithLocatorSupport(Context context, Interpreter interpreter) {
336 super(context, interpreter);
337 }
338
339 @Override
340 protected Object getOrigin() {
341 Interpreter i = (Interpreter) super.getOrigin();
342 Locator locator = i.locator;
343 if (locator != null) {
344 return Interpreter.class.getName() + "@" + locator.getLineNumber() + ":" + locator.getColumnNumber();
345 } else {
346 return Interpreter.class.getName() + "@NA:NA";
347 }
348 }
349 }
350