1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.model.processor;
15
16 import ch.qos.logback.core.Context;
17 import ch.qos.logback.core.joran.action.ImcplicitActionDataForBasicProperty;
18 import ch.qos.logback.core.joran.action.ImplicitModelData;
19 import ch.qos.logback.core.joran.action.ImplicitModelDataForComplexProperty;
20 import ch.qos.logback.core.joran.spi.NoAutoStartUtil;
21 import ch.qos.logback.core.joran.util.PropertySetter;
22 import ch.qos.logback.core.joran.util.beans.BeanDescriptionCache;
23 import ch.qos.logback.core.model.ComponentModel;
24 import ch.qos.logback.core.model.ImplicitModel;
25 import ch.qos.logback.core.model.Model;
26 import ch.qos.logback.core.model.ModelConstants;
27 import ch.qos.logback.core.spi.ContextAware;
28 import ch.qos.logback.core.spi.LifeCycle;
29 import ch.qos.logback.core.util.AggregationType;
30 import ch.qos.logback.core.util.Loader;
31 import ch.qos.logback.core.util.OptionHelper;
32
33 public class ImplicitModelHandler extends ModelHandlerBase {
34
35 private final BeanDescriptionCache beanDescriptionCache;
36 private ImplicitModelData implicitModelData;
37
38 static public final String IGNORING_UNKNOWN_PROP = "Ignoring unknown property";
39
40 boolean inError = false;
41
42 public ImplicitModelHandler(Context context, BeanDescriptionCache beanDescriptionCache) {
43 super(context);
44 this.beanDescriptionCache = beanDescriptionCache;
45 }
46
47 protected Class<? extends ImplicitModel> getSupportedModelClass() {
48 return ImplicitModel.class;
49 }
50
51 static public ImplicitModelHandler makeInstance(Context context, ModelInterpretationContext mic) {
52 BeanDescriptionCache beanDescriptionCache = mic.getBeanDescriptionCache();
53 return new ImplicitModelHandler(context, beanDescriptionCache);
54 }
55
56 @Override
57 public void handle(ModelInterpretationContext mic, Model model) {
58
59 ImplicitModel implicitModel = (ImplicitModel) model;
60
61
62 if (mic.isObjectStackEmpty()) {
63 inError = true;
64 return;
65 }
66 String nestedElementTagName = implicitModel.getTag();
67
68 Object o = mic.peekObject();
69 PropertySetter parentBean = new PropertySetter(beanDescriptionCache, o);
70 parentBean.setContext(context);
71
72 AggregationType aggregationType = parentBean.computeAggregationType(nestedElementTagName);
73
74 switch (aggregationType) {
75 case NOT_FOUND:
76 addWarn(IGNORING_UNKNOWN_PROP+" [" + nestedElementTagName + "] in [" + o.getClass().getName() + "]");
77 inError = true;
78
79 implicitModel.markAsSkipped();
80 return;
81 case AS_BASIC_PROPERTY:
82 case AS_BASIC_PROPERTY_COLLECTION:
83 ImcplicitActionDataForBasicProperty adBasicProperty = new ImcplicitActionDataForBasicProperty(parentBean,
84 aggregationType, nestedElementTagName);
85 implicitModelData = adBasicProperty;
86 doBasicProperty(mic, model, adBasicProperty);
87 return;
88
89 case AS_COMPLEX_PROPERTY_COLLECTION:
90 case AS_COMPLEX_PROPERTY:
91 ImplicitModelDataForComplexProperty adComplex = new ImplicitModelDataForComplexProperty(parentBean,
92 aggregationType, nestedElementTagName);
93 implicitModelData = adComplex;
94 doComplex(mic, implicitModel, adComplex);
95 return;
96 default:
97 addError("PropertySetter.computeAggregationType returned " + aggregationType);
98 return;
99 }
100
101 }
102
103 void doBasicProperty(ModelInterpretationContext interpretationContext, Model model,
104 ImcplicitActionDataForBasicProperty actionData) {
105 String finalBody = interpretationContext.subst(model.getBodyText());
106
107
108
109 switch (actionData.aggregationType) {
110 case AS_BASIC_PROPERTY:
111 actionData.parentBean.setProperty(actionData.propertyName, finalBody);
112 break;
113 case AS_BASIC_PROPERTY_COLLECTION:
114 actionData.parentBean.addBasicProperty(actionData.propertyName, finalBody);
115 break;
116 default:
117 addError("Unexpected aggregationType " + actionData.aggregationType);
118 }
119 }
120
121 public void doComplex(ModelInterpretationContext interpretationContext, ComponentModel componentModel,
122 ImplicitModelDataForComplexProperty actionData) {
123
124 String className = componentModel.getClassName();
125
126 String substClassName = interpretationContext.subst(className);
127
128 String fqcn = interpretationContext.getImport(substClassName);
129
130 Class<?> componentClass = null;
131 try {
132
133 if (!OptionHelper.isNullOrEmptyOrAllSpaces(fqcn)) {
134 componentClass = Loader.loadClass(fqcn, context);
135 } else {
136
137 PropertySetter parentBean = actionData.parentBean;
138 componentClass = parentBean.getClassNameViaImplicitRules(actionData.propertyName,
139 actionData.getAggregationType(), interpretationContext.getDefaultNestedComponentRegistry());
140 }
141
142 if (componentClass == null) {
143 actionData.inError = true;
144 String errMsg = "Could not find an appropriate class for property [" + componentModel.getTag() + "]";
145 addError(errMsg);
146 return;
147 }
148
149 if (OptionHelper.isNullOrEmptyOrAllSpaces(fqcn)) {
150 addInfo("Assuming default type [" + componentClass.getName() + "] for [" + componentModel.getTag()
151 + "] property");
152 }
153
154 actionData.setNestedComplexProperty(componentClass.getConstructor().newInstance());
155
156
157 if (actionData.getNestedComplexProperty() instanceof ContextAware) {
158 ((ContextAware) actionData.getNestedComplexProperty()).setContext(this.context);
159 }
160
161
162 interpretationContext.pushObject(actionData.getNestedComplexProperty());
163
164 } catch (Exception oops) {
165 actionData.inError = true;
166 String msg = "Could not create component [" + componentModel.getTag() + "] of type [" + fqcn + "]";
167 addError(msg, oops);
168 }
169 }
170
171 @Override
172 public void postHandle(ModelInterpretationContext intercon, Model model) {
173 if (inError) {
174 return;
175 }
176
177 if(implicitModelData == null)
178 return;
179
180
181
182 if(implicitModelData.inError) {
183 return;
184 }
185 if (implicitModelData instanceof ImplicitModelDataForComplexProperty) {
186 postHandleComplex(intercon, model, (ImplicitModelDataForComplexProperty) implicitModelData);
187 }
188
189 }
190
191 private void postHandleComplex(ModelInterpretationContext mic, Model model,
192 ImplicitModelDataForComplexProperty imdComplex) {
193
194 PropertySetter nestedBean = new PropertySetter(beanDescriptionCache,
195 imdComplex.getNestedComplexProperty());
196 nestedBean.setContext(context);
197
198
199 if (nestedBean.computeAggregationType(ModelConstants.PARENT_PROPPERTY_KEY) == AggregationType.AS_COMPLEX_PROPERTY) {
200 nestedBean.setComplexProperty(ModelConstants.PARENT_PROPPERTY_KEY, imdComplex.parentBean.getObj());
201 }
202
203
204
205 Object nestedComplexProperty = imdComplex.getNestedComplexProperty();
206 if (NoAutoStartUtil.shouldBeStarted(nestedComplexProperty)) {
207 ((LifeCycle) nestedComplexProperty).start();
208 }
209
210 Object o = mic.peekObject();
211
212 if (o != imdComplex.getNestedComplexProperty()) {
213 addError("The object on the top the of the stack is not the component pushed earlier.");
214 } else {
215 mic.popObject();
216
217 switch (imdComplex.aggregationType) {
218 case AS_COMPLEX_PROPERTY:
219 imdComplex.parentBean.setComplexProperty(model.getTag(), imdComplex.getNestedComplexProperty());
220
221 break;
222 case AS_COMPLEX_PROPERTY_COLLECTION:
223 imdComplex.parentBean.addComplexProperty(model.getTag(), imdComplex.getNestedComplexProperty());
224 break;
225 default:
226 addError("Unexpected aggregationType " + imdComplex.aggregationType);
227 }
228 }
229 }
230
231 }