KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jndi > JndiObjectFactoryBean


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.jndi;
18
19 import javax.naming.NamingException JavaDoc;
20
21 import org.springframework.aop.framework.ProxyFactory;
22 import org.springframework.beans.factory.BeanClassLoaderAware;
23 import org.springframework.beans.factory.FactoryBean;
24 import org.springframework.util.ClassUtils;
25
26 /**
27  * {@link org.springframework.beans.factory.FactoryBean} that looks up a
28  * JNDI object. Exposes the object found in JNDI for bean references,
29  * e.g. for data access object's "dataSource" property in case of a
30  * {@link javax.sql.DataSource}.
31  *
32  * <p>The typical usage will be to register this as singleton factory
33  * (e.g. for a certain JNDI-bound DataSource) in an application context,
34  * and give bean references to application services that need it.
35  *
36  * <p>The default behavior is to look up the JNDI object on startup and cache it.
37  * This can be customized through the "lookupOnStartup" and "cache" properties,
38  * using a {@link JndiObjectTargetSource} underneath. Note that you need to specify
39  * a "proxyInterface" in such a scenario, since the actual JNDI object type is not
40  * known in advance.
41  *
42  * <p>Of course, bean classes in a Spring environment may lookup e.g. a DataSource
43  * from JNDI themselves. This class simply enables central configuration of the
44  * JNDI name, and easy switching to non-JNDI alternatives. The latter is
45  * particularly convenient for test setups, reuse in standalone clients, etc.
46  *
47  * <p>Note that switching to e.g. DriverManagerDataSource is just a matter of
48  * configuration: Simply replace the definition of this FactoryBean with a
49  * {@link org.springframework.jdbc.datasource.DriverManagerDataSource} definition!
50  *
51  * @author Juergen Hoeller
52  * @since 22.05.2003
53  * @see #setProxyInterface
54  * @see #setLookupOnStartup
55  * @see #setCache
56  * @see JndiObjectTargetSource
57  */

