Coverage report

  %line %branch
org.apache.commons.configuration.JNDIConfiguration
91% 
100% 

 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.