%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.commons.configuration.JNDIConfiguration |
|
|
1 | /* |
|
2 | * Copyright 2001-2004 The Apache Software Foundation. |
|
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.apache.commons.configuration; |
|
18 | ||
19 | import java.util.ArrayList; |
|
20 | import java.util.HashSet; |
|
21 | import java.util.Iterator; |
|
22 | import java.util.List; |
|
23 | import java.util.Properties; |
|
24 | import java.util.Set; |
|
25 | ||
26 | import javax.naming.Context; |
|
27 | import javax.naming.InitialContext; |
|
28 | import javax.naming.NameClassPair; |
|
29 | import javax.naming.NameNotFoundException; |
|
30 | import javax.naming.NamingEnumeration; |
|
31 | import javax.naming.NamingException; |
|
32 | import javax.naming.NotContextException; |
|
33 | ||
34 | import org.apache.commons.lang.StringUtils; |
|
35 | import org.apache.commons.logging.Log; |
|
36 | import org.apache.commons.logging.LogFactory; |
|
37 | ||
38 | /** |
|
39 | * This Configuration class allows you to interface with a JNDI datasource. |
|
40 | * A JNDIConfiguration is read-only, write operations will throw an |
|
41 | * UnsupportedOperationException. The clear operations are supported but the |
|
42 | * underlying JNDI data source is not changed. |
|
43 | * |
|
44 | * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a> |
|
45 | * @version $Id: JNDIConfiguration.java,v 1.19 2004/10/04 20:06:09 ebourg Exp $ |
|
46 | */ |
|
47 | public class JNDIConfiguration extends AbstractConfiguration |
|
48 | { |
|
49 | /** Logger. */ |
|
50 | 12 | private static Log log = LogFactory.getLog(JNDIConfiguration.class); |
51 | ||
52 | /** The prefix of the context. */ |
|
53 | private String prefix; |
|
54 | ||
55 | /** The initial JNDI context. */ |
|
56 | private Context context; |
|
57 | ||
58 | /** The base JNDI context. */ |
|
59 | private Context baseContext; |
|
60 | ||
61 | /** The Set of keys that have been virtually cleared. */ |
|
62 | 48 | private Set clearedProperties = new HashSet(); |
63 | ||
64 | /** |
|
65 | * Creates a JNDIConfiguration using the default initial context as the |
|
66 | * root of the properties. |
|
67 | * |
|
68 | * @throws NamingException thrown if an error occurs when initializing the default context |
|
69 | */ |
|
70 | public JNDIConfiguration() throws NamingException |
|
71 | { |
|
72 | 46 | this((String) null); |
73 | 46 | } |
74 | ||
75 | /** |
|
76 | * Creates a JNDIConfiguration using the default initial context, shifted |
|
77 | * with the specified prefix, as the root of the properties. |
|
78 | * |
|
79 | * @param prefix |
|
80 | * |
|
81 | * @throws NamingException thrown if an error occurs when initializing the default context |
|
82 | */ |
|
83 | public JNDIConfiguration(String prefix) throws NamingException |
|
84 | { |
|
85 | 46 | this(new InitialContext(), prefix); |
86 | 46 | } |
87 | ||
88 | /** |
|
89 | * Creates a JNDIConfiguration using the specified initial context as the |
|
90 | * root of the properties. |
|
91 | * |
|
92 | * @param context the initial context |
|
93 | */ |
|
94 | public JNDIConfiguration(Context context) |
|
95 | { |
|
96 | 1 | this(context, null); |
97 | 1 | } |
98 | ||
99 | /** |
|
100 | * Creates a JNDIConfiguration using the specified initial context shifted |
|
101 | * by the specified prefix as the root of the properties. |
|
102 | * |
|
103 | * @param context the initial context |
|
104 | * @param prefix |
|
105 | */ |
|
106 | public JNDIConfiguration(Context context, String prefix) |
|
107 | 48 | { |
108 | 48 | this.context = context; |
109 | 48 | this.prefix = prefix; |
110 | 48 | } |
111 | ||
112 | /** |
|
113 | * JNDIConfigurations can not be added to. |
|
114 | * |
|
115 | * @param key The Key to add the property to. |
|
116 | * @param token The Value to add. |
|
117 | */ |
|
118 | public void addProperty(String key, Object token) |
|
119 | { |
|
120 | 0 | throw new UnsupportedOperationException("This operation is not supported"); |
121 | } |
|
122 | ||
123 | /** |
|
124 | * This method recursive traverse the JNDI tree, looking for Context objects. |
|
125 | * When it finds them, it traverses them as well. Otherwise it just adds the |
|
126 | * values to the list of keys found. |
|
127 | * |
|
128 | * @param keys All the keys that have been found. |
|
129 | * @param context The parent context |
|
130 | * @param prefix What prefix we are building on. |
|
131 | * @throws NamingException If JNDI has an issue. |
|
132 | */ |
|
133 | private void recursiveGetKeys(Set keys, Context context, String prefix) throws NamingException |
|
134 | { |
|
135 | 9 | NamingEnumeration elements = null; |
136 | ||
137 | try |
|
138 | { |
|
139 | 9 | elements = context.list(""); |
140 | ||
141 | // iterates through the context's elements |
|
142 | 72 | while (elements.hasMore()) |
143 | { |
|
144 | 63 | NameClassPair nameClassPair = (NameClassPair) elements.next(); |
145 | 63 | String name = nameClassPair.getName(); |
146 | 63 | Object object = context.lookup(name); |
147 | ||
148 | // build the key |
|
149 | 63 | StringBuffer key = new StringBuffer(); |
150 | 63 | key.append(prefix); |
151 | 63 | if (key.length() > 0) |
152 | { |
|
153 | 60 | key.append("."); |
154 | } |
|
155 | 63 | key.append(name); |
156 | ||
157 | 63 | if (object instanceof Context) |
158 | { |
|
159 | // add the keys of the sub context |
|
160 | 3 | Context subcontext = (Context) object; |
161 | 3 | recursiveGetKeys(keys, subcontext, key.toString()); |
162 | } |
|
163 | else |
|
164 | { |
|
165 | // add the key |
|
166 | 60 | keys.add(key.toString()); |
167 | } |
|
168 | } |
|
169 | } |
|
170 | finally |
|
171 | { |
|
172 | // close the enumeration |
|
173 | 9 | if (elements != null) |
174 | { |
|
175 | 9 | elements.close(); |
176 | } |
|
177 | } |
|
178 | 9 | } |
179 | ||
180 | /** |
|
181 | * {@inheritDoc} |
|
182 | */ |
|
183 | public Iterator getKeys() |
|
184 | { |
|
185 | 3 | return getKeys(""); |
186 | } |
|
187 | ||
188 | /** |
|
189 | * {@inheritDoc} |
|
190 | */ |
|
191 | public Iterator getKeys(String prefix) |
|
192 | { |
|
193 | // build the path |
|
194 | 10 | String[] splitPath = StringUtils.split(prefix, "."); |
195 | ||
196 | 10 | List path = new ArrayList(); |
197 | ||
198 | 21 | for (int i = 0; i < splitPath.length; i++) |
199 | { |
|
200 | 11 | path.add(splitPath[i]); |
201 | } |
|
202 | ||
203 | try |
|
204 | { |
|
205 | // find the context matching the specified path |
|
206 | 10 | Context context = getContext(path, getBaseContext()); |
207 | ||
208 | // return all the keys under the context found |
|
209 | 10 | Set keys = new HashSet(); |
210 | 10 | if (context != null) |
211 | { |
|
212 | 6 | recursiveGetKeys(keys, context, prefix); |
213 | } |
|
214 | 4 | else if (containsKey(prefix)) |
215 | { |
|
216 | // add the prefix if it matches exactly a property key |
|
217 | 2 | keys.add(prefix); |
218 | } |
|
219 | ||
220 | 10 | return keys.iterator(); |
221 | } |
|
222 | 0 | catch (NamingException e) |
223 | { |
|
224 | 0 | throw new ConfigurationRuntimeException(e.getMessage(), e); |
225 | } |
|
226 | } |
|
227 | ||
228 | /** |
|
229 | * Because JNDI is based on a tree configuration, we need to filter down the |
|
230 | * tree, till we find the Context specified by the key to start from. |
|
231 | * Otherwise return null. |
|
232 | * |
|
233 | * @param path the path of keys to traverse in order to find the context |
|
234 | * @param context the context to start from |
|
235 | * @return The context at that key's location in the JNDI tree, or null if not found |
|
236 | * @throws NamingException if JNDI has an issue |
|
237 | */ |
|
238 | private Context getContext(List path, Context context) throws NamingException |
|
239 | { |
|
240 | // return the current context if the path is empty |
|
241 | 15 | if (path == null || path.isEmpty()) |
242 | { |
|
243 | 6 | return context; |
244 | } |
|
245 | ||
246 | 9 | String key = (String) path.get(0); |
247 | ||
248 | // search a context matching the key in the context's elements |
|
249 | 9 | NamingEnumeration elements = null; |
250 | ||
251 | try |
|
252 | { |
|
253 | 9 | elements = context.list(""); |
254 | 31 | while (elements.hasMore()) |
255 | { |
|
256 | 27 | NameClassPair nameClassPair = (NameClassPair) elements.next(); |
257 | 27 | String name = nameClassPair.getName(); |
258 | 27 | Object object = context.lookup(name); |
259 | ||
260 | 27 | if (object instanceof Context && name.equals(key)) |
261 | { |
|
262 | 5 | Context subcontext = (Context) object; |
263 | ||
264 | // recursive search in the sub context |
|
265 | 5 | return getContext(path.subList(1, path.size()), subcontext); |
266 | } |
|
267 | } |
|
268 | } |
|
269 | finally |
|
270 | { |
|
271 | 9 | if (elements != null) |
272 | { |
|
273 | 9 | elements.close(); |
274 | } |
|
275 | } |
|
276 | ||
277 | 4 | return null; |
278 | } |
|
279 | ||
280 | /** |
|
281 | * {@inheritDoc} |
|
282 | * |
|
283 | * <b>This operation is not supported</b> |
|
284 | */ |
|
285 | public Properties getProperties(String key) |
|
286 | { |
|
287 | 0 | throw new UnsupportedOperationException("This operation is not supported"); |
288 | } |
|
289 | ||
290 | /** |
|
291 | * {@inheritDoc} |
|
292 | */ |
|
293 | public boolean isEmpty() |
|
294 | { |
|
295 | try |
|
296 | { |
|
297 | 2 | NamingEnumeration enumeration = null; |
298 | ||
299 | try |
|
300 | { |
|
301 | 2 | enumeration = getBaseContext().list(""); |
302 | 2 | return !enumeration.hasMore(); |
303 | } |
|
304 | finally |
|
305 | { |
|
306 | // close the enumeration |
|
307 | 2 | if (enumeration != null) |
308 | { |
|
309 | 2 | enumeration.close(); |
310 | } |
|
311 | } |
|
312 | } |
|
313 | 0 | catch (NamingException ne) |
314 | { |
|
315 | 0 | log.warn(ne); |
316 | 0 | return true; |
317 | } |
|
318 | } |
|
319 | ||
320 | /** |
|
321 | * {@inheritDoc} |
|
322 | */ |
|
323 | public Object getProperty(String key) |
|
324 | { |
|
325 | 13 | return getPropertyDirect(key); |
326 | } |
|
327 | ||
328 | /** |
|
329 | * {@inheritDoc} |
|
330 | */ |
|
331 | public void setProperty(String key, Object value) |
|
332 | { |
|
333 | 0 | throw new UnsupportedOperationException("This operation is not supported"); |
334 | } |
|
335 | ||
336 | /** |
|
337 | * {@inheritDoc} |
|
338 | */ |
|
339 | public void clearProperty(String key) |
|
340 | { |
|
341 | 4 | clearedProperties.add(key); |
342 | 4 | } |
343 | ||
344 | /** |
|
345 | * {@inheritDoc} |
|
346 | */ |
|
347 | public boolean containsKey(String key) |
|
348 | { |
|
349 | 10 | if (clearedProperties.contains(key)) |
350 | { |
|
351 | 1 | return false; |
352 | } |
|
353 | 9 | key = StringUtils.replace(key, ".", "/"); |
354 | try |
|
355 | { |
|
356 | // throws a NamingException if JNDI doesn't contain the key. |
|
357 | 9 | getBaseContext().lookup(key); |
358 | 5 | return true; |
359 | } |
|
360 | 4 | catch (NamingException ne) |
361 | { |
|
362 | 4 | return false; |
363 | } |
|
364 | } |
|
365 | ||
366 | /** |
|
367 | * @return String |
|
368 | */ |
|
369 | public String getPrefix() |
|
370 | { |
|
371 | 0 | return prefix; |
372 | } |
|
373 | ||
374 | /** |
|
375 | * Sets the prefix. |
|
376 | * |
|
377 | * @param prefix The prefix to set |
|
378 | */ |
|
379 | public void setPrefix(String prefix) |
|
380 | { |
|
381 | 2 | this.prefix = prefix; |
382 | ||
383 | // clear the previous baseContext |
|
384 | 2 | baseContext = null; |
385 | 2 | } |
386 | ||
387 | /** |
|
388 | * {@inheritDoc} |
|
389 | */ |
|
390 | protected Object getPropertyDirect(String key) |
|
391 | { |
|
392 | 67 | if (clearedProperties.contains(key)) |
393 | { |
|
394 | 3 | return null; |
395 | } |
|
396 | ||
397 | try |
|
398 | { |
|
399 | 64 | key = StringUtils.replace(key, ".", "/"); |
400 | 64 | return getBaseContext().lookup(key); |
401 | } |
|
402 | 7 | catch (NameNotFoundException e) |
403 | { |
|
404 | 7 | return null; |
405 | } |
|
406 | 7 | catch (NotContextException e) |
407 | { |
|
408 | 7 | return null; |
409 | } |
|
410 | 0 | catch (NamingException e) |
411 | { |
|
412 | 0 | e.printStackTrace(); |
413 | 0 | return null; |
414 | } |
|
415 | } |
|
416 | ||
417 | /** |
|
418 | * {@inheritDoc} |
|
419 | */ |
|
420 | protected void addPropertyDirect(String key, Object obj) |
|
421 | { |
|
422 | 0 | throw new UnsupportedOperationException("This operation is not supported"); |
423 | } |
|
424 | ||
425 | /** |
|
426 | * Return the base context with the prefix applied. |
|
427 | */ |
|
428 | public Context getBaseContext() throws NamingException |
|
429 | { |
|
430 | 85 | if (baseContext == null) |
431 | { |
|
432 | 46 | baseContext = (Context) getContext().lookup(prefix == null ? "" : prefix); |
433 | } |
|
434 | ||
435 | 85 | return baseContext; |
436 | } |
|
437 | ||
438 | /** |
|
439 | * Return the initial context used by this configuration. This context is |
|
440 | * independent of the prefix specified. |
|
441 | */ |
|
442 | public Context getContext() |
|
443 | { |
|
444 | 46 | return context; |
445 | } |
|
446 | ||
447 | /** |
|
448 | * Set the initial context of the configuration. |
|
449 | */ |
|
450 | public void setContext(Context context) |
|
451 | { |
|
452 | // forget the removed properties |
|
453 | 1 | clearedProperties.clear(); |
454 | ||
455 | // change the context |
|
456 | 1 | this.context = context; |
457 | 1 | } |
458 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |