KickJava   Java API By Example, From Geeks To Geeks.

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


1 package jfun.yan.spring;
2
3 import java.util.Properties JavaDoc;
4
5 import org.springframework.beans.factory.BeanFactoryAware;
6 import org.springframework.beans.factory.BeanNameAware;
7 import org.springframework.beans.factory.DisposableBean;
8 import org.springframework.beans.factory.FactoryBean;
9 import org.springframework.beans.factory.InitializingBean;
10 import org.springframework.beans.factory.config.BeanPostProcessor;
11 import org.springframework.context.ApplicationContext;
12 import org.springframework.context.ApplicationContextAware;
13 import org.springframework.context.ApplicationEventPublisherAware;
14 import org.springframework.context.MessageSourceAware;
15 import org.springframework.context.ResourceLoaderAware;
16 import org.springframework.transaction.PlatformTransactionManager;
17 import org.springframework.transaction.interceptor.TransactionProxyFactoryBean;
18
19 import jfun.yan.Component;
20 import jfun.yan.Components;
21 import jfun.yan.Container;
22 import jfun.yan.Map;
23 import jfun.yan.Map3;
24 import jfun.yan.Monad;
25 import jfun.yan.Mutation;
26 import jfun.yan.factory.ThreadLocalScope;
27 import jfun.yan.xml.NutsUtils;
28 import jfun.yan.xml.SingletonMode;
29
30
31
32 /**
33  * The main adapter class to between Yan and Spring.
34  * <p>
35  * @author Ben Yu
36  * Nov 17, 2005 12:01:20 AM
37  */

