KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tapestry > bean > BeanProvider


1 // Copyright 2004, 2005 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 JavaDoc;
18 import java.util.Collections JavaDoc;
19 import java.util.HashMap JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.Set JavaDoc;
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.event.PageDetachListener;
34 import org.apache.tapestry.event.PageEndRenderListener;
35 import org.apache.tapestry.event.PageEvent;
36 import org.apache.tapestry.spec.BeanLifecycle;
37 import org.apache.tapestry.spec.IBeanSpecification;
38 import org.apache.tapestry.spec.IComponentSpecification;
39
40 /**
41  * Basic implementation of the {@link IBeanProvider} interface.
42  *
43  * @author Howard Lewis Ship
44  * @since 1.0.4
45  */

46
47 public class BeanProvider implements IBeanProvider, PageDetachListener, PageEndRenderListener
48 {
49     private static final Log LOG = LogFactory.getLog(BeanProvider.class);
50
51     /**
52      * Indicates whether this instance has been registered with its page as a PageDetachListener.
53      * Registration only occurs the first time a bean with lifecycle REQUEST is instantiated.
54      */

55
56     private boolean _registeredForDetach = false;
57
58     /**
59      * Indicates whether this instance has been registered as a render listener with the page.
60      */

61
62     private boolean _registeredForRender = false;
63
64     /**
65      * The component for which beans are being created and tracked.
66      */

67
68     private IComponent _component;
69
70     /**
71      * Used for instantiating classes.
72      */

73
74     private ClassResolver _resolver;
75
76     /**
77      * Map of beans, keyed on name.
78      */

79
80     private Map JavaDoc _beans;
81
82     /**
83      * Set of bean names provided by this provider.
84      *
85      * @since 2.2
86      */

87
88     private Set JavaDoc _beanNames;
89
90     public BeanProvider(IComponent component)
91     {
92         _component = component;
93         IEngine engine = component.getPage().getEngine();
94         _resolver = engine.getClassResolver();
95
96         if (LOG.isDebugEnabled())
97             LOG.debug("Created BeanProvider for " + component);
98
99     }
100
101     /** @since 1.0.6 * */
102
103     public Collection JavaDoc getBeanNames()
104     {
105         if (_beanNames == null)
106         {
107             Collection JavaDoc c = _component.getSpecification().getBeanNames();
108
109             if (c == null || c.isEmpty())
110                 _beanNames = Collections.EMPTY_SET;
111             else
112                 _beanNames = Collections.unmodifiableSet(new HashSet JavaDoc(c));
113         }
114
115         return _beanNames;
116     }
117
118     /**
119      * @since 1.0.5
120      */

121
122     public IComponent getComponent()
123     {
124         return _component;
125     }
126
127     public Object JavaDoc getBean(String JavaDoc name)
128     {
129         if (LOG.isDebugEnabled())
130             LOG.debug("getBean(" + name + ")");
131
132         Object JavaDoc bean = null;
133
134         if (_beans != null)
135             bean = _beans.get(name);
136
137         if (bean != null)
138             return bean;
139
140         IBeanSpecification spec = _component.getSpecification().getBeanSpecification(name);
141
142         if (spec == null)
143             throw new ApplicationRuntimeException(BeanMessages.beanNotDefined(_component, name));
144
145         bean = instantiateBean(name, spec);
146
147         BeanLifecycle lifecycle = spec.getLifecycle();
148
149         if (lifecycle == BeanLifecycle.NONE)
150             return bean;
151
152         if (_beans == null)
153             _beans = new HashMap JavaDoc();
154
155         _beans.put(name, bean);
156
157         // The first time in a request that a REQUEST lifecycle bean is created,
158
// register with the page to be notified at the end of the
159
// request cycle.
160

161         if (lifecycle == BeanLifecycle.REQUEST && !_registeredForDetach)
162         {
163             _component.getPage().addPageDetachListener(this);
164             _registeredForDetach = true;
165         }
166
167         if (lifecycle == BeanLifecycle.RENDER && !_registeredForRender)
168         {
169             _component.getPage().addPageEndRenderListener(this);
170             _registeredForRender = true;
171         }
172
173         // No need to register if a PAGE lifecycle bean; those can stick around
174
// forever.
175

176         return bean;
177     }
178
179     private Object JavaDoc instantiateBean(String JavaDoc beanName, IBeanSpecification spec)
180     {
181         String JavaDoc className = spec.getClassName();
182         Object JavaDoc bean = null;
183
184         if (LOG.isDebugEnabled())
185             LOG.debug("Instantiating instance of " + className);
186
187         // Do it the hard way!
188

189         try
190         {
191             Class JavaDoc beanClass = _resolver.findClass(className);
192
193             bean = beanClass.newInstance();
194         }
195         catch (Exception JavaDoc ex)
196         {
197             throw new ApplicationRuntimeException(BeanMessages.instantiationError(
198                     beanName,
199                     _component,
200                     className,
201                     ex), spec.getLocation(), ex);
202         }
203
204         // OK, have the bean, have to initialize it.
205

206         List JavaDoc initializers = spec.getInitializers();
207
208         if (initializers == null)
209             return bean;
210
211         Iterator JavaDoc i = initializers.iterator();
212         while (i.hasNext())
213         {
214             IBeanInitializer iz = (IBeanInitializer) i.next();
215
216             if (LOG.isDebugEnabled())
217                 LOG.debug("Initializing property " + iz.getPropertyName());
218
219             iz.setBeanProperty(this, bean);
220         }
221
222         return bean;
223     }
224
225     /**
226      * Removes all beans with the REQUEST lifecycle. Beans with the PAGE lifecycle stick around, and
227      * beans with no lifecycle were never stored in the first place.
228      */

229
230     public void pageDetached(PageEvent event)
231     {
232         removeBeans(BeanLifecycle.REQUEST);
233     }
234
235     /**
236      * Removes any beans with the specified lifecycle.
237      *
238      * @since 2.2
239      */

240
241     private void removeBeans(BeanLifecycle lifecycle)
242     {
243         if (_beans == null)
244             return;
245
246         IComponentSpecification spec = null;
247
248         Iterator JavaDoc i = _beans.entrySet().iterator();
249         while (i.hasNext())
250         {
251             Map.Entry JavaDoc e = (Map.Entry JavaDoc) i.next();
252             String JavaDoc name = (String JavaDoc) e.getKey();
253
254             if (spec == null)
255                 spec = _component.getSpecification();
256
257             IBeanSpecification s = spec.getBeanSpecification(name);
258
259             if (s.getLifecycle() == lifecycle)
260             {
261                 Object JavaDoc bean = e.getValue();
262
263                 if (LOG.isDebugEnabled())
264                     LOG.debug("Removing " + lifecycle.getName() + " bean " + name + ": " + bean);
265
266                 i.remove();
267             }
268         }
269     }
270
271     /** @since 1.0.8 * */
272
273     public ClassResolver getClassResolver()
274     {
275         return _resolver;
276     }
277
278     /** @since 2.2 * */
279
280     public void pageEndRender(PageEvent event)
281     {
282         removeBeans(BeanLifecycle.RENDER);
283     }
284
285     /** @since 2.2 * */
286
287     public boolean canProvideBean(String JavaDoc name)
288     {
289         return getBeanNames().contains(name);
290     }
291
292 }
Popular Tags