Coverage report

  %line %branch
org.apache.commons.configuration.JNDIConfiguration
88% 
99% 

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

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.