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.spi.ContextAware;
20 import ch.qos.logback.core.spi.LifeCycle;
21 import ch.qos.logback.core.util.ContainmentType;
22 import ch.qos.logback.core.util.Loader;
23 import ch.qos.logback.core.util.OptionHelper;
24 import ch.qos.logback.core.util.PropertySetter;
25
26
27
28
29
30
31
32 public class NestedComponentIA extends ImplicitAction {
33
34
35
36
37
38
39
40
41 Stack<ImplicitActionData> actionDataStack = new Stack<ImplicitActionData>();
42
43 public boolean isApplicable(Pattern pattern, Attributes attributes,
44 InterpretationContext ec) {
45
46 String nestedElementTagName = pattern.peekLast();
47
48
49 if (ec.isEmpty()) {
50 return false;
51 }
52
53 Object o = ec.peekObject();
54 PropertySetter parentBean = new PropertySetter(o);
55 parentBean.setContext(context);
56
57 ContainmentType containmentType = parentBean
58 .canContainComponent(nestedElementTagName);
59
60 switch (containmentType) {
61 case NOT_FOUND:
62 case AS_SINGLE_PROPERTY:
63 case AS_PROPERTY_COLLECTION:
64 return false;
65
66
67 case AS_COMPONENT_COLLECTION:
68 case AS_SINGLE_COMPONENT:
69
70 ImplicitActionData ad = new ImplicitActionData(parentBean,
71 containmentType);
72 actionDataStack.push(ad);
73
74 return true;
75 default:
76 addError("PropertySetter.canContainComponent returned " + containmentType);
77 return false;
78 }
79 }
80
81 public void begin(InterpretationContext ec, String localName,
82 Attributes attributes) {
83
84
85 ImplicitActionData actionData = (ImplicitActionData) actionDataStack.peek();
86
87 String className = attributes.getValue(CLASS_ATTRIBUTE);
88
89
90 className = ec.subst(className);
91
92 if (OptionHelper.isEmpty(className)) {
93 actionData.inError = true;
94 String errMsg = "No class name attribute in [" + localName + "]";
95 addError(errMsg);
96
97 return;
98 }
99
100 try {
101
102
103
104
105
106
107 actionData.nestedComponent = Loader.loadClass(className, context).newInstance();
108
109
110 if (actionData.nestedComponent instanceof ContextAware) {
111 ((ContextAware) actionData.nestedComponent).setContext(this.context);
112 }
113
114 addInfo("Pushing component [" + localName
115 + "] on top of the object stack.");
116 ec.pushObject(actionData.nestedComponent);
117 } catch (Exception oops) {
118 actionData.inError = true;
119 String msg = "Could not create component [" + localName + "] of type ["
120 + className + "]";
121 addError(msg, oops);
122 }
123 }
124
125 public void end(InterpretationContext ec, String tagName) {
126
127
128
129 ImplicitActionData actionData = (ImplicitActionData) actionDataStack.pop();
130
131 if (actionData.inError) {
132 return;
133 }
134
135 PropertySetter nestedBean = new PropertySetter(actionData.nestedComponent);
136 nestedBean.setContext(context);
137
138 if (nestedBean.canContainComponent("parent") == ContainmentType.AS_SINGLE_COMPONENT) {
139 nestedBean.setComponent("parent", actionData.parentBean.getObj());
140 }
141 if (actionData.nestedComponent instanceof LifeCycle) {
142 ((LifeCycle) actionData.nestedComponent).start();
143 }
144
145 Object o = ec.peekObject();
146
147 if (o != actionData.nestedComponent) {
148 addError("The object on the top the of the stack is not the component pushed earlier.");
149 } else {
150
151 ec.popObject();
152
153
154 switch (actionData.containmentType) {
155 case AS_SINGLE_COMPONENT:
156
157
158
159 actionData.parentBean.setComponent(tagName, actionData.nestedComponent);
160
161 break;
162 case AS_COMPONENT_COLLECTION:
163
164
165
166 actionData.parentBean.addComponent(tagName, actionData.nestedComponent);
167
168 break;
169 }
170 }
171 }
172
173 }