001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.jndi;
018:
019: import java.util.Properties;
020:
021: import javax.naming.Context;
022: import javax.naming.InitialContext;
023: import javax.naming.NameNotFoundException;
024: import javax.naming.NamingException;
025:
026: import org.apache.commons.logging.Log;
027: import org.apache.commons.logging.LogFactory;
028:
029: /**
030: * Helper class that simplifies JNDI operations. It provides methods to lookup and
031: * bind objects, and allows implementations of the {@link JndiCallback} interface
032: * to perform any operation they like with a JNDI naming context provided.
033: *
034: * @author Rod Johnson
035: * @author Juergen Hoeller
036: * @see JndiCallback
037: * @see #execute
038: */
039: public class JndiTemplate {
040:
041: protected final Log logger = LogFactory.getLog(getClass());
042:
043: private Properties environment;
044:
045: /**
046: * Create a new JndiTemplate instance.
047: */
048: public JndiTemplate() {
049: }
050:
051: /**
052: * Create a new JndiTemplate instance, using the given environment.
053: */
054: public JndiTemplate(Properties environment) {
055: this .environment = environment;
056: }
057:
058: /**
059: * Set the environment for the JNDI InitialContext.
060: */
061: public void setEnvironment(Properties environment) {
062: this .environment = environment;
063: }
064:
065: /**
066: * Return the environment for the JNDI InitialContext, if any.
067: */
068: public Properties getEnvironment() {
069: return this .environment;
070: }
071:
072: /**
073: * Execute the given JNDI context callback implementation.
074: * @param contextCallback JndiCallback implementation
075: * @return a result object returned by the callback, or <code>null</code>
076: * @throws NamingException thrown by the callback implementation
077: * @see #createInitialContext
078: */
079: public Object execute(JndiCallback contextCallback)
080: throws NamingException {
081: Context ctx = createInitialContext();
082: try {
083: return contextCallback.doInContext(ctx);
084: } finally {
085: try {
086: ctx.close();
087: } catch (NamingException ex) {
088: logger.debug("Could not close JNDI InitialContext", ex);
089: }
090: }
091: }
092:
093: /**
094: * Create a new JNDI initial context. Invoked by execute.
095: * The default implementation use this template's environment settings.
096: * Can be subclassed for custom contexts, e.g. for testing.
097: * @return the initial Context instance
098: * @throws NamingException in case of initialization errors
099: */
100: protected Context createInitialContext() throws NamingException {
101: return new InitialContext(getEnvironment());
102: }
103:
104: /**
105: * Look up the object with the given name in the current JNDI context.
106: * @param name the JNDI name of the object
107: * @return object found (cannot be <code>null</code>; if a not so well-behaved
108: * JNDI implementations returns null, a NamingException gets thrown)
109: * @throws NamingException if there is no object with the given
110: * name bound to JNDI
111: */
112: public Object lookup(final String name) throws NamingException {
113: if (logger.isDebugEnabled()) {
114: logger.debug("Looking up JNDI object with name [" + name
115: + "]");
116: }
117: return execute(new JndiCallback() {
118: public Object doInContext(Context ctx)
119: throws NamingException {
120: Object located = ctx.lookup(name);
121: if (located == null) {
122: throw new NameNotFoundException(
123: "JNDI object with ["
124: + name
125: + "] not found: JNDI implementation returned null");
126: }
127: return located;
128: }
129: });
130: }
131:
132: /**
133: * Look up the object with the given name in the current JNDI context.
134: * @param name the JNDI name of the object
135: * @param requiredType type the JNDI object must match. Can be an interface or
136: * superclass of the actual class, or <code>null</code> for any match. For example,
137: * if the value is <code>Object.class</code>, this method will succeed whatever
138: * the class of the returned instance.
139: * @return object found (cannot be <code>null</code>; if a not so well-behaved
140: * JNDI implementations returns null, a NamingException gets thrown)
141: * @throws NamingException if there is no object with the given
142: * name bound to JNDI
143: */
144: public Object lookup(String name, Class requiredType)
145: throws NamingException {
146: Object jndiObject = lookup(name);
147: if (requiredType != null
148: && !requiredType.isInstance(jndiObject)) {
149: throw new TypeMismatchNamingException(name, requiredType,
150: (jndiObject != null ? jndiObject.getClass() : null));
151: }
152: return jndiObject;
153: }
154:
155: /**
156: * Bind the given object to the current JNDI context, using the given name.
157: * @param name the JNDI name of the object
158: * @param object the object to bind
159: * @throws NamingException thrown by JNDI, mostly name already bound
160: */
161: public void bind(final String name, final Object object)
162: throws NamingException {
163: if (logger.isDebugEnabled()) {
164: logger
165: .debug("Binding JNDI object with name [" + name
166: + "]");
167: }
168: execute(new JndiCallback() {
169: public Object doInContext(Context ctx)
170: throws NamingException {
171: ctx.bind(name, object);
172: return null;
173: }
174: });
175: }
176:
177: /**
178: * Rebind the given object to the current JNDI context, using the given name.
179: * Overwrites any existing binding.
180: * @param name the JNDI name of the object
181: * @param object the object to rebind
182: * @throws NamingException thrown by JNDI
183: */
184: public void rebind(final String name, final Object object)
185: throws NamingException {
186: if (logger.isDebugEnabled()) {
187: logger.debug("Rebinding JNDI object with name [" + name
188: + "]");
189: }
190: execute(new JndiCallback() {
191: public Object doInContext(Context ctx)
192: throws NamingException {
193: ctx.rebind(name, object);
194: return null;
195: }
196: });
197: }
198:
199: /**
200: * Remove the binding for the given name from the current JNDI context.
201: * @param name the JNDI name of the object
202: * @throws NamingException thrown by JNDI, mostly name not found
203: */
204: public void unbind(final String name) throws NamingException {
205: if (logger.isDebugEnabled()) {
206: logger.debug("Unbinding JNDI object with name [" + name
207: + "]");
208: }
209: execute(new JndiCallback() {
210: public Object doInContext(Context ctx)
211: throws NamingException {
212: ctx.unbind(name);
213: return null;
214: }
215: });
216: }
217:
218: }
|