Coverage report

| %line | %branch
--- | --- | ---
org.apache.commons.configuration.JNDIConfiguration |
87% |
97% |

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.