38 public class SpringAdapter {
39
40   private static Object JavaDoc injectFactoryBeanResult(final SpringContext ctxt, Object JavaDoc obj)
41   throws ClassNotFoundException JavaDoc, Exception JavaDoc {
42     //injectBasicBean(obj, ctxt);
43
if(obj instanceof FactoryBean){
44       obj = ((FactoryBean)obj).getObject();
45       //Spring 1.2.6 source code doesn't handle FactoryBean results. so we skip.
46
//injectBasicBean(obj, ctxt);
47
}
48     return obj;
49   }
50   private static Map3 getFactoryBeanMap3(final SpringContext ctxt,
51       final String JavaDoc[] itfs){
52     return new Map3(){
53       public Object JavaDoc map(Object JavaDoc tx, Object JavaDoc attrs, Object JavaDoc obj)
54       throws Exception JavaDoc{
55         final PlatformTransactionManager man =(PlatformTransactionManager)tx;
56         final Properties JavaDoc tattrs = (Properties JavaDoc)attrs;
57         final Object JavaDoc r = injectFactoryBeanResult(ctxt, obj);
58         return proxyTransaction(r, ctxt, man, tattrs, itfs);
59       }
60     };
61   }
62
63   private static Map getFactoryBeanMap(final SpringContext ctxt){
64     return new Map(){
65       public Object JavaDoc map(Object JavaDoc obj)
66       throws Exception JavaDoc{
67         return injectFactoryBeanResult(ctxt, obj);
68       }
69     };
70   }
71   private static Mutation getBeanMutation(final SpringContext ctxt){
72     return new Mutation(){
73       public void mutate(Object JavaDoc obj)
74       throws Exception JavaDoc{
75         injectBasicBean(obj, ctxt);
76       }
77     };
78   }
79   /**
80    * Inject spring dependencies into an object when it is of any
81    * Spring marker interface. Run FactoryBean if any.
82    * Add transaction proxy if any.
83    * @param obj the object to inject dependencies.
84    * @param ctxt the SpringContext object hosting all pertinent
85    * runtime information.
86    * @param transaction_manager the Component that instantiates the transaction manager.
87    * Can be null if transaction_attributes is null.
88    * @param transaction_attributes the Component that instantiates a Properties object
89    * that contains transaction attributes.
90    * This is the indicator parameter. When it is null, no transaction proxying is done.
91    * And when it is not null, the transaction_manager cannot be null.
92    * @param interfaces the interface names to proxy on.
93    * Can be null.
94    * @return the final result object.
95    */

96   public static Object JavaDoc injectBean(Object JavaDoc obj, SpringContext ctxt,
97       PlatformTransactionManager transaction_manager,
98       Properties JavaDoc transaction_attributes, String JavaDoc[] interfaces)
99   throws Exception JavaDoc{
100     injectBasicBean(obj, ctxt);
101     return proxyTransaction(obj, ctxt,
102         transaction_manager, transaction_attributes, interfaces);
103   }
104   private static void injectApplicationContext(Object JavaDoc obj, ApplicationContext actxt){
105     if(obj instanceof ApplicationContextAware){
106       ((ApplicationContextAware)obj).setApplicationContext(actxt);
107     }
108     else{
109       if(obj instanceof BeanFactoryAware){
110         ((BeanFactoryAware)obj).setBeanFactory(actxt);
111       }
112
113       if(obj instanceof ResourceLoaderAware){
114         ((ResourceLoaderAware)obj).setResourceLoader(actxt);
115       }
116       if(obj instanceof ApplicationEventPublisherAware){
117         ((ApplicationEventPublisherAware)obj).setApplicationEventPublisher(actxt);
118       }
119       if(obj instanceof MessageSourceAware){
120         ((MessageSourceAware)obj).setMessageSource(actxt);
121       }
122     }
123   }
124   /**
125    * Inject spring dependencies into an object when it is of any
126    * Spring marker interface.
127    * @param obj the object to inject dependencies.
128    * @param ctxt the SpringContext object hosting all pertinent
129    * runtime information.
130    * @param transaction_manager the Component that instantiates the transaction manager.
131    * @param transaction_attributes the Component that instantiates a Properties object
132    * that contains transaction attributes.
133    * @param interfaces the interface names to proxy on.
134    * @return the final result object.
135    */

136   private static void injectBasicBean(Object JavaDoc obj, SpringContext ctxt)
137   throws Exception JavaDoc{
138     if(ctxt.isGloballyDefined()){
139       //only ids of global components make sense.
140
final String JavaDoc id = ctxt.getId();
141       if(id!=null && obj instanceof BeanNameAware){
142         ((BeanNameAware)obj).setBeanName(id);
143       }
144     }
145     injectApplicationContext(obj, ctxt.getApplicationContext());
146
147     initBean(obj, ctxt);
148   }
149   private static void initBean(Object JavaDoc obj, SpringContext ctxt)
150   throws Exception JavaDoc{
151     final Object JavaDoc original = obj;
152     // applyBeanPostProcessorsBeforeInitialization(bean, beanName, mergedBeanDefinition)
153
if(obj instanceof InitializingBean){
154       ((InitializingBean)obj).afterPropertiesSet();
155     }
156     //runInitializer(obj, ctxt.getInitializer());
157
//applyBeanPostProcessorsAfterInitialization(bean, beanName, mergedBeanDefinition);
158
if(original instanceof DisposableBean){
159       final DisposableBean db = (DisposableBean)original;
160       ctxt.manageDisposableBean(db);
161     }
162   }
163   private static final Component autowire_txman =
164     Components.useType(PlatformTransactionManager.class);
165   /**
166    * Decorate a Component with spring context so that
167    * dependencies can be injected automatically, and
168    * FactoryBean can be automatically instantiated.
169    * @param c the Component object.
170    * @param ctxt the SpringContext object.
171    * @param transaction_manager the Component that instantiates the transaction manager.
172    * Can be null if transaction_attributes is null.
173    * @param transaction_attributes the Component that instantiates a Properties object
174    * that contains transaction attributes.
175    * This is the indicator parameter. When it is null, no transaction proxying is done.
176    * And when it is not null, the transaction_manager cannot be null.
177    * @param interfaces the interface names to proxy on.
178    * Can be null.
179    * @return the new Component that does all the spring-related work.
180    */

181   public static Component adapt(Component c,
182       SpringContext ctxt, Component transaction_manager,
183       Component transaction_attributes, String JavaDoc[] interfaces){
184     if(transaction_attributes!=null && transaction_manager==null){
185       transaction_manager =
186         ctxt.cast(PlatformTransactionManager.class,
187             autowire_txman
188         ).label("transaction manager auto detection");
189     }
190     final Class JavaDoc type = c.getType();
191
192     final Component r = createSpringBeanComponent(c, ctxt, transaction_manager, transaction_attributes, interfaces);
193     if(type!=null && BeanPostProcessor.class.isAssignableFrom(type)){
194       //does bpp suffer from proxies?
195
ctxt.addBeanPostProcessor(ctxt.getTagName(), c);
196     }
197     if(type!=null && FactoryBean.class.isAssignableFrom(type)){
198       //for factory bean, we do not know its type in advance.
199
return r;
200     }
201     if(transaction_attributes!=null){
202       //for beans to be proxied, we do not know the type.
203
return r;
204     }
205     if(r.getType()==null && type!=null)
206       return ctxt.cast(type, r);
207     else return r;
208   }
209   private static Component createSpringBeanComponent(Component c, SpringContext ctxt,
210       Component transaction_manager, Component transaction_attributes,
211       String JavaDoc[] interfaces) {
212     final Class JavaDoc type = c.getType();
213     c = c.mutate(getBeanMutation(ctxt));
214     if(type!=null && SpringUtils.isSpringInfrastructureClass(type)){
215       //no proxy for spring special cases.
216
return c;//.map(getBeanMap(ctxt));
217
}
218     final boolean isfactorybean = type!=null && FactoryBean.class.isAssignableFrom(type);
219     if(isfactorybean){
220       if(ctxt.isSingletonAttributeSet()){
221         final SingletonMode mode = ctxt.getSingleton();
222         if(mode!=null)
223           c = mode.decorate(c);
224       }
225       else{
226         //factroy bean is by default singleton.
227
c = c.singleton(new ThreadLocalScope());
228       }
229     }
230     if(transaction_attributes==null){
231       //no transaction to do
232
if(type==null || isfactorybean){
233         return singletonedFactoryBean(isfactorybean,c,
234             c.map(getFactoryBeanMap(ctxt)));
235       }
236       else{
237         return c;
238       }
239     }
240     else{
241       return singletonedFactoryBean(isfactorybean, c,
242           Monad.map(transaction_manager, transaction_attributes, c, getFactoryBeanMap3(ctxt, interfaces)));
243     }
244   }
245   private static Component singletonedFactoryBean(boolean factorybean,
246       Component original_cc, Component c){
247     if(factorybean){
248       return decorateFactoryBean(new NonSingletonComponent(c), original_cc);
249     }
250     else{
251       return c;
252     }
253   }
254   private static Object JavaDoc proxyTransaction(Object JavaDoc target, SpringContext ctxt,
255       PlatformTransactionManager tx, Properties JavaDoc attrs, String JavaDoc[] itfs)
256   throws Exception JavaDoc{
257     if(tx==null){
258       if(attrs==null)
259         return target;
260       else
261         throw new IllegalArgumentException JavaDoc("transaction manager is missing to perform declarative transaction");
262     }
263     final TransactionProxyFactoryBean tpfb = new TransactionProxyFactoryBean();
264     //tpfb.setBeanFactory(ctxt.getApplicationContext());
265
tpfb.setTarget(target);
266     tpfb.setTransactionManager(tx);
267     if(itfs!=null)
268       tpfb.setProxyInterfaces(itfs);
269     tpfb.setTransactionAttributes(attrs);
270     //injectBasicBean(tpfb, ctxt);
271
tpfb.setTarget(target);
272     tpfb.setTransactionManager(tx);
273     tpfb.setTransactionAttributes(attrs);
274     
275     if(itfs!=null){
276       tpfb.setProxyInterfaces(itfs);
277     }
278     injectBasicBean(tpfb, ctxt);
279     return tpfb.getObject();
280   }
281   static final SpringKey factory_bean_key = new SpringKey("org.springframework.FactoryBean");
282   static Component decorateFactoryBean(Component c, Component factorybean_cc){
283     return NutsUtils.setState(c, factory_bean_key, factorybean_cc);
284   }
285   static boolean isFactoryBeanComponent(Component c){
286     return getFactoryBeanComponent(c) != null;
287   }
288   static Component getFactoryBeanComponent(Component c){
289     final Class JavaDoc type = c.getType();
290     if(type!=null && FactoryBean.class.isAssignableFrom(type)){
291       return c;
292     }
293     else{
294       final Component fbc = (Component)NutsUtils.getState(c, factory_bean_key);
295       return fbc;
296     }
297   }
298   /**
299    * Get FactoryBean instance from a Spring integrated Container object.
300    * @param yan the Container object.
301    * @param key the key of the FactoryBean component. The key doesn't need to be
302    * prefixed with a '&' as one has to do in Spring.
303    * @return the FactoryBean instance.
304    */

305   public static FactoryBean getFactoryBean(Container yan, Object JavaDoc key){
306     final Component c = yan.getComponent(key);
307     if(c==null){
308       return null;
309     }
310     final Component fbc = getFactoryBeanComponent(c);
311     if(fbc==null){
312       return null;
313     }
314     return (FactoryBean)yan.instantiateComponent(fbc);
315   }
316 }
317
Popular Tags