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
131 ec.pushObject(actionData.getNestedComplexProperty());
132
133 } catch (Exception oops) {
134 actionData.inError = true;
135 String msg = "Could not create component [" + localName + "] of type ["
136 + className + "]";
137 addError(msg, oops);
138 }
139
140 }
141
142 public void end(InterpretationContext ec, String tagName) {
143
144
145
146 IADataForComplexProperty actionData = (IADataForComplexProperty) actionDataStack
147 .pop();
148
149 if (actionData.inError) {
150 return;
151 }
152
153 PropertySetter nestedBean = new PropertySetter(actionData
154 .getNestedComplexProperty());
155 nestedBean.setContext(context);
156
157
158 if (nestedBean.computeAggregationType("parent") == AggregationType.AS_COMPLEX_PROPERTY) {
159 nestedBean.setComplexProperty("parent", actionData.parentBean.getObj());
160 }
161
162
163
164 Object nestedComplexProperty = actionData.getNestedComplexProperty();
165 if (nestedComplexProperty instanceof LifeCycle
166 && NoAutoStartUtil.notMarkedWithNoAutoStart(nestedComplexProperty)) {
167 ((LifeCycle) nestedComplexProperty).start();
168 }
169
170 Object o = ec.peekObject();
171
172 if (o != actionData.getNestedComplexProperty()) {
173 addError("The object on the top the of the stack is not the component pushed earlier.");
174 } else {
175 ec.popObject();
176
177 switch (actionData.aggregationType) {
178 case AS_COMPLEX_PROPERTY:
179 actionData.parentBean.setComplexProperty(tagName, actionData
180 .getNestedComplexProperty());
181
182 break;
183 case AS_COMPLEX_PROPERTY_COLLECTION:
184 actionData.parentBean.addComplexProperty(tagName, actionData
185 .getNestedComplexProperty());
186
187 break;
188 }
189 }
190 }
191
192 }