1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.joran.action;
15
16 import java.util.Stack;
17
18 import org.xml.sax.Attributes;
19
20 import ch.qos.logback.core.joran.spi.InterpretationContext;
21 import ch.qos.logback.core.joran.spi.NoAutoStartUtil;
22 import ch.qos.logback.core.joran.spi.Pattern;
23 import ch.qos.logback.core.joran.util.PropertySetter;
24 import ch.qos.logback.core.spi.ContextAware;
25 import ch.qos.logback.core.spi.LifeCycle;
26 import ch.qos.logback.core.util.AggregationType;
27 import ch.qos.logback.core.util.Loader;
28 import ch.qos.logback.core.util.OptionHelper;
29
30
31
32
33
34
35
36 public class NestedComplexPropertyIA extends ImplicitAction {
37
38
39
40
41
42
43
44
45 Stack<IADataForComplexProperty> actionDataStack = new Stack<IADataForComplexProperty>();
46
47 public boolean isApplicable(Pattern pattern, Attributes attributes,
48 InterpretationContext ic) {
49
50 String nestedElementTagName = pattern.peekLast();
51
52
53 if (ic.isEmpty()) {
54 return false;
55 }
56
57 Object o = ic.peekObject();
58 PropertySetter parentBean = new PropertySetter(o);
59 parentBean.setContext(context);
60
61 AggregationType aggregationType = parentBean
62 .computeAggregationType(nestedElementTagName);
63
64 switch (aggregationType) {
65 case NOT_FOUND:
66 case AS_BASIC_PROPERTY:
67 case AS_BASIC_PROPERTY_COLLECTION:
68 return false;
69
70
71 case AS_COMPLEX_PROPERTY_COLLECTION:
72 case AS_COMPLEX_PROPERTY:
73 IADataForComplexProperty ad = new IADataForComplexProperty(parentBean,
74 aggregationType, nestedElementTagName);
75 actionDataStack.push(ad);
76
77 return true;
78 default:
79 addError("PropertySetter.computeAggregationType returned "
80 + aggregationType);
81 return false;
82 }
83 }
84
85 public void begin(InterpretationContext ec, String localName,
86 Attributes attributes) {
87
88
89 IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack
90 .peek();
91
92 String className = attributes.getValue(CLASS_ATTRIBUTE);
93
94 className = ec.subst(className);
95
96 Class componentClass = null;
97 try {
98
99 if (!OptionHelper.isEmpty(className)) {
100 componentClass = Loader.loadClass(className, context);
101 } else {
102
103 PropertySetter parentBean = actionData.parentBean;
104 componentClass = parentBean.getClassNameViaImplicitRules(actionData
105 .getComplexPropertyName(), actionData.getAggregationType(), ec
106 .getDefaultNestedComponentRegistry());
107 }
108
109 if (componentClass == null) {
110 actionData.inError = true;
111 String errMsg = "Could not find an appropriate class for property ["
112 + localName + "]";
113 addError(errMsg);
114 return;
115 }
116
117 if (OptionHelper.isEmpty(className)) {
118 addInfo("Assuming default type [" + componentClass.getName()
119 + "] for [" + localName + "] property");
120 }
121
122 actionData.setNestedComplexProperty(componentClass.newInstance());
123
124
125 if (actionData.getNestedComplexProperty() instanceof ContextAware) {
126 ((ContextAware) actionData.getNestedComplexProperty())
127 .setContext(this.context);
128 }
129
130 addInfo("Pushing component [" + localName
131 + "] on top of the object stack.");
132 ec.pushObject(actionData.getNestedComplexProperty());
133
134 } catch (Exception oops) {
135 actionData.inError = true;
136 String msg = "Could not create component [" + localName + "] of type ["
137 + className + "]";
138 addError(msg, oops);
139 }
140
141 }
142
143 public void end(InterpretationContext ec, String tagName) {
144
145
146
147 IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack
148 .pop();
149
150 if (actionData.inError) {
151 return;
152 }
153
154 PropertySetter nestedBean = new PropertySetter(actionData
155 .getNestedComplexProperty());
156 nestedBean.setContext(context);
157
158
159 if (nestedBean.computeAggregationType("parent") == AggregationType.AS_COMPLEX_PROPERTY) {
160 nestedBean.setComplexProperty("parent", actionData.parentBean.getObj());
161 }
162
163
164
165 Object nestedComplexProperty = actionData.getNestedComplexProperty();
166 if (nestedComplexProperty instanceof LifeCycle
167 && NoAutoStartUtil.notMarkedWithNoAutoStart(nestedComplexProperty)) {
168 ((LifeCycle) nestedComplexProperty).start();
169 }
170
171 Object o = ec.peekObject();
172
173 if (o != actionData.getNestedComplexProperty()) {
174 addError("The object on the top the of the stack is not the component pushed earlier.");
175 } else {
176 ec.popObject();
177
178 switch (actionData.aggregationType) {
179 case AS_COMPLEX_PROPERTY:
180 actionData.parentBean.setComplexProperty(tagName, actionData
181 .getNestedComplexProperty());
182
183 break;
184 case AS_COMPLEX_PROPERTY_COLLECTION:
185 actionData.parentBean.addComplexProperty(tagName, actionData
186 .getNestedComplexProperty());
187
188 break;
189 }
190 }
191 }
192
193 }