Source code: org/apache/tapestry/bean/BeanProvider.java
1 /* $$ Clover has instrumented this file $$ */// Copyright 2004 The Apache Software Foundation
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package org.apache.tapestry.bean;
16
17 import java.util.Collection;
18 import java.util.Collections;
19 import java.util.HashMap;
20 import java.util.HashSet;
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.hivemind.ApplicationRuntimeException;
29 import org.apache.hivemind.ClassResolver;
30 import org.apache.tapestry.IBeanProvider;
31 import org.apache.tapestry.IComponent;
32 import org.apache.tapestry.IEngine;
33 import org.apache.tapestry.Tapestry;
34 import org.apache.tapestry.event.PageDetachListener;
35 import org.apache.tapestry.event.PageEvent;
36 import org.apache.tapestry.event.PageRenderListener;
37 import org.apache.tapestry.spec.BeanLifecycle;
38 import org.apache.tapestry.spec.IBeanSpecification;
39 import org.apache.tapestry.spec.IComponentSpecification;
40
41 /**
42 * Basic implementation of the {@link IBeanProvider} interface.
43 *
44 * @author Howard Lewis Ship
45 * @since 1.0.4
46 **/
47
48 public class BeanProvider implements IBeanProvider, PageDetachListener, PageRenderListener
49 {public static com.cortexeb.tools.clover.d __CLOVER_42_0 = com.cortexeb.tools.clover.aq.getRecorder(new char[] {67,58,92,119,111,114,107,115,112,97,99,101,92,106,97,107,97,114,116,97,45,116,97,112,101,115,116,114,121,92,102,114,97,109,101,119,111,114,107,92,116,97,114,103,101,116,92,99,108,111,118,101,114,45,100,98},1096998272901L);
50 private static final Log LOG = LogFactory.getLog(BeanProvider.class);
51
52 /**
53 * Indicates whether this instance has been registered with its
54 * page as a PageDetachListener. Registration only occurs
55 * the first time a bean with lifecycle REQUEST is instantiated.
56 *
57 **/
58
59 private boolean _registeredForDetach = false;
60
61 /**
62 * Indicates whether this instance has been registered as a render
63 * listener with the page.
64 *
65 **/
66
67 private boolean _registeredForRender = false;
68
69 /**
70 * The component for which beans are being created and tracked.
71 *
72 **/
73
74 private IComponent _component;
75
76 /**
77 * Used for instantiating classes.
78 *
79 **/
80
81 private ClassResolver _resolver;
82
83 /**
84 * Map of beans, keyed on name.
85 *
86 **/
87
88 private Map _beans;
89
90 /**
91 * Set of bean names provided by this provider.
92 *
93 * @since 2.2
94 *
95 **/
96
97 private Set _beanNames;
98
99 public BeanProvider(IComponent component)
100 {try { __CLOVER_42_0.M[258]++;
101 __CLOVER_42_0.S[1012]++;this._component = component;
102 __CLOVER_42_0.S[1013]++;IEngine engine = component.getPage().getEngine();
103 __CLOVER_42_0.S[1014]++;_resolver = engine.getClassResolver();
104
105 __CLOVER_42_0.S[1015]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_42_0.CT[194] != 0)) || (++__CLOVER_42_0.CF[194] == 0))){
106 __CLOVER_42_0.S[1016]++;LOG.debug("Created BeanProvider for " + component);}
107
108 } finally { }}
109
110 /** @since 1.0.6 **/
111
112 public Collection getBeanNames()
113 {try { __CLOVER_42_0.M[259]++;
114 __CLOVER_42_0.S[1017]++;if ((((_beanNames == null) && (++__CLOVER_42_0.CT[195] != 0)) || (++__CLOVER_42_0.CF[195] == 0))){
115 {
116 __CLOVER_42_0.S[1018]++;Collection c = _component.getSpecification().getBeanNames();
117
118 __CLOVER_42_0.S[1019]++;if ((((c == null || c.isEmpty()) && (++__CLOVER_42_0.CT[196] != 0)) || (++__CLOVER_42_0.CF[196] == 0))){
119 __CLOVER_42_0.S[1020]++;_beanNames = Collections.EMPTY_SET;}
120 else{
121 __CLOVER_42_0.S[1021]++;_beanNames = Collections.unmodifiableSet(new HashSet(c));}
122 }}
123
124 __CLOVER_42_0.S[1022]++;return _beanNames;
125 } finally { }}
126
127 /**
128 * @since 1.0.5
129 *
130 **/
131
132 public IComponent getComponent()
133 {try { __CLOVER_42_0.M[260]++;
134 __CLOVER_42_0.S[1023]++;return _component;
135 } finally { }}
136
137 public Object getBean(String name)
138 {try { __CLOVER_42_0.M[261]++;
139 __CLOVER_42_0.S[1024]++;Object bean = null;
140
141 __CLOVER_42_0.S[1025]++;if ((((_beans != null) && (++__CLOVER_42_0.CT[197] != 0)) || (++__CLOVER_42_0.CF[197] == 0))){
142 __CLOVER_42_0.S[1026]++;bean = _beans.get(name);}
143
144 __CLOVER_42_0.S[1027]++;if ((((bean != null) && (++__CLOVER_42_0.CT[198] != 0)) || (++__CLOVER_42_0.CF[198] == 0))){
145 __CLOVER_42_0.S[1028]++;return bean;}
146
147 __CLOVER_42_0.S[1029]++;IBeanSpecification spec = _component.getSpecification().getBeanSpecification(name);
148
149 __CLOVER_42_0.S[1030]++;if ((((spec == null) && (++__CLOVER_42_0.CT[199] != 0)) || (++__CLOVER_42_0.CF[199] == 0))){
150 __CLOVER_42_0.S[1031]++;throw new ApplicationRuntimeException(
151 Tapestry.format(
152 "BeanProvider.bean-not-defined",
153 _component.getExtendedId(),
154 name));}
155
156 __CLOVER_42_0.S[1032]++;bean = instantiateBean(name, spec);
157
158 __CLOVER_42_0.S[1033]++;BeanLifecycle lifecycle = spec.getLifecycle();
159
160 __CLOVER_42_0.S[1034]++;if ((((lifecycle == BeanLifecycle.NONE) && (++__CLOVER_42_0.CT[200] != 0)) || (++__CLOVER_42_0.CF[200] == 0))){
161 __CLOVER_42_0.S[1035]++;return bean;}
162
163 __CLOVER_42_0.S[1036]++;if ((((_beans == null) && (++__CLOVER_42_0.CT[201] != 0)) || (++__CLOVER_42_0.CF[201] == 0))){
164 __CLOVER_42_0.S[1037]++;_beans = new HashMap();}
165
166 __CLOVER_42_0.S[1038]++;_beans.put(name, bean);
167
168 // The first time in a request that a REQUEST lifecycle bean is created,
169 // register with the page to be notified at the end of the
170 // request cycle.
171
172 __CLOVER_42_0.S[1039]++;if ((((lifecycle == BeanLifecycle.REQUEST && !_registeredForDetach) && (++__CLOVER_42_0.CT[202] != 0)) || (++__CLOVER_42_0.CF[202] == 0))){
173 {
174 __CLOVER_42_0.S[1040]++;_component.getPage().addPageDetachListener(this);
175 __CLOVER_42_0.S[1041]++;_registeredForDetach = true;
176 }}
177
178 __CLOVER_42_0.S[1042]++;if ((((lifecycle == BeanLifecycle.RENDER && !_registeredForRender) && (++__CLOVER_42_0.CT[203] != 0)) || (++__CLOVER_42_0.CF[203] == 0))){
179 {
180 __CLOVER_42_0.S[1043]++;_component.getPage().addPageRenderListener(this);
181 __CLOVER_42_0.S[1044]++;_registeredForRender = true;
182 }}
183
184 // No need to register if a PAGE lifecycle bean; those can stick around
185 // forever.
186
187 __CLOVER_42_0.S[1045]++;return bean;
188 } finally { }}
189
190 private Object instantiateBean(String beanName, IBeanSpecification spec)
191 {try { __CLOVER_42_0.M[262]++;
192 __CLOVER_42_0.S[1046]++;String className = spec.getClassName();
193 __CLOVER_42_0.S[1047]++;Object bean = null;
194
195 __CLOVER_42_0.S[1048]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_42_0.CT[204] != 0)) || (++__CLOVER_42_0.CF[204] == 0))){
196 __CLOVER_42_0.S[1049]++;LOG.debug("Instantiating instance of " + className);}
197
198 // Do it the hard way!
199
200 __CLOVER_42_0.S[1050]++;try
201 {
202 __CLOVER_42_0.S[1051]++;Class beanClass = _resolver.findClass(className);
203
204 __CLOVER_42_0.S[1052]++;bean = beanClass.newInstance();
205 }
206 catch (Exception ex)
207 {
208
209 __CLOVER_42_0.S[1053]++;throw new ApplicationRuntimeException(
210 Tapestry.format(
211 "BeanProvider.instantiation-error",
212 new Object[] {
213 beanName,
214 _component.getExtendedId(),
215 className,
216 ex.getMessage()}),
217 spec.getLocation(),
218 ex);
219 }
220
221 // OK, have the bean, have to initialize it.
222
223 __CLOVER_42_0.S[1054]++;List initializers = spec.getInitializers();
224
225 __CLOVER_42_0.S[1055]++;if ((((initializers == null) && (++__CLOVER_42_0.CT[205] != 0)) || (++__CLOVER_42_0.CF[205] == 0))){
226 __CLOVER_42_0.S[1056]++;return bean;}
227
228 __CLOVER_42_0.S[1057]++;Iterator i = initializers.iterator();
229 __CLOVER_42_0.S[1058]++;while ((((i.hasNext()) && (++__CLOVER_42_0.CT[206] != 0)) || (++__CLOVER_42_0.CF[206] == 0))){
230 {
231 __CLOVER_42_0.S[1059]++;IBeanInitializer iz = (IBeanInitializer) i.next();
232
233 __CLOVER_42_0.S[1060]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_42_0.CT[207] != 0)) || (++__CLOVER_42_0.CF[207] == 0))){
234 __CLOVER_42_0.S[1061]++;LOG.debug("Initializing property " + iz.getPropertyName());}
235
236 __CLOVER_42_0.S[1062]++;iz.setBeanProperty(this, bean);
237 }}
238
239 __CLOVER_42_0.S[1063]++;return bean;
240 } finally { }}
241
242 /**
243 * Removes all beans with the REQUEST lifecycle. Beans with
244 * the PAGE lifecycle stick around, and beans with no lifecycle
245 * were never stored in the first place.
246 *
247 **/
248
249 public void pageDetached(PageEvent event)
250 {try { __CLOVER_42_0.M[263]++;
251 __CLOVER_42_0.S[1064]++;removeBeans(BeanLifecycle.REQUEST);
252 } finally { }}
253
254 /**
255 * Removes any beans with the specified lifecycle.
256 *
257 * @since 2.2
258 *
259 **/
260
261 private void removeBeans(BeanLifecycle lifecycle)
262 {try { __CLOVER_42_0.M[264]++;
263 __CLOVER_42_0.S[1065]++;if ((((_beans == null) && (++__CLOVER_42_0.CT[208] != 0)) || (++__CLOVER_42_0.CF[208] == 0))){
264 __CLOVER_42_0.S[1066]++;return;}
265
266 __CLOVER_42_0.S[1067]++;IComponentSpecification spec = null;
267
268 __CLOVER_42_0.S[1068]++;Iterator i = _beans.entrySet().iterator();
269 __CLOVER_42_0.S[1069]++;while ((((i.hasNext()) && (++__CLOVER_42_0.CT[209] != 0)) || (++__CLOVER_42_0.CF[209] == 0))){
270 {
271 __CLOVER_42_0.S[1070]++;Map.Entry e = (Map.Entry) i.next();
272 __CLOVER_42_0.S[1071]++;String name = (String) e.getKey();
273
274 __CLOVER_42_0.S[1072]++;if ((((spec == null) && (++__CLOVER_42_0.CT[210] != 0)) || (++__CLOVER_42_0.CF[210] == 0))){
275 __CLOVER_42_0.S[1073]++;spec = _component.getSpecification();}
276
277 __CLOVER_42_0.S[1074]++;IBeanSpecification s = spec.getBeanSpecification(name);
278
279 __CLOVER_42_0.S[1075]++;if ((((s.getLifecycle() == lifecycle) && (++__CLOVER_42_0.CT[211] != 0)) || (++__CLOVER_42_0.CF[211] == 0))){
280 {
281 __CLOVER_42_0.S[1076]++;Object bean = e.getValue();
282
283 __CLOVER_42_0.S[1077]++;if ((((LOG.isDebugEnabled()) && (++__CLOVER_42_0.CT[212] != 0)) || (++__CLOVER_42_0.CF[212] == 0))){
284 __CLOVER_42_0.S[1078]++;LOG.debug("Removing " + lifecycle.getName() + " bean " + name + ": " + bean);}
285
286 __CLOVER_42_0.S[1079]++;i.remove();
287 }}
288 }}
289 } finally { }}
290
291 /** @since 1.0.8 **/
292
293 public ClassResolver getClassResolver()
294 {try { __CLOVER_42_0.M[265]++;
295 __CLOVER_42_0.S[1080]++;return _resolver;
296 } finally { }}
297
298 /** @since 2.2 **/
299
300 public void pageBeginRender(PageEvent event)
301 {try { __CLOVER_42_0.M[266]++;
302 } finally { }}
303
304 /** @since 2.2 **/
305
306 public void pageEndRender(PageEvent event)
307 {try { __CLOVER_42_0.M[267]++;
308 __CLOVER_42_0.S[1081]++;removeBeans(BeanLifecycle.RENDER);
309 } finally { }}
310
311 /** @since 2.2 **/
312
313 public boolean canProvideBean(String name)
314 {try { __CLOVER_42_0.M[268]++;
315 __CLOVER_42_0.S[1082]++;return getBeanNames().contains(name);
316 } finally { }}
317
318 }