1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.configuration;
19
20 import java.util.ArrayList;
21 import java.util.Arrays;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Set;
26
27 import javax.naming.Context;
28 import javax.naming.InitialContext;
29 import javax.naming.NameClassPair;
30 import javax.naming.NameNotFoundException;
31 import javax.naming.NamingEnumeration;
32 import javax.naming.NamingException;
33 import javax.naming.NotContextException;
34
35 import org.apache.commons.lang.StringUtils;
36 import org.apache.commons.logging.LogFactory;
37
38
39
40
41
42
43
44
45
46
47 public class JNDIConfiguration extends AbstractConfiguration
48 {
49
50 private String prefix;
51
52
53 private Context context;
54
55
56 private Context baseContext;
57
58
59 private Set<String> clearedProperties = new HashSet<String>();
60
61
62
63
64
65
66
67 public JNDIConfiguration() throws NamingException
68 {
69 this((String) null);
70 }
71
72
73
74
75
76
77
78
79
80 public JNDIConfiguration(String prefix) throws NamingException
81 {
82 this(new InitialContext(), prefix);
83 }
84
85
86
87
88
89
90
91 public JNDIConfiguration(Context context)
92 {
93 this(context, null);
94 }
95
96
97
98
99
100
101
102
103 public JNDIConfiguration(Context context, String prefix)
104 {
105 this.context = context;
106 this.prefix = prefix;
107 setLogger(LogFactory.getLog(getClass()));
108 addErrorLogListener();
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122 private void recursiveGetKeys(Set<String> keys, Context context, String prefix,
123 Set<Context> processedCtx) throws NamingException
124 {
125 processedCtx.add(context);
126 NamingEnumeration<NameClassPair> elements = null;
127
128 try
129 {
130 elements = context.list("");
131
132
133 while (elements.hasMore())
134 {
135 NameClassPair nameClassPair = elements.next();
136 String name = nameClassPair.getName();
137 Object object = context.lookup(name);
138
139
140 StringBuilder key = new StringBuilder();
141 key.append(prefix);
142 if (key.length() > 0)
143 {
144 key.append(".");
145 }
146 key.append(name);
147
148 if (object instanceof Context)
149 {
150
151 Context subcontext = (Context) object;
152 if (!processedCtx.contains(subcontext))
153 {
154 recursiveGetKeys(keys, subcontext, key.toString(),
155 processedCtx);
156 }
157 }
158 else
159 {
160
161 keys.add(key.toString());
162 }
163 }
164 }
165 finally
166 {
167
168 if (elements != null)
169 {
170 elements.close();
171 }
172 }
173 }
174
175
176
177
178
179
180 public Iterator<String> getKeys()
181 {
182 return getKeys("");
183 }
184
185
186
187
188
189
190
191
192 @Override
193 public Iterator<String> getKeys(String prefix)
194 {
195
196 String[] splitPath = StringUtils.split(prefix, ".");
197
198 List<String> path = Arrays.asList(splitPath);
199
200 try
201 {
202
203 Context context = getContext(path, getBaseContext());
204
205
206 Set<String> keys = new HashSet<String>();
207 if (context != null)
208 {
209 recursiveGetKeys(keys, context, prefix, new HashSet<Context>());
210 }
211 else if (containsKey(prefix))
212 {
213
214 keys.add(prefix);
215 }
216
217 return keys.iterator();
218 }
219 catch (NameNotFoundException e)
220 {
221
222 return new ArrayList<String>().iterator();
223 }
224 catch (NamingException e)
225 {
226 fireError(EVENT_READ_PROPERTY, null, null, e);
227 return new ArrayList<String>().iterator();
228 }
229 }
230
231
232
233
234
235
236
237
238
239
240
241 private Context getContext(List<String> path, Context context) throws NamingException
242 {
243
244 if (path == null || path.isEmpty())
245 {
246 return context;
247 }
248
249 String key = path.get(0);
250
251
252 NamingEnumeration<NameClassPair> elements = null;
253
254 try
255 {
256 elements = context.list("");
257 while (elements.hasMore())
258 {
259 NameClassPair nameClassPair = elements.next();
260 String name = nameClassPair.getName();
261 Object object = context.lookup(name);
262
263 if (object instanceof Context && name.equals(key))
264 {
265 Context subcontext = (Context) object;
266
267
268 return getContext(path.subList(1, path.size()), subcontext);
269 }
270 }
271 }
272 finally
273 {
274 if (elements != null)
275 {
276 elements.close();
277 }
278 }
279
280 return null;
281 }
282
283
284
285
286
287
288 public boolean isEmpty()
289 {
290 try
291 {
292 NamingEnumeration<NameClassPair> enumeration = null;
293
294 try
295 {
296 enumeration = getBaseContext().list("");
297 return !enumeration.hasMore();
298 }
299 finally
300 {
301
302 if (enumeration != null)
303 {
304 enumeration.close();
305 }
306 }
307 }
308 catch (NamingException e)
309 {
310 fireError(EVENT_READ_PROPERTY, null, null, e);
311 return true;
312 }
313 }
314
315
316
317
318
319
320
321
322
323 @Override
324 public void setProperty(String key, Object value)
325 {
326 throw new UnsupportedOperationException("This operation is not supported");
327 }
328
329
330
331
332
333
334 @Override
335 public void clearProperty(String key)
336 {
337 clearedProperties.add(key);
338 }
339
340
341
342
343
344
345
346 public boolean containsKey(String key)
347 {
348 if (clearedProperties.contains(key))
349 {
350 return false;
351 }
352 key = key.replaceAll("\\.", "/");
353 try
354 {
355
356 getBaseContext().lookup(key);
357 return true;
358 }
359 catch (NameNotFoundException e)
360 {
361
362 return false;
363 }
364 catch (NamingException e)
365 {
366 fireError(EVENT_READ_PROPERTY, key, null, e);
367 return false;
368 }
369 }
370
371
372
373
374
375 public String getPrefix()
376 {
377 return prefix;
378 }
379
380
381
382
383
384
385 public void setPrefix(String prefix)
386 {
387 this.prefix = prefix;
388
389
390 baseContext = null;
391 }
392
393
394
395
396
397
398
399 public Object getProperty(String key)
400 {
401 if (clearedProperties.contains(key))
402 {
403 return null;
404 }
405
406 try
407 {
408 key = key.replaceAll("\\.", "/");
409 return getBaseContext().lookup(key);
410 }
411 catch (NameNotFoundException e)
412 {
413
414 return null;
415 }
416 catch (NotContextException nctxex)
417 {
418
419 return null;
420 }
421 catch (NamingException e)
422 {
423 fireError(EVENT_READ_PROPERTY, key, null, e);
424 return null;
425 }
426 }
427
428
429
430
431
432
433
434
435
436 @Override
437 protected void addPropertyDirect(String key, Object obj)
438 {
439 throw new UnsupportedOperationException("This operation is not supported");
440 }
441
442
443
444
445
446
447
448 public Context getBaseContext() throws NamingException
449 {
450 if (baseContext == null)
451 {
452 baseContext = (Context) getContext().lookup(prefix == null ? "" : prefix);
453 }
454
455 return baseContext;
456 }
457
458
459
460
461
462
463
464 public Context getContext()
465 {
466 return context;
467 }
468
469
470
471
472
473
474 public void setContext(Context context)
475 {
476
477 clearedProperties.clear();
478
479
480 this.context = context;
481 }
482 }