KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > picocontainer > gems > adapters > ThreadLocalComponentAdapter


1 /*****************************************************************************
2  * Copyright (c) PicoContainer Organization. All rights reserved. *
3  * ------------------------------------------------------------------------- *
4  * The software in this package is published under the terms of the BSD *
5  * style license a copy of which has been included with this distribution in *
6  * the LICENSE.txt file. *
7  * *
8  * Original code by Joerg Schaible *
9  *****************************************************************************/

10 package org.picocontainer.gems.adapters;
11
12 import com.thoughtworks.proxy.Invoker;
13 import com.thoughtworks.proxy.ProxyFactory;
14 import com.thoughtworks.proxy.factory.StandardProxyFactory;
15 import com.thoughtworks.proxy.kit.ReflectionUtils;
16
17 import org.picocontainer.ComponentAdapter;
18 import org.picocontainer.PicoContainer;
19 import org.picocontainer.PicoInitializationException;
20 import org.picocontainer.PicoIntrospectionException;
21 import org.picocontainer.defaults.AssignabilityRegistrationException;
22 import org.picocontainer.defaults.CachingComponentAdapter;
23 import org.picocontainer.defaults.DecoratingComponentAdapter;
24 import org.picocontainer.defaults.NotConcreteRegistrationException;
25
26 import java.lang.reflect.InvocationTargetException JavaDoc;
27 import java.lang.reflect.Method JavaDoc;
28 import java.lang.reflect.Proxy JavaDoc;
29 import java.util.Set JavaDoc;
30
31
32 /**
33  * A {@link ComponentAdapter} that realizes a {@link ThreadLocal} component instance.
34  * <p>
35  * The adapter creates proxy instances, that will create the necessary instances on-the-fly invoking the methods of the
36  * instance. Use this adapter, if you are instantiating your components in a single thread, but should be different when
37  * accessed from different threads. See {@link ThreadLocalComponentAdapterFactory} for details.
38  * </p>
39  * <p>
40  * Note: Because this implementation uses a {@link Proxy}, you can only access the methods exposed by the implemented
41  * interfaces of your component.
42  * </p>
43  *
44  * @author J&ouml;rg Schaible
45  */

46 public class ThreadLocalComponentAdapter extends DecoratingComponentAdapter {
47
48     private transient Class JavaDoc[] interfaces;
49     private ProxyFactory proxyFactory;
50
51     /**
52      * Construct a ThreadLocalComponentAdapter.
53      *
54      * @param delegate The {@link ComponentAdapter} to delegate.
55      * @param proxyFactory The {@link ProxyFactory} to use.
56      * @throws PicoIntrospectionException Thrown if the component does not implement any interface.
57      */

58     public ThreadLocalComponentAdapter(final ComponentAdapter delegate, final ProxyFactory proxyFactory)
59             throws PicoIntrospectionException {
60         super(new CachingComponentAdapter(delegate, new ThreadLocalReference()));
61         this.proxyFactory = proxyFactory;
62         interfaces = getInterfaces();
63     }
64
65     /**
66      * Construct a ThreadLocalComponentAdapter using {@link Proxy} instances.
67      *
68      * @param delegate The {@link ComponentAdapter} to delegate.
69      * @throws PicoIntrospectionException Thrown if the component does not implement any interface.
70      */

71     public ThreadLocalComponentAdapter(final ComponentAdapter delegate) throws PicoIntrospectionException {
72         this(new CachingComponentAdapter(delegate, new ThreadLocalReference()), new StandardProxyFactory());
73     }
74
75     public Object JavaDoc getComponentInstance(final PicoContainer pico)
76             throws PicoInitializationException, PicoIntrospectionException, AssignabilityRegistrationException,
77             NotConcreteRegistrationException {
78
79         if (interfaces == null) {
80             interfaces = getInterfaces();
81         }
82
83         final ComponentAdapter delegate = getDelegate();
84         final Invoker invoker = new ThreadLocalInvoker(pico, delegate);
85         return proxyFactory.createProxy(interfaces, invoker);
86     }
87
88     final private Class JavaDoc[] getInterfaces() {
89         final Object JavaDoc componentKey = getComponentKey();
90         final Class JavaDoc[] interfaces;
91         if (componentKey instanceof Class JavaDoc && ((Class JavaDoc)componentKey).isInterface()) {
92             interfaces = new Class JavaDoc[]{(Class JavaDoc)componentKey};
93         } else {
94             final Set JavaDoc allInterfaces = ReflectionUtils.getAllInterfaces(getComponentImplementation());
95             interfaces = (Class JavaDoc[])allInterfaces.toArray(new Class JavaDoc[allInterfaces.size()]);
96         }
97         if (interfaces.length == 0) {
98             throw new PicoIntrospectionException("Can't proxy implementation for "
99                     + getComponentImplementation().getName()
100                     + ". It does not implement any interfaces.");
101         }
102         return interfaces;
103     }
104
105     final static private class ThreadLocalInvoker implements Invoker {
106
107         private final PicoContainer pico;
108         private final ComponentAdapter delegate;
109
110         private ThreadLocalInvoker(final PicoContainer pico, final ComponentAdapter delegate) {
111             this.pico = pico;
112             this.delegate = delegate;
113         }
114
115         public Object JavaDoc invoke(final Object JavaDoc proxy, final Method JavaDoc method, final Object JavaDoc[] args) throws Throwable JavaDoc {
116             final Object JavaDoc delegatedInstance = delegate.getComponentInstance(pico);
117             if (method.equals(ReflectionUtils.equals)) { // necessary for JDK 1.3
118
return new Boolean JavaDoc(args[0] != null && args[0].equals(delegatedInstance));
119             } else {
120                 try {
121                     return method.invoke(delegatedInstance, args);
122                 } catch (final InvocationTargetException JavaDoc e) {
123                     throw e.getTargetException();
124                 }
125             }
126         }
127     }
128 }
Popular Tags