1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.model.processor.conditional;
15
16 import ch.qos.logback.core.util.EnvUtil;
17 import ch.qos.logback.core.util.OptionHelper;
18 import ch.qos.logback.core.Context;
19 import ch.qos.logback.core.CoreConstants;
20 import ch.qos.logback.core.joran.conditional.Condition;
21 import ch.qos.logback.core.joran.conditional.PropertyEvalScriptBuilder;
22 import ch.qos.logback.core.model.Model;
23 import ch.qos.logback.core.model.conditional.IfModel;
24 import ch.qos.logback.core.model.conditional.IfModel.BranchState;
25 import ch.qos.logback.core.model.processor.ModelHandlerBase;
26 import ch.qos.logback.core.model.processor.ModelHandlerException;
27 import ch.qos.logback.core.model.processor.ModelInterpretationContext;
28 import ch.qos.logback.core.spi.ScanException;
29
30 public class IfModelHandler extends ModelHandlerBase {
31
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 public static final String NEW_OPERATOR_DISALLOWED_MSG = "The 'condition' attribute may not contain the 'new' operator.";
37 public static final String NEW_OPERATOR_DISALLOWED_SEE = "See also " + CoreConstants.CODES_URL + "#conditionNew";
38
39 public static final String CONDITION_ATTR_DEPRECATED_MSG = "The 'condition' attribute in <if> element is deprecated and slated for removal. Use <condition> element instead.";
40 public static final String CONDITION_ATTR_DEPRECATED_SEE = "See also " + CoreConstants.CODES_URL + "#conditionAttributeDeprecation";
41
42 enum Branch {IF_BRANCH, ELSE_BRANCH; }
43
44 IfModel ifModel = null;
45
46 public IfModelHandler(Context context) {
47 super(context);
48 }
49
50 static public ModelHandlerBase makeInstance(Context context, ModelInterpretationContext ic) {
51 return new IfModelHandler(context);
52 }
53
54 @Override
55 protected Class<IfModel> getSupportedModelClass() {
56 return IfModel.class;
57 }
58
59 @Override
60 public void handle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {
61
62 ifModel = (IfModel) model;
63 mic.pushModel(ifModel);
64 Object micTopObject = mic.peekObject();
65 String conditionStr = ifModel.getCondition();
66 emitDeprecationWarningIfNecessary(conditionStr);
67
68
69 if(micTopObject instanceof BranchState) {
70 BranchState branchState = (BranchState) micTopObject;
71 ifModel.setBranchState(branchState);
72
73 mic.popObject();
74 } else {
75 janinoFallback(mic, model, conditionStr);
76 }
77 }
78
79 private void janinoFallback(ModelInterpretationContext mic, Model model, String conditionStr) {
80 if (!EnvUtil.isJaninoAvailable()) {
81 addError(MISSING_JANINO_MSG);
82 addError(MISSING_JANINO_SEE);
83 return;
84 }
85
86 Condition condition = null;
87 int lineNum = model.getLineNumber();
88
89 if (!OptionHelper.isNullOrEmptyOrAllSpaces(conditionStr)) {
90 try {
91 conditionStr = OptionHelper.substVars(conditionStr, mic, context);
92 } catch (ScanException e) {
93 addError("Failed to parse input [" + conditionStr + "] on line "+lineNum, e);
94 ifModel.setBranchState(BranchState.IN_ERROR);
95 return;
96 }
97
98
99 if(hasNew(conditionStr)) {
100 addError(NEW_OPERATOR_DISALLOWED_MSG);
101 addError(NEW_OPERATOR_DISALLOWED_SEE);
102 return;
103 }
104
105 try {
106 PropertyEvalScriptBuilder pesb = new PropertyEvalScriptBuilder(mic);
107 pesb.setContext(context);
108 condition = pesb.build(conditionStr);
109 } catch (Exception|NoClassDefFoundError e) {
110 ifModel.setBranchState(BranchState.IN_ERROR);
111 addError("Failed to parse condition [" + conditionStr + "] on line "+lineNum, e);
112 return;
113 }
114
115 if (condition != null) {
116 boolean boolResult = condition.evaluate();
117 addInfo("Condition ["+conditionStr+"] evaluated to "+boolResult+ " on line "+lineNum);
118 ifModel.setBranchState(boolResult);
119 } else {
120 addError("The condition variable is null. This should not occur.");
121 ifModel.setBranchState(BranchState.IN_ERROR);
122 return;
123 }
124 }
125 }
126
127 private void emitDeprecationWarningIfNecessary(String conditionStr) {
128 if(!OptionHelper.isNullOrEmptyOrAllSpaces(conditionStr)) {
129 addWarn(CONDITION_ATTR_DEPRECATED_MSG);
130 addWarn(CONDITION_ATTR_DEPRECATED_SEE);
131 }
132 }
133
134
135 private boolean hasNew(String conditionStr) {
136 return conditionStr.contains("new ");
137 }
138
139 @Override
140 public void postHandle(ModelInterpretationContext mic, Model model) throws ModelHandlerException {
141
142 if(mic.isModelStackEmpty()) {
143 addError("Unexpected unexpected empty model stack.");
144 return;
145 }
146
147 Object o = mic.peekModel();
148 if (o != ifModel) {
149 addWarn("The object [" + o + "] on the top the of the stack is not the expected [" + ifModel);
150 } else {
151 mic.popModel();
152 }
153 }
154
155 }