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.