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 this.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 this.implicitModelData = adBasicProperty;
86 doBasicProperty(mic, implicitModel, adBasicProperty);
87 return;
88
89 case AS_COMPLEX_PROPERTY_COLLECTION:
90 case AS_COMPLEX_PROPERTY:
91 Class<?> propertyType = parentBean.getTypeForComplexProperty(nestedElementTagName, aggregationType);
92 ImplicitModelDataForComplexProperty imdForComplexProperty = new ImplicitModelDataForComplexProperty(parentBean,
93 aggregationType, nestedElementTagName);
94 imdForComplexProperty.setExpectedPropertyType(propertyType);
95 this.implicitModelData = imdForComplexProperty;
96 doComplex(mic, implicitModel, imdForComplexProperty);
97 return;
98 default:
99 addError("PropertySetter.computeAggregationType returned " + aggregationType);
100 return;
101 }
102
103 }
104
105 void doBasicProperty(ModelInterpretationContext interpretationContext, Model model,
106 ImcplicitActionDataForBasicProperty actionData) {
107 String finalBody = interpretationContext.subst(model.getBodyText());
108
109
110
111 switch (actionData.aggregationType) {
112 case AS_BASIC_PROPERTY:
113 actionData.parentBean.setProperty(actionData.propertyName, finalBody);
114 break;
115 case AS_BASIC_PROPERTY_COLLECTION:
116 actionData.parentBean.addBasicProperty(actionData.propertyName, finalBody);
117 break;
118 default:
119 addError("Unexpected aggregationType " + actionData.aggregationType);
120 }
121 }
122
123 public void doComplex(ModelInterpretationContext interpretationContext, ComponentModel componentModel,
124 ImplicitModelDataForComplexProperty imdForComplexProperty) {
125
126 String propertyClassName = componentModel.getClassName();
127
128 String substPropertyClassName = interpretationContext.subst(propertyClassName);
129
130 String fqcn = interpretationContext.getImport(substPropertyClassName);
131
132 Class<?> propertyClass = null;
133 try {
134
135 if (!OptionHelper.isNullOrEmptyOrAllSpaces(fqcn)) {
136 propertyClass = Loader.loadClass(fqcn, context);
137 } else {
138
139 PropertySetter parentBean = imdForComplexProperty.parentBean;
140 propertyClass = parentBean.getClassNameViaImplicitRules(imdForComplexProperty.propertyName,
141 imdForComplexProperty.getAggregationType(), interpretationContext.getDefaultNestedComponentRegistry());
142 }
143
144 if (propertyClass == null) {
145 imdForComplexProperty.inError = true;
146 String errMsg = "Could not find an appropriate class for property [" + componentModel.getTag() + "]";
147 addError(errMsg);
148 return;
149 }
150
151 if (OptionHelper.isNullOrEmptyOrAllSpaces(fqcn)) {
152 addInfo("Assuming default type [" + propertyClass.getName() + "] for [" + componentModel.getTag()
153 + "] property");
154 }
155
156
157
158 Class<?> expectedPropertyType = imdForComplexProperty.getExpectedPropertyType();
159
160 Object object = OptionHelper.instantiateClassWithSuperclassRestriction(propertyClass, expectedPropertyType);
161
162 imdForComplexProperty.setNestedComplexProperty(object);
163
164
165 if (imdForComplexProperty.getNestedComplexProperty() instanceof ContextAware) {
166 ((ContextAware) imdForComplexProperty.getNestedComplexProperty()).setContext(this.context);
167 }
168
169
170 interpretationContext.pushObject(imdForComplexProperty.getNestedComplexProperty());
171
172 } catch (Exception oops) {
173 imdForComplexProperty.inError = true;
174 String msg = "Could not create component [" + componentModel.getTag() + "] of type [" + fqcn + "]";
175 addError(msg, oops);
176 }
177 }
178
179 @Override
180 public void postHandle(ModelInterpretationContext intercon, Model model) {
181 if (inError) {
182 return;
183 }
184
185 if(implicitModelData == null)
186 return;
187
188
189
190 if(implicitModelData.inError) {
191 return;
192 }
193 if (implicitModelData instanceof ImplicitModelDataForComplexProperty) {
194 postHandleComplex(intercon, model, (ImplicitModelDataForComplexProperty) implicitModelData);
195 }
196
197 }
198
199 private void postHandleComplex(ModelInterpretationContext mic, Model model,
200 ImplicitModelDataForComplexProperty imdComplex) {
201
202 PropertySetter nestedBean = new PropertySetter(beanDescriptionCache,
203 imdComplex.getNestedComplexProperty());
204 nestedBean.setContext(context);
205
206
207 if (nestedBean.computeAggregationType(ModelConstants.PARENT_PROPPERTY_KEY) == AggregationType.AS_COMPLEX_PROPERTY) {
208 nestedBean.setComplexProperty(ModelConstants.PARENT_PROPPERTY_KEY, imdComplex.parentBean.getObj());
209 }
210
211
212
213 Object nestedComplexProperty = imdComplex.getNestedComplexProperty();
214 if (NoAutoStartUtil.shouldBeStarted(nestedComplexProperty)) {
215 ((LifeCycle) nestedComplexProperty).start();
216 }
217
218 Object o = mic.peekObject();
219
220 if (o != imdComplex.getNestedComplexProperty()) {
221 addError("The object on the top the of the stack is not the component pushed earlier.");
222 } else {
223 mic.popObject();
224
225 switch (imdComplex.aggregationType) {
226 case AS_COMPLEX_PROPERTY:
227 imdComplex.parentBean.setComplexProperty(model.getTag(), imdComplex.getNestedComplexProperty());
228
229 break;
230 case AS_COMPLEX_PROPERTY_COLLECTION:
231 imdComplex.parentBean.addComplexProperty(model.getTag(), imdComplex.getNestedComplexProperty());
232 break;
233 default:
234 addError("Unexpected aggregationType " + imdComplex.aggregationType);
235 }
236 }
237 }
238
239 }