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