58 public class JndiObjectFactoryBean extends JndiObjectLocator implements FactoryBean, BeanClassLoaderAware {
59
60     private Class JavaDoc proxyInterface;
61
62     private boolean lookupOnStartup = true;
63
64     private boolean cache = true;
65
66     private Object JavaDoc defaultObject;
67
68     private ClassLoader JavaDoc beanClassLoader = ClassUtils.getDefaultClassLoader();
69
70     private Object JavaDoc jndiObject;
71
72
73     /**
74      * Specify the proxy interface to use for the JNDI object.
75      * Needs to be specified because the actual JNDI object type is not known
76      * in advance in case of a lazy lookup.
77      * <p>Typically used in conjunction with "lookupOnStartup"=false and/or "cache"=false.
78      * @see #setLookupOnStartup
79      * @see #setCache
80      */

81     public void setProxyInterface(Class JavaDoc proxyInterface) {
82         if (!proxyInterface.isInterface()) {
83             throw new IllegalArgumentException JavaDoc("[" + proxyInterface.getName() + "] is not an interface");
84         }
85         this.proxyInterface = proxyInterface;
86     }
87
88     /**
89      * Set whether to look up the JNDI object on startup. Default is "true".
90      * <p>Can be turned off to allow for late availability of the JNDI object.
91      * In this case, the JNDI object will be fetched on first access.
92      * <p>For a lazy lookup, a proxy interface needs to be specified.
93      * @see #setProxyInterface
94      * @see #setCache
95      */

96     public void setLookupOnStartup(boolean lookupOnStartup) {
97         this.lookupOnStartup = lookupOnStartup;
98     }
99
100     /**
101      * Set whether to cache the JNDI object once it has been located.
102      * Default is "true".
103      * <p>Can be turned off to allow for hot redeployment of JNDI objects.
104      * In this case, the JNDI object will be fetched for each invocation.
105      * <p>For hot redeployment, a proxy interface needs to be specified.
106      * @see #setProxyInterface
107      * @see #setLookupOnStartup
108      */

109     public void setCache(boolean cache) {
110         this.cache = cache;
111     }
112
113     /**
114      * Specify a default object to fall back to if the JNDI lookup fails.
115      * Default is none.
116      * <p>This can be an arbitrary bean reference or literal value.
117      * It is typically used for literal values in scenarios where the JNDI environment
118      * might define specific config settings but those are not required to be present.
119      * <p>Note: This is only supported for lookup on startup.
120      * @see #setLookupOnStartup
121      */

122     public void setDefaultObject(Object JavaDoc defaultObject) {
123         this.defaultObject = defaultObject;
124     }
125
126     public void setBeanClassLoader(ClassLoader JavaDoc classLoader) {
127         this.beanClassLoader = classLoader;
128     }
129
130
131     /**
132      * Look up the JNDI object and store it.
133      */

134     public void afterPropertiesSet() throws IllegalArgumentException JavaDoc, NamingException JavaDoc {
135         super.afterPropertiesSet();
136
137         if (this.proxyInterface != null) {
138             if (this.defaultObject != null) {
139                 throw new IllegalArgumentException JavaDoc(
140                         "'defaultObject' is not supported in combination with 'proxyInterface'");
141             }
142             // We need a proxy and a JndiObjectTargetSource.
143
this.jndiObject = JndiObjectProxyFactory.createJndiObjectProxy(this);
144         }
145
146         else {
147             if (!this.lookupOnStartup || !this.cache) {
148                 throw new IllegalArgumentException JavaDoc(
149                     "Cannot deactivate 'lookupOnStartup' or 'cache' without specifying a 'proxyInterface'");
150             }
151             if (this.defaultObject != null && getExpectedType() != null &&
152                     !getExpectedType().isInstance(this.defaultObject)) {
153                 throw new IllegalArgumentException JavaDoc("Default object [" + this.defaultObject +
154                         "] of type [" + this.defaultObject.getClass().getName() +
155                         "] is not of expected type [" + getExpectedType().getName() + "]");
156             }
157             // Locate specified JNDI object.
158
this.jndiObject = lookupWithFallback();
159         }
160     }
161
162     /**
163      * Lookup variant that that returns the specified "defaultObject"
164      * (if any) in case of lookup failure.
165      * @return the located object, or the "defaultObject" as fallback
166      * @throws NamingException in case of lookup failure without fallback
167      * @see #setDefaultObject
168      */

169     protected Object JavaDoc lookupWithFallback() throws NamingException JavaDoc {
170         try {
171             return lookup();
172         }
173         catch (TypeMismatchNamingException ex) {
174             // Always let TypeMismatchNamingException through -
175
// we don't want to fall back to the defaultObject in this case.
176
throw ex;
177         }
178         catch (NamingException JavaDoc ex) {
179             if (this.defaultObject != null) {
180                 if (logger.isDebugEnabled()) {
181                     logger.debug("JNDI lookup failed - returning specified default object instead", ex);
182                 }
183                 else if (logger.isInfoEnabled()) {
184                     logger.info("JNDI lookup failed - returning specified default object instead: " + ex);
185                 }
186                 return this.defaultObject;
187             }
188             throw ex;
189         }
190     }
191
192
193     /**
194      * Return the singleton JNDI object.
195      */

196     public Object JavaDoc getObject() {
197         return this.jndiObject;
198     }
199
200     public Class JavaDoc getObjectType() {
201         if (this.proxyInterface != null) {
202             return this.proxyInterface;
203         }
204         else if (this.jndiObject != null) {
205             return this.jndiObject.getClass();
206         }
207         else {
208             return getExpectedType();
209         }
210     }
211
212     public boolean isSingleton() {
213         return true;
214     }
215
216
217     /**
218      * Inner class to just introduce an AOP dependency when actually creating a proxy.
219      */

220     private static class JndiObjectProxyFactory {
221
222         private static Object JavaDoc createJndiObjectProxy(JndiObjectFactoryBean jof) throws NamingException JavaDoc {
223             // Create a JndiObjectTargetSource that mirrors the JndiObjectFactoryBean's configuration.
224
JndiObjectTargetSource targetSource = new JndiObjectTargetSource();
225             targetSource.setJndiTemplate(jof.getJndiTemplate());
226             targetSource.setJndiName(jof.getJndiName());
227             targetSource.setExpectedType(jof.getExpectedType());
228             targetSource.setResourceRef(jof.isResourceRef());
229             targetSource.setLookupOnStartup(jof.lookupOnStartup);
230             targetSource.setCache(jof.cache);
231             targetSource.afterPropertiesSet();
232
233             // Create a proxy with JndiObjectFactoryBean's proxy interface and the JndiObjectTargetSource.
234
ProxyFactory proxyFactory = new ProxyFactory();
235             proxyFactory.addInterface(jof.proxyInterface);
236             proxyFactory.setTargetSource(targetSource);
237             return proxyFactory.getProxy(jof.beanClassLoader);
238         }
239     }
240
241 }
242
Popular Tags