1
14 package ch.qos.logback.core.joran.conditional;
15
16 import java.util.List;
17 import java.util.Stack;
18
19 import ch.qos.logback.core.CoreConstants;
20 import ch.qos.logback.core.util.EnvUtil;
21 import org.xml.sax.Attributes;
22
23 import ch.qos.logback.core.joran.action.Action;
24 import ch.qos.logback.core.joran.event.SaxEvent;
25 import ch.qos.logback.core.joran.spi.ActionException;
26 import ch.qos.logback.core.joran.spi.InterpretationContext;
27 import ch.qos.logback.core.joran.spi.Interpreter;
28 import ch.qos.logback.core.util.OptionHelper;
29
30 public class IfAction extends Action {
31 private static final String CONDITION_ATTR = "condition";
32
33 public static final String MISSING_JANINO_MSG = "Could not find Janino library on the class path. Skipping conditional processing.";
34 public static final String MISSING_JANINO_SEE = "See also " + CoreConstants.CODES_URL + "#ifJanino";
35
36 Stack<IfState> stack = new Stack<IfState>();
37
38 @Override
39 public void begin(InterpretationContext ic, String name, Attributes attributes) throws ActionException {
40
41 IfState state = new IfState();
42 boolean emptyStack = stack.isEmpty();
43 stack.push(state);
44
45 if (!emptyStack) {
46 return;
47 }
48
49 ic.pushObject(this);
50 if (!EnvUtil.isJaninoAvailable()) {
51 addError(MISSING_JANINO_MSG);
52 addError(MISSING_JANINO_SEE);
53 return;
54 }
55
56 state.active = true;
57 Condition condition = null;
58 String conditionAttribute = attributes.getValue(CONDITION_ATTR);
59
60 if (!OptionHelper.isEmpty(conditionAttribute)) {
61 conditionAttribute = OptionHelper.substVars(conditionAttribute, ic, context);
62 PropertyEvalScriptBuilder pesb = new PropertyEvalScriptBuilder(ic);
63 pesb.setContext(context);
64 try {
65 condition = pesb.build(conditionAttribute);
66 } catch (Exception e) {
67 addError("Failed to parse condition [" + conditionAttribute + "]", e);
68 }
69
70 if (condition != null) {
71 state.boolResult = condition.evaluate();
72 }
73
74 }
75 }
76
77 @Override
78 public void end(InterpretationContext ic, String name) throws ActionException {
79
80 IfState state = stack.pop();
81 if (!state.active) {
82 return;
83 }
84
85 Object o = ic.peekObject();
86 if (o == null) {
87 throw new IllegalStateException("Unexpected null object on stack");
88 }
89 if (!(o instanceof IfAction)) {
90 throw new IllegalStateException("Unexpected object of type [" + o.getClass() + "] on stack");
91 }
92
93 if (o != this) {
94 throw new IllegalStateException("IfAction different then current one on stack");
95 }
96 ic.popObject();
97
98 if (state.boolResult == null) {
99 addError("Failed to determine \"if then else\" result");
100 return;
101 }
102
103 Interpreter interpreter = ic.getJoranInterpreter();
104 List<SaxEvent> listToPlay = state.thenSaxEventList;
105 if (!state.boolResult) {
106 listToPlay = state.elseSaxEventList;
107 }
108
109
110 if (listToPlay != null) {
111
112 interpreter.getEventPlayer().addEventsDynamically(listToPlay, 1);
113 }
114
115 }
116
117 public void setThenSaxEventList(List<SaxEvent> thenSaxEventList) {
118 IfState state = stack.firstElement();
119 if (state.active) {
120 state.thenSaxEventList = thenSaxEventList;
121 } else {
122 throw new IllegalStateException("setThenSaxEventList() invoked on inactive IfAction");
123 }
124 }
125
126 public void setElseSaxEventList(List<SaxEvent> elseSaxEventList) {
127 IfState state = stack.firstElement();
128 if (state.active) {
129 state.elseSaxEventList = elseSaxEventList;
130 } else {
131 throw new IllegalStateException("setElseSaxEventList() invoked on inactive IfAction");
132 }
133
134 }
135
136 public boolean isActive() {
137 if (stack == null)
138 return false;
139 if (stack.isEmpty())
140 return false;
141 return stack.peek().active;
142 }
143 }
144
145 class IfState {
146 Boolean boolResult;
147 List<SaxEvent> thenSaxEventList;
148 List<SaxEvent> elseSaxEventList;
149 boolean active;
150 }
151