KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jfun > yan > spring > Container2ApplicationContext


1 package jfun.yan.spring;
2
3 import java.io.IOException JavaDoc;
4 import java.util.ArrayList JavaDoc;
5 import java.util.Iterator JavaDoc;
6 import java.util.LinkedHashMap JavaDoc;
7 import java.util.Locale JavaDoc;
8 import java.util.Map JavaDoc;
9 import java.util.Set JavaDoc;
10
11 import jfun.yan.Component;
12 import jfun.yan.Container;
13 import jfun.yan.util.ReflectionUtil;
14
15 import org.springframework.beans.BeansException;
16 import org.springframework.beans.factory.BeanCreationException;
17 import org.springframework.beans.factory.BeanFactory;
18 import org.springframework.beans.factory.BeanFactoryUtils;
19 import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
20 import org.springframework.beans.factory.FactoryBean;
21 import org.springframework.beans.factory.ListableBeanFactory;
22 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
23 import org.springframework.context.ApplicationContext;
24 import org.springframework.context.ApplicationEvent;
25 import org.springframework.context.ApplicationEventPublisher;
26 import org.springframework.context.HierarchicalMessageSource;
27 import org.springframework.context.MessageSource;
28 import org.springframework.context.MessageSourceResolvable;
29 import org.springframework.context.NoSuchMessageException;
30 import org.springframework.context.event.ApplicationEventMulticaster;
31 import org.springframework.context.event.SimpleApplicationEventMulticaster;
32 import org.springframework.context.support.AbstractApplicationContext;
33 import org.springframework.core.io.Resource;
34 import org.springframework.core.io.support.ResourcePatternResolver;
35
36 /**
37  * This class adapts a yan Container object
38  * to Spring's ApplicationContext (primarily ListableBeanFactory) interface.
39  * <p>
40  * Many Thanks to spring for making ApplicationContext an interface!
41  * It helped.
42  * </p>
43  * <p>
44  * @author Ben Yu
45  * Nov 16, 2005 11:40:13 PM
46  */

