KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > mock > jndi > SimpleNamingContextBuilder


1 /*
2  * Copyright 2002-2005 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.mock.jndi;
18
19 import java.util.Hashtable JavaDoc;
20
21 import javax.naming.Context JavaDoc;
22 import javax.naming.NamingException JavaDoc;
23 import javax.naming.spi.InitialContextFactory JavaDoc;
24 import javax.naming.spi.InitialContextFactoryBuilder JavaDoc;
25 import javax.naming.spi.NamingManager JavaDoc;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 /**
31  * Simple implementation of a JNDI naming context builder.
32  *
33  * <p>Mainly targeted at test environments, where each test case can
34  * configure JNDI appropriately, so that <code>new InitialContext()</code>
35  * will expose the required objects. Also usable for standalone applications,
36  * e.g. for binding a JDBC DataSource to a well-known JNDI location, to be
37  * able to use traditional J2EE data access code outside of a J2EE container.
38  *
39  * <p>There are various choices for DataSource implementations:
40  * <ul>
41  * <li>SingleConnectionDataSource (using the same Connection for all getConnection calls);
42  * <li>DriverManagerDataSource (creating a new Connection on each getConnection call);
43  * <li>Apache's Jakarta Commons DBCP offers BasicDataSource (a real pool).
44  * </ul>
45  *
46  * <p>Typical usage in bootstrap code:
47  *
48  * <pre>
49  * SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
50  * DataSource ds = new DriverManagerDataSource(...);
51  * builder.bind("java:comp/env/jdbc/myds", ds);
52  * builder.activate();</pre>
53  *
54  * Note that it's impossible to activate multiple builders within the same JVM,
55  * due to JNDI restrictions. Thus to configure a fresh builder repeatedly, use
56  * the following code to get a reference to either an already activated builder
57  * or a newly activated one:
58  *
59  * <pre>
60  * SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
61  * DataSource ds = new DriverManagerDataSource(...);
62  * builder.bind("java:comp/env/jdbc/myds", ds);</pre>
63  *
64  * Note that you <i>should not</i> call activate() on a builder from this
65  * factory method, as there will already be an activated one in any case.
66  *
67  * <p>An instance of this class is only necessary at setup time.
68  * An application does not need to keep a reference to it after activation.
69  *
70  * @author Juergen Hoeller
71  * @author Rod Johnson
72  * @see #emptyActivatedContextBuilder()
73  * @see #bind(String, Object)
74  * @see #activate()
75  * @see org.springframework.mock.jndi.SimpleNamingContext
76  * @see org.springframework.jdbc.datasource.SingleConnectionDataSource
77  * @see org.springframework.jdbc.datasource.DriverManagerDataSource
78  * @see org.apache.commons.dbcp.BasicDataSource
79  */

80 public class SimpleNamingContextBuilder implements InitialContextFactoryBuilder JavaDoc {
81     
82     /** An instance of this class bound to JNDI */
83     private static SimpleNamingContextBuilder activated;
84
85
86     /**
87      * Checks if a SimpleNamingContextBuilder is active.
88      * @return the current SimpleNamingContextBuilder instance,
89      * or <code>null</code> if none
90      */

91     public static SimpleNamingContextBuilder getCurrentContextBuilder() {
92         return activated;
93     }
94
95     /**
96      * If no SimpleNamingContextBuilder is already configuring JNDI,
97      * create and activate one. Otherwise take the existing activate
98      * SimpleNamingContextBuilder, clear it and return it.
99      * <p>This is mainly intended for test suites that want to
100      * reinitialize JNDI bindings from scratch repeatedly.
101      * @return an empty SimpleNamingContextBuilder that can be used
102      * to control JNDI bindings
103      */

104     public static SimpleNamingContextBuilder emptyActivatedContextBuilder() throws NamingException JavaDoc {
105         if (activated != null) {
106             // Clear already activated context builder.
107
activated.clear();
108         }
109         else {
110             // Create and activate new context builder.
111
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
112             // The activate() call will cause an assigment to the activated variable.
113
builder.activate();
114         }
115         return activated;
116     }
117
118
119     private final Log logger = LogFactory.getLog(getClass());
120
121     private final Hashtable JavaDoc boundObjects = new Hashtable JavaDoc();
122
123
124     /**
125      * Register the context builder by registering it with the JNDI NamingManager.
126      * Note that once this has been done, <code>new InitialContext()</code> will always
127      * return a context from this factory. Use the <code>emptyActivatedContextBuilder()</code>
128      * static method to get an empty context (for example, in test methods).
129      * @throws IllegalStateException if there's already a naming context builder
130      * registered with the JNDI NamingManager
131      */

132     public void activate() throws IllegalStateException JavaDoc, NamingException JavaDoc {
133         logger.info("Activating simple JNDI environment");
134         if (NamingManager.hasInitialContextFactoryBuilder()) {
135             throw new IllegalStateException JavaDoc(
136                     "Cannot activate SimpleNamingContextBuilder: there is already a JNDI provider registered. " +
137                     "Note that JNDI is a JVM-wide service, shared at the JVM system class loader level, " +
138                     "with no reset option. As a consequence, a JNDI provider must only be registered once per JVM.");
139         }
140         NamingManager.setInitialContextFactoryBuilder(this);
141         activated = this;
142     }
143
144     /**
145      * Clear all bindings in this context builder.
146      */

147     public void clear() {
148         this.boundObjects.clear();
149     }
150
151     /**
152      * Bind the given object under the given name, for all naming contexts
153      * that this context builder will generate.
154      * @param name the JNDI name of the object (e.g. "java:comp/env/jdbc/myds")
155      * @param obj the object to bind (e.g. a DataSource implementation)
156      */

157     public void bind(String JavaDoc name, Object JavaDoc obj) {
158         if (logger.isInfoEnabled()) {
159             logger.info("Static JNDI binding: [" + name + "] = [" + obj + "]");
160         }
161         this.boundObjects.put(name, obj);
162     }
163
164     /**
165      * Simple InitialContextFactoryBuilder implementation,
166      * creating a new SimpleNamingContext instance.
167      * @see SimpleNamingContext
168      */

169     public InitialContextFactory JavaDoc createInitialContextFactory(Hashtable JavaDoc environment) {
170         return new InitialContextFactory JavaDoc() {
171             public Context JavaDoc getInitialContext(Hashtable JavaDoc environment) {
172                 return new SimpleNamingContext("", boundObjects, environment);
173             }
174         };
175     }
176
177 }
178
Popular Tags