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