View Javadoc
1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2015, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
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         // if boolResult==false & missing else, listToPlay may be null
110         if (listToPlay != null) {
111             // insert past this event
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 }