Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
JndiTemplate |
|
| 1.6;1.6 | ||||
JndiTemplate$1 |
|
| 1.6;1.6 | ||||
JndiTemplate$2 |
|
| 1.6;1.6 | ||||
JndiTemplate$3 |
|
| 1.6;1.6 | ||||
JndiTemplate$4 |
|
| 1.6;1.6 |
1 | /* | |
2 | * Licensed to the Apache Software Foundation (ASF) under one | |
3 | * or more contributor license agreements. See the NOTICE file | |
4 | * distributed with this work for additional information | |
5 | * regarding copyright ownership. The ASF licenses this file | |
6 | * to you under the Apache License, Version 2.0 (the | |
7 | * "License"); you may not use this file except in compliance | |
8 | * with the License. You may obtain a copy of the License at | |
9 | * | |
10 | * http://www.apache.org/licenses/LICENSE-2.0 | |
11 | * | |
12 | * Unless required by applicable law or agreed to in writing, | |
13 | * software distributed under the License is distributed on an | |
14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
15 | * KIND, either express or implied. See the License for the | |
16 | * specific language governing permissions and limitations | |
17 | * under the License. | |
18 | */ | |
19 | package org.apache.shiro.jndi; | |
20 | ||
21 | import java.util.Enumeration; | |
22 | import java.util.Hashtable; | |
23 | import java.util.Properties; | |
24 | import javax.naming.Context; | |
25 | import javax.naming.InitialContext; | |
26 | import javax.naming.NameNotFoundException; | |
27 | import javax.naming.NamingException; | |
28 | ||
29 | import org.slf4j.Logger; | |
30 | import org.slf4j.LoggerFactory; | |
31 | ||
32 | /** | |
33 | * Helper class that simplifies JNDI operations. It provides methods to lookup and | |
34 | * bind objects, and allows implementations of the {@link JndiCallback} interface | |
35 | * to perform any operation they like with a JNDI naming context provided. | |
36 | * <p/> | |
37 | * <p>Note that this implementation is an almost exact copy of the Spring Framework's identically named class from | |
38 | * their 2.5.4 distribution - we didn't want to re-invent the wheel, but not require a full dependency on the | |
39 | * Spring framework, nor does Spring make available only its JNDI classes in a small jar, or we would have used that. | |
40 | * Since Shiro is also Apache 2.0 licensed, all regular licenses and conditions and authors have remained in tact. | |
41 | * | |
42 | * @see JndiCallback | |
43 | * @see #execute | |
44 | */ | |
45 | public class JndiTemplate { | |
46 | ||
47 | 1 | private static final Logger log = LoggerFactory.getLogger(JndiTemplate.class); |
48 | ||
49 | private Properties environment; | |
50 | ||
51 | /** Create a new JndiTemplate instance. */ | |
52 | 4 | public JndiTemplate() { |
53 | 4 | } |
54 | ||
55 | /** | |
56 | * Create a new JndiTemplate instance, using the given environment. | |
57 | * | |
58 | * @param environment the Properties to initialize with | |
59 | */ | |
60 | 0 | public JndiTemplate(Properties environment) { |
61 | 0 | this.environment = environment; |
62 | 0 | } |
63 | ||
64 | /** | |
65 | * Set the environment for the JNDI InitialContext. | |
66 | * | |
67 | * @param environment the Properties to initialize with | |
68 | */ | |
69 | public void setEnvironment(Properties environment) { | |
70 | 0 | this.environment = environment; |
71 | 0 | } |
72 | ||
73 | /** | |
74 | * Return the environment for the JNDI InitialContext, or <code>null</code> if none should be used. | |
75 | * | |
76 | * @return the environment for the JNDI InitialContext, or <code>null</code> if none should be used. | |
77 | */ | |
78 | public Properties getEnvironment() { | |
79 | 0 | return this.environment; |
80 | } | |
81 | ||
82 | /** | |
83 | * Execute the given JNDI context callback implementation. | |
84 | * | |
85 | * @param contextCallback JndiCallback implementation | |
86 | * @return a result object returned by the callback, or <code>null</code> | |
87 | * @throws NamingException thrown by the callback implementation | |
88 | * @see #createInitialContext | |
89 | */ | |
90 | public Object execute(JndiCallback contextCallback) throws NamingException { | |
91 | 0 | Context ctx = createInitialContext(); |
92 | try { | |
93 | 0 | return contextCallback.doInContext(ctx); |
94 | } | |
95 | finally { | |
96 | 0 | try { |
97 | 0 | ctx.close(); |
98 | 0 | } catch (NamingException ex) { |
99 | 0 | log.debug("Could not close JNDI InitialContext", ex); |
100 | 0 | } |
101 | } | |
102 | } | |
103 | ||
104 | /** | |
105 | * Create a new JNDI initial context. Invoked by {@link #execute}. | |
106 | * <p>The default implementation use this template's environment settings. | |
107 | * Can be subclassed for custom contexts, e.g. for testing. | |
108 | * | |
109 | * @return the initial Context instance | |
110 | * @throws NamingException in case of initialization errors | |
111 | */ | |
112 | @SuppressWarnings({"unchecked"}) | |
113 | protected Context createInitialContext() throws NamingException { | |
114 | 0 | Properties env = getEnvironment(); |
115 | 0 | Hashtable icEnv = null; |
116 | 0 | if (env != null) { |
117 | 0 | icEnv = new Hashtable(env.size()); |
118 | 0 | for (Enumeration en = env.propertyNames(); en.hasMoreElements();) { |
119 | 0 | String key = (String) en.nextElement(); |
120 | 0 | icEnv.put(key, env.getProperty(key)); |
121 | 0 | } |
122 | } | |
123 | 0 | return new InitialContext(icEnv); |
124 | } | |
125 | ||
126 | /** | |
127 | * Look up the object with the given name in the current JNDI context. | |
128 | * | |
129 | * @param name the JNDI name of the object | |
130 | * @return object found (cannot be <code>null</code>; if a not so well-behaved | |
131 | * JNDI implementations returns null, a NamingException gets thrown) | |
132 | * @throws NamingException if there is no object with the given | |
133 | * name bound to JNDI | |
134 | */ | |
135 | public Object lookup(final String name) throws NamingException { | |
136 | 0 | log.debug("Looking up JNDI object with name '{}'", name); |
137 | 0 | return execute(new JndiCallback() { |
138 | public Object doInContext(Context ctx) throws NamingException { | |
139 | 0 | Object located = ctx.lookup(name); |
140 | 0 | if (located == null) { |
141 | 0 | throw new NameNotFoundException( |
142 | "JNDI object with [" + name + "] not found: JNDI implementation returned null"); | |
143 | } | |
144 | 0 | return located; |
145 | } | |
146 | }); | |
147 | } | |
148 | ||
149 | /** | |
150 | * Look up the object with the given name in the current JNDI context. | |
151 | * | |
152 | * @param name the JNDI name of the object | |
153 | * @param requiredType type the JNDI object must match. Can be an interface or | |
154 | * superclass of the actual class, or <code>null</code> for any match. For example, | |
155 | * if the value is <code>Object.class</code>, this method will succeed whatever | |
156 | * the class of the returned instance. | |
157 | * @return object found (cannot be <code>null</code>; if a not so well-behaved | |
158 | * JNDI implementations returns null, a NamingException gets thrown) | |
159 | * @throws NamingException if there is no object with the given | |
160 | * name bound to JNDI | |
161 | */ | |
162 | public Object lookup(String name, Class requiredType) throws NamingException { | |
163 | 0 | Object jndiObject = lookup(name); |
164 | 0 | if (requiredType != null && !requiredType.isInstance(jndiObject)) { |
165 | 0 | String msg = "Jndi object acquired under name '" + name + "' is of type [" + |
166 | jndiObject.getClass().getName() + "] and not assignable to the required type [" + | |
167 | requiredType.getName() + "]."; | |
168 | 0 | throw new NamingException(msg); |
169 | } | |
170 | 0 | return jndiObject; |
171 | } | |
172 | ||
173 | /** | |
174 | * Bind the given object to the current JNDI context, using the given name. | |
175 | * | |
176 | * @param name the JNDI name of the object | |
177 | * @param object the object to bind | |
178 | * @throws NamingException thrown by JNDI, mostly name already bound | |
179 | */ | |
180 | public void bind(final String name, final Object object) throws NamingException { | |
181 | 0 | log.debug("Binding JNDI object with name '{}'", name); |
182 | 0 | execute(new JndiCallback() { |
183 | public Object doInContext(Context ctx) throws NamingException { | |
184 | 0 | ctx.bind(name, object); |
185 | 0 | return null; |
186 | } | |
187 | }); | |
188 | 0 | } |
189 | ||
190 | /** | |
191 | * Rebind the given object to the current JNDI context, using the given name. | |
192 | * Overwrites any existing binding. | |
193 | * | |
194 | * @param name the JNDI name of the object | |
195 | * @param object the object to rebind | |
196 | * @throws NamingException thrown by JNDI | |
197 | */ | |
198 | public void rebind(final String name, final Object object) throws NamingException { | |
199 | 0 | log.debug("Rebinding JNDI object with name '{}'", name); |
200 | 0 | execute(new JndiCallback() { |
201 | public Object doInContext(Context ctx) throws NamingException { | |
202 | 0 | ctx.rebind(name, object); |
203 | 0 | return null; |
204 | } | |
205 | }); | |
206 | 0 | } |
207 | ||
208 | /** | |
209 | * Remove the binding for the given name from the current JNDI context. | |
210 | * | |
211 | * @param name the JNDI name of the object | |
212 | * @throws NamingException thrown by JNDI, mostly name not found | |
213 | */ | |
214 | public void unbind(final String name) throws NamingException { | |
215 | 0 | log.debug("Unbinding JNDI object with name '{}'", name); |
216 | 0 | execute(new JndiCallback() { |
217 | public Object doInContext(Context ctx) throws NamingException { | |
218 | 0 | ctx.unbind(name); |
219 | 0 | return null; |
220 | } | |
221 | }); | |
222 | 0 | } |
223 | ||
224 | } |