47 public class Container2ApplicationContext implements ListableBeanFactory,
48 ApplicationContext{
49   
50   private final String JavaDoc name;
51   private final long startup_timestamp;
52   private final Container yan;
53   private final MessageSource parent_message_source;
54   private final ResourcePatternResolver resource_loader;
55   private final ApplicationEventPublisher parent_publisher;
56   private static final String JavaDoc prefix = BeanFactory.FACTORY_BEAN_PREFIX;;
57   private MessageSource message_source = null;
58   private ApplicationEventMulticaster multicaster = null;
59   private synchronized MessageSource getMessageSource(){
60     if(message_source!=null) return message_source;
61     final String JavaDoc key = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME;
62     final Class JavaDoc type = yan.getComponentType(key);
63     if(type!=null && MessageSource.class.isAssignableFrom(type)){
64       message_source = (MessageSource)yan.getInstance(key);
65       if (parent_message_source != null && message_source instanceof HierarchicalMessageSource) {
66         HierarchicalMessageSource hms = (HierarchicalMessageSource) message_source;
67         if (hms.getParentMessageSource() == null) {
68           // Only set parent context as parent MessageSource if no parent MessageSource
69
// registered already.
70
hms.setParentMessageSource(parent_message_source);
71         }
72       }
73     }
74     else{
75       return parent_message_source;
76     }
77     return message_source;
78   }
79   private synchronized ApplicationEventMulticaster getApplicationEventMulticaster(){
80     if(multicaster!=null) return multicaster;
81     final String JavaDoc key = AbstractApplicationContext.APPLICATION_EVENT_MULTICASTER_BEAN_NAME;
82     final Class JavaDoc type = yan.getComponentType(key);
83     if(type!=null && ApplicationEventMulticaster.class.isAssignableFrom(type)){
84       multicaster = (ApplicationEventMulticaster)yan.getInstance(key);
85     }
86     else{
87       multicaster = new SimpleApplicationEventMulticaster();
88     }
89     return multicaster;
90   }
91   /**
92    * Create a Container2BeanFactory object.
93    * @param message_source the MessageSource object.
94    * @param resource_loader the ResourcePatternResolver object.
95    * @param publisher the ApplicationEventPublisher object.
96    * @param name the name of the ApplicationContext.
97    * @param startup_timestamp the startup timestamp.
98    * @param yan the yan Container object.
99    */

100   public Container2ApplicationContext(
101       MessageSource message_source, ResourcePatternResolver resource_loader,
102       ApplicationEventPublisher publisher,
103       String JavaDoc name, long startup_timestamp,
104       Container yan
105   )
106   {
107     this.parent_message_source = message_source;
108     this.name = name;
109     this.resource_loader = resource_loader;
110     this.startup_timestamp = startup_timestamp;
111     this.yan = yan;
112     this.parent_publisher = publisher;
113   }
114
115   /**
116    * Get the container in this object.
117    */

118   public Container getContainer() {
119     return yan;
120   }
121
122
123   /**
124    * Get the number of components registered under a string key.
125    */

126   public int getBeanDefinitionCount() {
127     final Set JavaDoc keys = yan.keys();
128     int ret = 0;
129     for(Iterator JavaDoc it=keys.iterator(); it.hasNext();){
130       final Object JavaDoc key = it.next();
131       if(key instanceof String JavaDoc){
132         ret++;
133       }
134     }
135     return ret;
136   }
137
138   /**
139    * Get all the component keys that are of String type.
140    */

141   public String JavaDoc[] getBeanDefinitionNames() {
142     final Set JavaDoc keys = yan.keys();
143     final ArrayList JavaDoc names = new ArrayList JavaDoc();
144     for(Iterator JavaDoc it=keys.iterator(); it.hasNext();){
145       final Object JavaDoc key = it.next();
146       if(key instanceof String JavaDoc){
147         names.add((String JavaDoc)key);
148       }
149     }
150     final String JavaDoc[] ret = new String JavaDoc[names.size()];
151     names.toArray(ret);
152     return ret;
153   }
154
155   /**
156    * retrieves the string keys of all components
157    * whose's static instance type is a subtype of the required type.
158    * <p>
159    * FactoryBean's are not instantiated.
160    * </p>
161    * @param type the type to match. Null indicates all.
162    * @return the keys.
163    */

164   public String JavaDoc[] getBeanDefinitionNames(Class JavaDoc type) {
165     return getBeanNamesForType(type, true, false);
166   }
167   /**
168    * retrieves the string keys of all components
169    * whose's static instance type is a subtype of the required type.
170    * <p>
171    * FactoryBean's are instantiated if necessary to find out the product type.
172    * </p>
173    * @param type the type to match. Null indicates all.
174    * @return the keys.
175    */

176   public String JavaDoc[] getBeanNamesForType(Class JavaDoc type){
177     return getBeanNamesForType(type, true, true);
178   }
179   private interface BeanListener{
180     /**
181      * When a regular bean is found.
182      */

183     void onBean(String JavaDoc key, Component c);
184     /**
185      * When a FactoryBean is instantiated and the product type and singleton mode satisifies the condition.
186      */

187     void onFactoryBean(String JavaDoc key, FactoryBean fb);
188     /**
189      * When a FactoryBean component itself is matched.
190      */

191     void onFactoryBean(String JavaDoc key, Component fbc);
192   }
193   /**
194    * Iterate through the beans for a certain type.
195    * @param type the required type.
196    * @param includePrototypes whether prototype beans are included.
197    * (thread scope singleotn is considered prototype as well because it doesn't guarantee one instance globally).
198    * @param includeFactoryBeans whether we want to instantiate FactoryBean to find out the product type
199    * and the singleton mode.
200    * @param listener the BeanListener object.
201    */

202   private void foreachBean(Class JavaDoc type,
203       boolean includePrototypes, boolean includeFactoryBeans,
204       BeanListener listener){
205     final boolean for_factorybean = isFactoryBeanType(type);
206     for(Iterator JavaDoc it=yan.keys().iterator();it.hasNext();){
207       final Object JavaDoc key = it.next();
208       if(!(key instanceof String JavaDoc)) continue;
209       final jfun.yan.Component c = yan.getComponent(key);
210       final Component fbc = SpringAdapter.getFactoryBeanComponent(c);
211       if(fbc!=null){
212         //I am Factory Bean
213
if(includeFactoryBeans){
214           //attempt to match the FactoryBean result.
215
final FactoryBean fb = (FactoryBean)instantiate(fbc);
216           if(!includePrototypes && !fb.isSingleton()){
217             continue;
218           }
219           final Class JavaDoc fbt = fb.getObjectType();
220           if(type==null || ReflectionUtil.isAssignableFrom(type, fbt)){
221             final String JavaDoc beanname = (String JavaDoc)key;
222             listener.onFactoryBean(beanname, fb);
223             continue;
224           }
225         }
226         if(!includePrototypes && !c.isSingleton()){
227           continue;
228         }
229         if(type==null || for_factorybean){
230           //if searching FactoryBean.class or null, we return the FactoryBean itself.
231
listener.onFactoryBean((String JavaDoc)key, fbc);
232           continue;
233         }
234       }
235       else{
236         if(!includePrototypes && !c.isSingleton()){
237           continue;
238         }
239         if(type==null){
240           listener.onBean((String JavaDoc)key, c);
241           continue;
242         }
243         final Class JavaDoc ctype = c.getType();
244         if(ctype!=null&&ReflectionUtil.isAssignableFrom(type, ctype)){
245           listener.onBean((String JavaDoc)key, c);
246           continue;
247         }
248       }
249     }
250   }
251
252   public String JavaDoc[] getBeanNamesForType(Class JavaDoc type, boolean includePrototypes,
253       boolean includeFactoryBeans){
254     /*
255     final boolean for_factorybean = type!=null&&FactoryBean.class.equals(type);
256     final ArrayList buf = new ArrayList();
257     for(Iterator it=yan.keys().iterator();it.hasNext();){
258       final Object key = it.next();
259       if(!(key instanceof String)) continue;
260       final jfun.yan.Component c = yan.getComponent(key);
261       final Component fbc = SpringAdapter.getFactoryBeanComponent(c);
262       
263       if(fbc!=null){
264         //I am Factory Bean
265         if(includeFactoryBeans){
266           //attempt to match the FactoryBean result.
267           final FactoryBean fb = (FactoryBean)instantiate(fbc);
268           if(!includePrototypes && !fb.isSingleton()){
269             continue;
270           }
271           final Class fbt = fb.getObjectType();
272           if(type==null || ReflectionUtil.isAssignableFrom(type, fbt)){
273             final String beanname = (String)key;
274             buf.add(beanname);
275             continue;
276           }
277         }
278         if(!includePrototypes && !c.isSingleton()){
279           continue;
280         }
281         if(type==null || for_factorybean){
282           //if searching FactoryBean.class or null, we return the FactoryBean itself.
283           buf.add(BeanFactory.FACTORY_BEAN_PREFIX+key);
284           continue;
285         }
286       }
287       else{
288         if(!includePrototypes && !c.isSingleton()){
289           continue;
290         }
291         if(type==null){
292           buf.add(key);
293           continue;
294         }
295         final Class ctype = c.getType();
296         if(ctype!=null&&ReflectionUtil.isAssignableFrom(type, ctype)){
297           buf.add(key);
298           continue;
299         }
300       }
301     }*/

302     final ArrayList JavaDoc buf = new ArrayList JavaDoc();
303     final BeanListener listener = new BeanListener(){
304       public void onBean(String JavaDoc key, Component c) {
305         buf.add(key);
306       }
307       public void onFactoryBean(String JavaDoc key, Component fbc) {
308         buf.add(prefix+key);
309       }
310       public void onFactoryBean(String JavaDoc key, FactoryBean fb) {
311         buf.add(key);
312       }
313     };
314     foreachBean(type, includePrototypes, includeFactoryBeans, listener);
315     final String JavaDoc[] ret = new String JavaDoc[buf.size()];
316     buf.toArray(ret);
317     return ret;
318   }
319   /*
320    * Does this container contains a component with the given name?
321    * @param beanName the name of the component. If it starts with
322    * a "&", as specified by Spring, this "&" is chopped off
323    * before searching.
324    */

325   public boolean containsBeanDefinition(String JavaDoc beanName) {
326     return yan.containsKey(getRealBeanName(beanName));
327   }
328   private static String JavaDoc getRealBeanName(String JavaDoc name){
329     return BeanFactoryUtils.transformedBeanName(name);
330   }
331   
332   private static boolean isFactoryBeanType(Class JavaDoc type){
333     return type!=null && FactoryBean.class.equals(type);
334   }
335   /*
336   private FactoryBean getFactoryBean(Component c){
337     return new Component2FactoryBean(c, yan);
338   }*/

339   private Object JavaDoc instantiate(Component c){
340     return yan.instantiateComponent(c);
341   }
342   /**
343    * Get the (String,Object) map of all components with the given type.
344    * @param type the expected type. If this type is FactoryBean,
345    * the component is adapted to FactoryBean without actually instantiating
346    * instance.
347    * @return the Map object containing component instances (if the type
348    * is not BeanFactory), otherwise BeanFactory objects.
349    */

350   public Map JavaDoc getBeansOfType(Class JavaDoc type) throws BeansException {
351     return getBeansOfType(type, true, true);
352   }
353   /**
354    * Get the (String,Object) map of all components with the given type.
355    * @param type the expected type.
356    * @param includePrototypes Are the components who may not be singletons included?
357    * @param includeFactoryBeans Are FactoryBean objects included?
358    * @return the Map object containing component instances.
359    */

360   public Map JavaDoc getBeansOfType(Class JavaDoc type, boolean includePrototypes,
361       boolean includeFactoryBeans) throws BeansException {
362     /*
363     final String prefix = BeanFactory.FACTORY_BEAN_PREFIX;
364     final Map result = new LinkedHashMap();
365     if(isFactoryBeanType(type)){
366       for(Iterator it=yan.keys().iterator();it.hasNext();){
367         final Object key = it.next();
368         if(!(key instanceof String))
369           continue;
370         final String beanname = (String)key;
371         final Component c = yan.getComponent(key);
372         if(!includePrototypes && !c.isSingleton())
373           continue;
374         final Component fbc = SpringAdapter.getFactoryBeanComponent(c);
375         if(fbc!=null){
376           result.put(beanname, yan.instantiateComponent(fbc));
377         }
378       }
379     }
380     else{
381       for(Iterator it=yan.keys().iterator();it.hasNext();){
382         final Object key = it.next();
383         if(!(key instanceof String))
384           continue;
385         final Component c = yan.getComponent(key);
386         if(!includePrototypes && !c.isSingleton())
387           continue;
388         final Class ctype = c.getType();
389         if(ctype!=null && ReflectionUtil.isAssignableFrom(type, ctype)){
390           result.put(key, instantiate(c));
391         }
392         else if(includeFactoryBeans){
393           final Component fbc = SpringAdapter.getFactoryBeanComponent(c);
394           if(fbc!=null){
395             final FactoryBean fb = (FactoryBean)yan.instantiateComponent(fbc);
396             if(ReflectionUtil.isAssignableFrom(type, fb.getObjectType())){
397               final String beanname = (String)key;
398               try{
399                 result.put(beanname, fb.getObject());
400               }
401               catch(RuntimeException e){
402                 throw e;
403               }
404               catch(Error e){
405                 throw e;
406               }
407               catch(Exception e){
408                 throw new BeanCreationException((String)key, "FactoryBean failed", e);
409               }
410             }
411           }
412         }
413       }
414     }
415     return result;*/

416     final Map JavaDoc result = new LinkedHashMap JavaDoc();
417     final BeanListener listener = new BeanListener(){
418       public void onBean(String JavaDoc key, Component c) {
419         result.put(key, instantiate(c));
420       }
421       public void onFactoryBean(String JavaDoc key, Component fbc) {
422         result.put(prefix+key, instantiate(fbc));
423       }
424       public void onFactoryBean(String JavaDoc key, FactoryBean fb) {
425         result.put(key, instantiate(key, fb));
426       }
427     };
428     return result;
429   }
430   private Component findComponent(String JavaDoc name){
431     final Component c = yan.getComponent(name);
432     if(c==null){
433       throw new NoSuchBeanDefinitionException(name, "bean "+name+" not found.");
434     }
435     return c;
436   }
437   private Component getComponent(String JavaDoc name){
438     return findComponent(BeanFactoryUtils.transformedBeanName(name));
439   }
440   /**
441    * Get a bean object.
442    * @param name the name of the component.
443    * If the name starts with a "&", as specified by Spring,
444    * a FactoryBean object is returned corresponding to the component,
445    * otherwise the component itself is instantiated.
446    */

447   public Object JavaDoc getBean(final String JavaDoc name) throws BeansException {
448     /*
449     if(BeanFactoryUtils.isFactoryDereference(name)){
450      final String factoryname = BeanFactoryUtils.transformedBeanName(name);
451      return getFactoryBean(findComponent(factoryname));
452     }
453     else{
454      return instantiate(findComponent(name));
455     }*/

456     return getBean(name, null);
457   }
458
459   /**
460    * Get a bean object.
461    * @param beanname the name of the component.
462    * If the name starts with a "&", as specified by Spring,
463    * a FactoryBean object is returned corresponding to the component,
464    * otherwise the component itself is instantiated.
465    * @param requiredType the expecting type. If the name starts with
466    * a "&", as specified by Spring convention, the type has to be
467    * either null or FactoryBean or a super type of FactoryBean.
468    * And in that case, a FactoryBean object is returned.
469    * If the name is a regular bean name, the corresponding component
470    * is instantiated.
471    */

472   public Object JavaDoc getBean(final String JavaDoc beanname, Class JavaDoc requiredType) throws BeansException {
473     if(BeanFactoryUtils.isFactoryDereference(beanname)){
474       //return FactoryBean
475
final String JavaDoc factoryname = BeanFactoryUtils.transformedBeanName(beanname);
476       final Component c = findComponent(factoryname);
477       final Component fbc = SpringAdapter.getFactoryBeanComponent(c);
478       if(fbc!=null){
479         throw new NoSuchBeanDefinitionException(beanname,
480             "FactoryBean "+factoryname+" not found.");
481       }
482       final Object JavaDoc result = instantiate(fbc);
483       checkBeanInstanceType(beanname, requiredType, result);
484       return result;
485     }
486     else{
487       final Component c = findComponent(beanname);
488       final Component fbc = SpringAdapter.getFactoryBeanComponent(c);
489       if(requiredType==null){
490         return instantiate(c);
491       }
492       if(fbc!=null){
493         final FactoryBean fb = (FactoryBean)instantiate(fbc);
494         final Class JavaDoc ctype = fb.getObjectType();
495         checkBeanType(beanname, requiredType, ctype);
496         return instantiate(beanname, fb);
497       }
498       else{
499         final Class JavaDoc ctype = c.getType();
500         if(c.isConcrete()){
501           checkBeanType(beanname, requiredType, ctype);
502         }
503         final Object JavaDoc result = instantiate(c);
504         checkBeanInstanceType(beanname, requiredType, result);
505         return result;
506       }
507     }
508   }
509
510   /**
511    * Same as {@link #containsBeanDefinition(String)} since
512    * this class does not care about hierarchy.
513    * In fact, Yan does not create Spring hierarchies.
514    */

515   public boolean containsBean(String JavaDoc name) {
516     return this.containsBeanDefinition(name);
517     //yan.containsKey(BeanFactoryUtils.transformedBeanName(name));
518
}
519
520   /**
521    * Is the component identified by the name a singleton?
522    * FactoryBean is instantiated if the name doesn't start with '&'
523    * and the bean is a FactoryBean.
524    */

525   public boolean isSingleton(final String JavaDoc name)
526   throws NoSuchBeanDefinitionException {
527     final Component c = getComponent(name);
528     if(!BeanFactoryUtils.isFactoryDereference(name)){
529       final Component fbc = SpringAdapter.getFactoryBeanComponent(c);
530       if(fbc!=null){
531         final FactoryBean fb = (FactoryBean)instantiate(fbc);
532         return fb.isSingleton();
533       }
534     }
535     return c.isSingleton();
536   }
537
538   /**
539    * Get the static type of a component identified by the name.
540    * @param name the bean name. FactoryBean is instantiated if
541    * the name doesn't start with '&' and the bean is a FactoryBean.
542    */

543   public Class JavaDoc getType(final String JavaDoc name)
544   throws NoSuchBeanDefinitionException {
545     final Component c = getComponent(name);
546     if(!BeanFactoryUtils.isFactoryDereference(name)){
547       final Component fbc = SpringAdapter.getFactoryBeanComponent(c);
548       if(fbc!=null){
549         final FactoryBean fb = (FactoryBean)instantiate(fbc);
550         return fb.getObjectType();
551       }
552     }
553     return c.getType();
554   }
555   private static final String JavaDoc[] no_aliases = {};
556   /**
557    * Always returns empty.
558    */

559   public String JavaDoc[] getAliases(String JavaDoc name)
560   throws NoSuchBeanDefinitionException {
561     getComponent(name);
562     return no_aliases;
563   }
564
565   public String JavaDoc getDisplayName() {
566     return name;
567   }
568
569   public ApplicationContext getParent() {
570     return null;
571   }
572
573   public long getStartupDate() {
574     return startup_timestamp;
575   }
576
577   public void publishEvent(ApplicationEvent event) {
578     final ApplicationEventMulticaster multicaster = getApplicationEventMulticaster();
579     multicaster.multicastEvent(event);
580     if(parent_publisher!=null)
581       parent_publisher.publishEvent(event);
582   }
583
584
585
586   public String JavaDoc getMessage(String JavaDoc code, Object JavaDoc[] args, Locale JavaDoc locale) throws NoSuchMessageException {
587     return getMessageSource().getMessage(code, args, locale);
588   }
589
590   public String JavaDoc getMessage(MessageSourceResolvable resolvable, Locale JavaDoc locale) throws NoSuchMessageException {
591     return getMessageSource().getMessage(resolvable, locale);
592   }
593
594   public String JavaDoc getMessage(String JavaDoc code, Object JavaDoc[] args, String JavaDoc defaultMessage, Locale JavaDoc locale) {
595     return getMessageSource().getMessage(code, args, defaultMessage, locale);
596   }
597
598   public Resource[] getResources(String JavaDoc locationPattern) throws IOException JavaDoc {
599     return resource_loader.getResources(locationPattern);
600   }
601
602   public Resource getResource(String JavaDoc location) {
603     return resource_loader.getResource(location);
604   }
605
606   public BeanFactory getParentBeanFactory() {
607     return null;
608   }
609   private void checkBeanType(String JavaDoc beanname, Class JavaDoc required, Class JavaDoc actual){
610     if(actual!=null && required!=null &&
611         !ReflectionUtil.isAssignableFrom(required, actual)){
612       throw new BeanNotOfRequiredTypeException(beanname, required, actual);
613     }
614   }
615   private void checkBeanInstanceType(String JavaDoc beanname, Class JavaDoc required, Object JavaDoc instance){
616     if(required!=null &&
617         !ReflectionUtil.isInstance(required, instance)){
618       throw new BeanNotOfRequiredTypeException(beanname, required,
619           instance==null?null:instance.getClass());
620     }
621   }
622   private static Object JavaDoc instantiate(String JavaDoc beanname, FactoryBean fb){
623     try{
624       return fb.getObject();
625     }
626     catch(RuntimeException JavaDoc e){
627       throw e;
628     }
629     catch(Error JavaDoc e){
630       throw e;
631     }
632     catch(Exception JavaDoc e){
633       throw new BeanCreationException(beanname, "FactoryBean failed", e);
634     }
635   }
636 }
637
Popular Tags