Coverage report

  %line %branch
org.apache.commons.configuration.AbstractConfiguration$1
100% 
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.math.BigDecimal;
 20  
 import java.math.BigInteger;
 21  
 import java.util.ArrayList;
 22  
 import java.util.Collection;
 23  
 import java.util.Iterator;
 24  
 import java.util.List;
 25  
 import java.util.NoSuchElementException;
 26  
 import java.util.Properties;
 27  
 import java.util.StringTokenizer;
 28  
 import java.util.Vector;
 29  
 
 30  
 import org.apache.commons.collections.Predicate;
 31  
 import org.apache.commons.collections.iterators.FilterIterator;
 32  
 import org.apache.commons.lang.BooleanUtils;
 33  
 
 34  
 /**
 35  
  * Abstract configuration class. Provide basic functionality but does not
 36  
  * store any data. If you want to write your own Configuration class
 37  
  * then you should implement only abstract methods from this class.
 38  
  *
 39  
  * @author <a href="mailto:ksh@scand.com">Konstantin Shaposhnikov</a>
 40  
  * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
 41  
  * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
 42  
  * @version $Id: AbstractConfiguration.java,v 1.25 2004/10/05 21:17:25 ebourg Exp $
 43  
  */
 44  
 public abstract class AbstractConfiguration implements Configuration
 45  
 {
 46  
     /** start token */
 47  
     protected static final String START_TOKEN = "${";
 48  
 
 49  
     /** end token */
 50  
     protected static final String END_TOKEN = "}";
 51  
 
 52  
     /** The property delimiter used while parsing (a comma). */
 53  
     private static char DELIMITER = ',';
 54  
 
 55  
     /** how big the initial arraylist for splitting up name value pairs */
 56  
     private static final int INITIAL_LIST_SIZE = 2;
 57  
 
 58  
     /**
 59  
      * Whether the configuration should throw NoSuchElementExceptions or simply
 60  
      * return null when a property does not exist. Defaults to return null.
 61  
      */
 62  
     private boolean throwExceptionOnMissing = false;
 63  
 
 64  
     /**
 65  
      * For configurations extending AbstractConfiguration, allow them to
 66  
      * change the delimiter from the default comma (",").
 67  
      *
 68  
      * @param delimiter The new delimiter
 69  
      */
 70  
     public static void setDelimiter(char delimiter)
 71  
     {
 72  
         AbstractConfiguration.DELIMITER = delimiter;
 73  
     }
 74  
 
 75  
     /**
 76  
      * Retrieve the current delimiter.  By default this is a comma (",").
 77  
      * 
 78  
      * @return The delimiter in use
 79  
      */
 80  
     public static char getDelimiter()
 81  
     {
 82  
         return AbstractConfiguration.DELIMITER;
 83  
     }
 84  
 
 85  
     /**
 86  
      * If set to false, missing elements return null if possible (for objects).
 87  
      *
 88  
      * @param throwExceptionOnMissing The new value for the property
 89  
      */
 90  
     public void setThrowExceptionOnMissing(boolean throwExceptionOnMissing)
 91  
     {
 92  
         this.throwExceptionOnMissing = throwExceptionOnMissing;
 93  
     }
 94  
 
 95  
     /**
 96  
      * Returns true if missing values throw Exceptions.
 97  
      *
 98  
      * @return true if missing values throw Exceptions
 99  
      */
 100  
     public boolean isThrowExceptionOnMissing()
 101  
     {
 102  
         return throwExceptionOnMissing;
 103  
     }
 104  
 
 105  
 
 106  
     /**
 107  
      * {@inheritDoc}
 108  
      */
 109  
     public void addProperty(String key, Object token)
 110  
     {
 111  
         if (token instanceof String)
 112  
         {
 113  
             Iterator it = split((String) token).iterator();
 114  
             while (it.hasNext())
 115  
             {
 116  
                 addPropertyDirect(key, it.next());
 117  
             }
 118  
         }
 119  
         else if (token instanceof Collection)
 120  
         {
 121  
             Iterator it = ((Collection) token).iterator();
 122  
             while (it.hasNext())
 123  
             {
 124  
                 addProperty(key, it.next());
 125  
             }
 126  
         }
 127  
         else
 128  
         {
 129  
             addPropertyDirect(key, token);
 130  
         }
 131  
     }
 132  
 
 133  
     /**
 134  
      * Read property. Should return <code>null</code> if the key doesn't
 135  
      * map to an existing object.
 136  
      *
 137  
      * @param key key to use for mapping
 138  
      *
 139  
      * @return object associated with the given configuration key.
 140  
      */
 141  
     protected abstract Object getPropertyDirect(String key);
 142  
 
 143  
     /**
 144  
      * Adds a key/value pair to the Configuration. Override this method to
 145  
      * provide write acces to underlying Configuration store.
 146  
      *
 147  
      * @param key key to use for mapping
 148  
      * @param obj object to store
 149  
      */
 150  
     protected abstract void addPropertyDirect(String key, Object obj);
 151  
 
 152  
     /**
 153  
      * interpolate key names to handle ${key} stuff
 154  
      *
 155  
      * @param base string to interpolate
 156  
      *
 157  
      * @return returns the key name with the ${key} substituted
 158  
      */
 159  
     protected String interpolate(String base)
 160  
     {
 161  
         return interpolateHelper(base, null);
 162  
     }
 163  
 
 164  
     /**
 165  
      * Recursive handler for multple levels of interpolation.
 166  
      *
 167  
      * When called the first time, priorVariables should be null.
 168  
      *
 169  
      * @param base string with the ${key} variables
 170  
      * @param priorVariables serves two purposes: to allow checking for
 171  
      * loops, and creating a meaningful exception message should a loop
 172  
      * occur.  It's 0'th element will be set to the value of base from
 173  
      * the first call.  All subsequent interpolated variables are added
 174  
      * afterward.
 175  
      *
 176  
      * @return the string with the interpolation taken care of
 177  
      */
 178  
     protected String interpolateHelper(String base, List priorVariables)
 179  
     {
 180  
         if (base == null)
 181  
         {
 182  
             return null;
 183  
         }
 184  
 
 185  
         // on the first call initialize priorVariables
 186  
         // and add base as the first element
 187  
         if (priorVariables == null)
 188  
         {
 189  
             priorVariables = new ArrayList();
 190  
             priorVariables.add(base);
 191  
         }
 192  
 
 193  
         int begin = -1;
 194  
         int end = -1;
 195  
         int prec = 0 - END_TOKEN.length();
 196  
         String variable = null;
 197  
         StringBuffer result = new StringBuffer();
 198  
 
 199  
         // FIXME: we should probably allow the escaping of the start token
 200  
         while (((begin = base.indexOf(START_TOKEN, prec + END_TOKEN.length()))
 201  
             > -1)
 202  
             && ((end = base.indexOf(END_TOKEN, begin)) > -1))
 203  
         {
 204  
             result.append(base.substring(prec + END_TOKEN.length(), begin));
 205  
             variable = base.substring(begin + START_TOKEN.length(), end);
 206  
 
 207  
             // if we've got a loop, create a useful exception message and throw
 208  
             if (priorVariables.contains(variable))
 209  
             {
 210  
                 String initialBase = priorVariables.remove(0).toString();
 211  
                 priorVariables.add(variable);
 212  
                 StringBuffer priorVariableSb = new StringBuffer();
 213  
 
 214  
                 // create a nice trace of interpolated variables like so:
 215  
                 // var1->var2->var3
 216  
                 for (Iterator it = priorVariables.iterator(); it.hasNext();)
 217  
                 {
 218  
                     priorVariableSb.append(it.next());
 219  
                     if (it.hasNext())
 220  
                     {
 221  
                         priorVariableSb.append("->");
 222  
                     }
 223  
                 }
 224  
 
 225  
                 throw new IllegalStateException(
 226  
                     "infinite loop in property interpolation of "
 227  
                         + initialBase
 228  
                         + ": "
 229  
                         + priorVariableSb.toString());
 230  
             }
 231  
             // otherwise, add this variable to the interpolation list.
 232  
             else
 233  
             {
 234  
                 priorVariables.add(variable);
 235  
             }
 236  
 
 237  
             //QUESTION: getProperty or getPropertyDirect
 238  
             Object value = getProperty(variable);
 239  
             if (value != null)
 240  
             {
 241  
                 result.append(interpolateHelper(value.toString(),
 242  
                     priorVariables));
 243  
 
 244  
                 // pop the interpolated variable off the stack
 245  
                 // this maintains priorVariables correctness for
 246  
                 // properties with multiple interpolations, e.g.
 247  
                 // prop.name=${some.other.prop1}/blahblah/${some.other.prop2}
 248  
                 priorVariables.remove(priorVariables.size() - 1);
 249  
             }
 250  
             else
 251  
             {
 252  
                 //variable not defined - so put it back in the value
 253  
                 result.append(START_TOKEN).append(variable).append(END_TOKEN);
 254  
             }
 255  
 
 256  
             prec = end;
 257  
         }
 258  
         result.append(base.substring(prec + END_TOKEN.length(), base.length()));
 259  
         return result.toString();
 260  
     }
 261  
 
 262  
     /**
 263  
      * Returns a List of Strings built from the supplied String. Splits up CSV
 264  
      * lists. If no commas are in the String, simply returns a List with the
 265  
      * String as its first element.
 266  
      *
 267  
      * @param token The String to tokenize
 268  
      *
 269  
      * @return A List of Strings
 270  
      */
 271  
     protected List split(String token)
 272  
     {
 273  
         List list = new ArrayList(INITIAL_LIST_SIZE);
 274  
 
 275  
         if (token.indexOf(DELIMITER) > 0)
 276  
         {
 277  
             PropertiesTokenizer tokenizer = new PropertiesTokenizer(token);
 278  
 
 279  
             while (tokenizer.hasMoreTokens())
 280  
             {
 281  
                 list.add(tokenizer.nextToken());
 282  
             }
 283  
         }
 284  
         else
 285  
         {
 286  
             list.add(token);
 287  
         }
 288  
 
 289  
         //
 290  
         // We keep the sequence of the keys here and
 291  
         // we also keep it in the List. So the
 292  
         // keys are added to the store in the sequence that
 293  
         // is given in the properties
 294  
         return list;
 295  
     }
 296  
 
 297  
     /**
 298  
      * {@inheritDoc}
 299  
      */
 300  
     public Configuration subset(String prefix)
 301  
     {
 302  
         return new SubsetConfiguration(this, prefix, ".");
 303  
     }
 304  
 
 305  
     /**
 306  
      * {@inheritDoc}
 307  
      */
 308  
     public abstract boolean isEmpty();
 309  
 
 310  
     /**
 311  
      * {@inheritDoc}
 312  
      */
 313  
     public abstract boolean containsKey(String key);
 314  
 
 315  
     /**
 316  
      * {@inheritDoc}
 317  
      */
 318  
     public void setProperty(String key, Object value)
 319  
     {
 320  
         clearProperty(key);
 321  
         addProperty(key, value); // QUESTION: or addPropertyDirect?
 322  
     }
 323  
 
 324  
     /**
 325  
      * {@inheritDoc}
 326  
      */
 327  
     public  abstract void clearProperty(String key);
 328  
 
 329  
     /**
 330  
      * {@inheritDoc}
 331  
      */
 332  
     public abstract Iterator getKeys();
 333  
 
 334  
     /**
 335  
      * {@inheritDoc}
 336  
      */
 337  
     public Iterator getKeys(final String prefix)
 338  
     {
 339  
         return new FilterIterator(getKeys(), class="keyword">new Predicate()
 340  
         {
 341  31
             public boolean evaluate(Object obj)
 342  
             {
 343  371
                 String key = (String) obj;
 344  371
                 return key.startsWith(prefix + ".") || key.equals(prefix);
 345  
             }
 346  
         });
 347  
     }
 348  
 
 349  
     /**
 350  
      * {@inheritDoc}
 351  
      */
 352  
     public Properties getProperties(String key)
 353  
     {
 354  
         return getProperties(key, null);
 355  
     }
 356  
 
 357  
     /**
 358  
      * Get a list of properties associated with the given configuration key.
 359  
      *
 360  
      * @param key The configuration key.
 361  
      * @param defaults Any default values for the returned
 362  
      * <code>Properties</code> object.  Ignored if <code>null</code>.
 363  
      *
 364  
      * @return The associated properties if key is found.
 365  
      *
 366  
      * @throws ConversionException is thrown if the key maps to an
 367  
      *         object that is not a String/List of Strings.
 368  
      *
 369  
      * @throws IllegalArgumentException if one of the tokens is
 370  
      *         malformed (does not contain an equals sign).
 371  
      */
 372  
     public Properties getProperties(String key, Properties defaults)
 373  
     {
 374  
         /*
 375  
          * Grab an array of the tokens for this key.
 376  
          */
 377  
         String[] tokens = getStringArray(key);
 378  
 
 379  
         /*
 380  
          * Each token is of the form 'key=value'.
 381  
          */
 382  
         Properties props = defaults == null ? new Properties() : class="keyword">new Properties(defaults);
 383  
         for (int i = 0; i < tokens.length; i++)
 384  
         {
 385  
             String token = tokens[i];
 386  
             int equalSign = token.indexOf('=');
 387  
             if (equalSign > 0)
 388  
             {
 389  
                 String pkey = token.substring(0, equalSign).trim();
 390  
                 String pvalue = token.substring(equalSign + 1).trim();
 391  
                 props.put(pkey, pvalue);
 392  
             }
 393  
             else if (tokens.length == 1 && "".equals(token))
 394  
             {
 395  
                 // Semantically equivalent to an empty Properties
 396  
                 // object.
 397  
                 break;
 398  
             }
 399  
             else
 400  
             {
 401  
                 throw new IllegalArgumentException(
 402  
                     '\'' + token + "' does not contain an equals sign");
 403  
             }
 404  
         }
 405  
         return props;
 406  
     }
 407  
 
 408  
     /**
 409  
      * {@inheritDoc}
 410  
      */
 411  
     public Object getProperty(String key)
 412  
     {
 413  
         return getPropertyDirect(key);
 414  
     }
 415  
 
 416  
     /**
 417  
      * {@inheritDoc}
 418  
      */
 419  
     public boolean getBoolean(String key)
 420  
     {
 421  
         Boolean b = getBoolean(key, null);
 422  
         if (b != null)
 423  
         {
 424  
             return b.booleanValue();
 425  
         }
 426  
         else
 427  
         {
 428  
             throw new NoSuchElementException(
 429  
                 '\'' + key + "' doesn't map to an existing object");
 430  
         }
 431  
     }
 432  
 
 433  
     /**
 434  
      * {@inheritDoc}
 435  
      */
 436  
     public boolean getBoolean(String key, class="keyword">boolean defaultValue)
 437  
     {
 438  
         return getBoolean(key, BooleanUtils.toBooleanObject(defaultValue)).booleanValue();
 439  
     }
 440  
 
 441  
     /**
 442  
      * {@inheritDoc}
 443  
      */
 444  
     public Boolean getBoolean(String key, Boolean defaultValue)
 445  
     {
 446  
         Object value = resolveContainerStore(key);
 447  
 
 448  
         if (value instanceof Boolean)
 449  
         {
 450  
             return (Boolean) value;
 451  
         }
 452  
         else if (value instanceof String)
 453  
         {
 454  
             Boolean b = BooleanUtils.toBooleanObject((String) value);
 455  
             if (b == null)
 456  
             {
 457  
                 throw new ConversionException('\'' + key + "' doesn't map to a Boolean object");
 458  
             }
 459  
             return b;
 460  
         }
 461  
         else if (value == null)
 462  
         {
 463  
             return defaultValue;
 464  
         }
 465  
         else
 466  
         {
 467  
             throw new ConversionException(
 468  
                 '\'' + key + "' doesn't map to a Boolean object");
 469  
         }
 470  
     }
 471  
 
 472  
     /**
 473  
      * {@inheritDoc}
 474  
      */
 475  
     public byte getByte(String key)
 476  
     {
 477  
         Byte b = getByte(key, null);
 478  
         if (b != null)
 479  
         {
 480  
             return b.byteValue();
 481  
         }
 482  
         else
 483  
         {
 484  
             throw new NoSuchElementException(
 485  
                 '\'' + key + " doesn't map to an existing object");
 486  
         }
 487  
     }
 488  
 
 489  
     /**
 490  
      * {@inheritDoc}
 491  
      */
 492  
     public byte getByte(String key, byte defaultValue)
 493  
     {
 494  
         return getByte(key, new Byte(defaultValue)).byteValue();
 495  
     }
 496  
 
 497  
     /**
 498  
      * {@inheritDoc}
 499  
      */
 500  
     public Byte getByte(String key, Byte defaultValue)
 501  
     {
 502  
         Object value = resolveContainerStore(key);
 503  
 
 504  
         if (value instanceof Byte)
 505  
         {
 506  
             return (Byte) value;
 507  
         }
 508  
         else if (value instanceof String)
 509  
         {
 510  
             try
 511  
             {
 512  
                 Byte b = new Byte((String) value);
 513  
                 return b;
 514  
             }
 515  
             catch (NumberFormatException e)
 516  
             {
 517  
                 throw new ConversionException('\'' + key + "' doesn't map to a Byte object", e);
 518  
             }
 519  
         }
 520  
         else if (value == null)
 521  
         {
 522  
             return defaultValue;
 523  
         }
 524  
         else
 525  
         {
 526  
             throw new ConversionException('\'' + key + "' doesn't map to a Byte object");
 527  
         }
 528  
     }
 529  
 
 530  
     /**
 531  
      * {@inheritDoc}
 532  
      */
 533  
     public double getDouble(String key)
 534  
     {
 535  
         Double d = getDouble(key, null);
 536  
         if (d != null)
 537  
         {
 538  
             return d.doubleValue();
 539  
         }
 540  
         else
 541  
         {
 542  
             throw new NoSuchElementException(
 543  
                 '\'' + key + "' doesn't map to an existing object");
 544  
         }
 545  
     }
 546  
 
 547  
     /**
 548  
      * {@inheritDoc}
 549  
      */
 550  
     public double getDouble(String key, class="keyword">double defaultValue)
 551  
     {
 552  
         return getDouble(key, new Double(defaultValue)).doubleValue();
 553  
     }
 554  
 
 555  
     /**
 556  
      * {@inheritDoc}
 557  
      */
 558  
     public Double getDouble(String key, Double defaultValue)
 559  
     {
 560  
         Object value = resolveContainerStore(key);
 561  
 
 562  
         if (value instanceof Double)
 563  
         {
 564  
             return (Double) value;
 565  
         }
 566  
         else if (value instanceof String)
 567  
         {
 568  
             try
 569  
             {
 570  
                 Double d = new Double((String) value);
 571  
                 return d;
 572  
             }
 573  
             catch (NumberFormatException e)
 574  
             {
 575  
                 throw new ConversionException('\'' + key + "' doesn't map to a Double object", e);
 576  
             }
 577  
         }
 578  
         else if (value == null)
 579  
         {
 580  
             return defaultValue;
 581  
         }
 582  
         else
 583  
         {
 584  
             throw new ConversionException('\'' + key + "' doesn't map to a Double object");
 585  
         }
 586  
     }
 587  
 
 588  
     /**
 589  
      * {@inheritDoc}
 590  
      */
 591  
     public float getFloat(String key)
 592  
     {
 593  
         Float f = getFloat(key, null);
 594  
         if (f != null)
 595  
         {
 596  
             return f.floatValue();
 597  
         }
 598  
         else
 599  
         {
 600  
             throw new NoSuchElementException(
 601  
                 '\'' + key + "' doesn't map to an existing object");
 602  
         }
 603  
     }
 604  
 
 605  
     /**
 606  
      * {@inheritDoc}
 607  
      */
 608  
     public float getFloat(String key, class="keyword">float defaultValue)
 609  
     {
 610  
         return getFloat(key, new Float(defaultValue)).floatValue();
 611  
     }
 612  
 
 613  
     /**
 614  
      * {@inheritDoc}
 615  
      */
 616  
     public Float getFloat(String key, Float defaultValue)
 617  
     {
 618  
         Object value = resolveContainerStore(key);
 619  
 
 620  
         if (value instanceof Float)
 621  
         {
 622  
             return (Float) value;
 623  
         }
 624  
         else if (value instanceof String)
 625  
         {
 626  
             try
 627  
             {
 628  
                 Float f = new Float((String) value);
 629  
                 return f;
 630  
             }
 631  
             catch (NumberFormatException e)
 632  
             {
 633  
                 throw new ConversionException('\'' + key + "' doesn't map to a Float object", e);
 634  
             }
 635  
         }
 636  
         else if (value == null)
 637  
         {
 638  
            return defaultValue;
 639  
         }
 640  
         else
 641  
         {
 642  
             throw new ConversionException('\'' + key + "' doesn't map to a Float object");
 643  
         }
 644  
     }
 645  
 
 646  
     /**
 647  
      * {@inheritDoc}
 648  
      */
 649  
     public int getInt(String key)
 650  
     {
 651  
         Integer i = getInteger(key, null);
 652  
         if (i != null)
 653  
         {
 654  
             return i.intValue();
 655  
         }
 656  
         else
 657  
         {
 658  
             throw new NoSuchElementException(
 659  
                 '\'' + key + "' doesn't map to an existing object");
 660  
         }
 661  
     }
 662  
 
 663  
     /**
 664  
      * {@inheritDoc}
 665  
      */
 666  
     public int getInt(String key, class="keyword">int defaultValue)
 667  
     {
 668  
         Integer i = getInteger(key, null);
 669  
 
 670  
         if (i == null)
 671  
         {
 672  
             return defaultValue;
 673  
         }
 674  
 
 675  
         return i.intValue();
 676  
     }
 677  
 
 678  
     /**
 679  
      * {@inheritDoc}
 680  
      */
 681  
     public Integer getInteger(String key, Integer defaultValue)
 682  
     {
 683  
         Object value = resolveContainerStore(key);
 684  
 
 685  
         if (value instanceof Integer)
 686  
         {
 687  
             return (Integer) value;
 688  
         }
 689  
         else if (value instanceof String)
 690  
         {
 691  
             try
 692  
             {
 693  
                 Integer i = new Integer((String) value);
 694  
                 return i;
 695  
             }
 696  
             catch (NumberFormatException e)
 697  
             {
 698  
                 throw new ConversionException('\'' + key + "' doesn't map to a Integer object", e);
 699  
             }
 700  
         }
 701  
         else if (value == null)
 702  
         {
 703  
             return defaultValue;
 704  
         }
 705  
         else
 706  
         {
 707  
             throw new ConversionException('\'' + key + "' doesn't map to a Integer object");
 708  
         }
 709  
     }
 710  
 
 711  
     /**
 712  
      * {@inheritDoc}
 713  
      */
 714  
     public long getLong(String key)
 715  
     {
 716  
         Long l = getLong(key, null);
 717  
         if (l != null)
 718  
         {
 719  
             return l.longValue();
 720  
         }
 721  
         else
 722  
         {
 723  
             throw new NoSuchElementException(
 724  
                 '\'' + key + "' doesn't map to an existing object");
 725  
         }
 726  
     }
 727  
 
 728  
     /**
 729  
      * {@inheritDoc}
 730  
      */
 731  
     public long getLong(String key, class="keyword">long defaultValue)
 732  
     {
 733  
         return getLong(key, new Long(defaultValue)).longValue();
 734  
     }
 735  
 
 736  
     /**
 737  
      * {@inheritDoc}
 738  
      */
 739  
     public Long getLong(String key, Long defaultValue)
 740  
     {
 741  
         Object value = resolveContainerStore(key);
 742  
 
 743  
         if (value instanceof Long)
 744  
         {
 745  
             return (Long) value;
 746  
         }
 747  
         else if (value instanceof String)
 748  
         {
 749  
             try
 750  
             {
 751  
                 Long l = new Long((String) value);
 752  
                 return l;
 753  
             }
 754  
             catch (NumberFormatException e)
 755  
             {
 756  
                 throw new ConversionException('\'' + key + "' doesn't map to a Long object", e);
 757  
             }
 758  
         }
 759  
         else if (value == null)
 760  
         {
 761  
             return defaultValue;
 762  
         }
 763  
         else
 764  
         {
 765  
             throw new ConversionException('\'' + key + "' doesn't map to a Long object");
 766  
         }
 767  
     }
 768  
 
 769  
     /**
 770  
      * {@inheritDoc}
 771  
      */
 772  
     public short getShort(String key)
 773  
     {
 774  
         Short s = getShort(key, null);
 775  
         if (s != null)
 776  
         {
 777  
             return s.shortValue();
 778  
         }
 779  
         else
 780  
         {
 781  
             throw new NoSuchElementException(
 782  
                 '\'' + key + "' doesn't map to an existing object");
 783  
         }
 784  
     }
 785  
 
 786  
     /**
 787  
      * {@inheritDoc}
 788  
      */
 789  
     public short getShort(String key, class="keyword">short defaultValue)
 790  
     {
 791  
         return getShort(key, new Short(defaultValue)).shortValue();
 792  
     }
 793  
 
 794  
     /**
 795  
      * {@inheritDoc}
 796  
      */
 797  
     public Short getShort(String key, Short defaultValue)
 798  
     {
 799  
         Object value = resolveContainerStore(key);
 800  
 
 801  
         if (value instanceof Short)
 802  
         {
 803  
             return (Short) value;
 804  
         }
 805  
         else if (value instanceof String)
 806  
         {
 807  
             try
 808  
             {
 809  
                 Short s = new Short((String) value);
 810  
                 return s;
 811  
             }
 812  
             catch (NumberFormatException e)
 813  
             {
 814  
                 throw new ConversionException('\'' + key + "' doesn't map to a Short object", e);
 815  
             }
 816  
         }
 817  
         else if (value == null)
 818  
         {
 819  
             return defaultValue;
 820  
         }
 821  
         else
 822  
         {
 823  
             throw new ConversionException('\'' + key + "' doesn't map to a Short object");
 824  
         }
 825  
     }
 826  
 
 827  
     /**
 828  
      * {@inheritDoc}
 829  
      */
 830  
     public BigDecimal getBigDecimal(String key)
 831  
     {
 832  
         BigDecimal number = getBigDecimal(key, null);
 833  
         if (number != null)
 834  
         {
 835  
             return number;
 836  
         }
 837  
         else if (isThrowExceptionOnMissing())
 838  
         {
 839  
             throw new NoSuchElementException(
 840  
                 '\'' + key + "' doesn't map to an existing object");
 841  
         }
 842  
         else
 843  
         {
 844  
             return null;
 845  
         }
 846  
     }
 847  
 
 848  
     /**
 849  
      * {@inheritDoc}
 850  
      */
 851  
     public BigDecimal getBigDecimal(String key, BigDecimal defaultValue)
 852  
     {
 853  
         Object value = resolveContainerStore(key);
 854  
 
 855  
         if (value instanceof BigDecimal)
 856  
         {
 857  
             return (BigDecimal) value;
 858  
         }
 859  
         else if (value instanceof String)
 860  
         {
 861  
             try
 862  
             {
 863  
                 BigDecimal number = new BigDecimal((String) value);
 864  
                 return number;
 865  
             }
 866  
             catch (Exception e)
 867  
             {
 868  
                 throw new ConversionException('\'' + key + "' doesn't map to a BigDecimal object", e);
 869  
             }
 870  
         }
 871  
         else if (value == null)
 872  
         {
 873  
             return defaultValue;
 874  
         }
 875  
         else
 876  
         {
 877  
             throw new ConversionException('\'' + key + "' doesn't map to a BigDecimal object");
 878  
         }
 879  
     }
 880  
 
 881  
     /**
 882  
      * {@inheritDoc}
 883  
      */
 884  
     public BigInteger getBigInteger(String key)
 885  
     {
 886  
         BigInteger number = getBigInteger(key, null);
 887  
         if (number != null)
 888  
         {
 889  
             return number;
 890  
         }
 891  
         else if (isThrowExceptionOnMissing())
 892  
         {
 893  
             throw new NoSuchElementException(
 894  
                     '\'' + key + "' doesn't map to an existing object");
 895  
         }
 896  
         else
 897  
         {
 898  
             return null;
 899  
         }
 900  
     }
 901  
 
 902  
     /**
 903  
      * {@inheritDoc}
 904  
      */
 905  
     public BigInteger getBigInteger(String key, BigInteger defaultValue)
 906  
     {
 907  
         Object value = resolveContainerStore(key);
 908  
 
 909  
         if (value instanceof BigInteger)
 910  
         {
 911  
             return (BigInteger) value;
 912  
         }
 913  
         else if (value instanceof String)
 914  
         {
 915  
             try
 916  
             {
 917  
                 BigInteger number = new BigInteger((String) value);
 918  
                 return number;
 919  
             }
 920  
             catch (Exception e)
 921  
             {
 922  
                 throw new ConversionException('\'' + key + "' doesn't map to a BigDecimal object", e);
 923  
             }
 924  
         }
 925  
         else if (value == null)
 926  
         {
 927  
             return defaultValue;
 928  
         }
 929  
         else
 930  
         {
 931  
             throw new ConversionException(
 932  
                 '\'' + key + "' doesn't map to a BigDecimal object");
 933  
         }
 934  
     }
 935  
 
 936  
     /**
 937  
      * {@inheritDoc}
 938  
      */
 939  
     public String getString(String key)
 940  
     {
 941  
         String s = getString(key, null);
 942  
         if (s != null)
 943  
         {
 944  
             return s;
 945  
         }
 946  
         else if (isThrowExceptionOnMissing())
 947  
         {
 948  
             throw new NoSuchElementException(
 949  
                 '\'' + key + "' doesn't map to an existing object");
 950  
         }
 951  
         else
 952  
         {
 953  
             return null;
 954  
         }
 955  
     }
 956  
 
 957  
     /**
 958  
      * {@inheritDoc}
 959  
      */
 960  
     public String getString(String key, String defaultValue)
 961  
     {
 962  
         Object value = resolveContainerStore(key);
 963  
 
 964  
         if (value instanceof String)
 965  
         {
 966  
             return interpolate((String) value);
 967  
         }
 968  
         else if (value == null)
 969  
         {
 970  
            return interpolate(defaultValue);
 971  
         }
 972  
         else
 973  
         {
 974  
             throw new ConversionException(
 975  
                 '\'' + key + "' doesn't map to a String object");
 976  
         }
 977  
     }
 978  
 
 979  
     /**
 980  
      * {@inheritDoc}
 981  
      */
 982  
     public String[] getStringArray(String key)
 983  
     {
 984  
         Object value = getPropertyDirect(key);
 985  
 
 986  
         String[] tokens;
 987  
 
 988  
         if (value instanceof String)
 989  
         {
 990  
             tokens = new String[1];
 991  
 
 992  
             tokens[0] = interpolate((String) value);
 993  
         }
 994  
         else if (value instanceof List)
 995  
         {
 996  
             List list = (List) value;
 997  
             tokens = new String[list.size()];
 998  
 
 999  
             for (int i = 0; i < tokens.length; i++)
 1000  
             {
 1001  
                 tokens[i] = interpolate((String) list.get(i));
 1002  
             }
 1003  
         }
 1004  
         else if (value == null)
 1005  
         {
 1006  
             tokens = new String[0];
 1007  
         }
 1008  
         else
 1009  
         {
 1010  
             throw new ConversionException(
 1011  
                 '\'' + key + "' doesn't map to a String/List object");
 1012  
         }
 1013  
         return tokens;
 1014  
     }
 1015  
 
 1016  
     /**
 1017  
      * {@inheritDoc}
 1018  
      */
 1019  
     public List getList(String key)
 1020  
     {
 1021  
         return getList(key, new ArrayList());
 1022  
     }
 1023  
 
 1024  
     /**
 1025  
      * {@inheritDoc}
 1026  
      */
 1027  
     public List getList(String key, List defaultValue)
 1028  
     {
 1029  
         Object value = getPropertyDirect(key);
 1030  
         List list = null;
 1031  
 
 1032  
         if (value instanceof String)
 1033  
         {
 1034  
             list = new ArrayList(1);
 1035  
             list.add(value);
 1036  
         }
 1037  
         else if (value instanceof List)
 1038  
         {
 1039  
             list = (List) value;
 1040  
         }
 1041  
         else if (value == null)
 1042  
         {
 1043  
             list = defaultValue;
 1044  
         }
 1045  
         else
 1046  
         {
 1047  
             throw new ConversionException(
 1048  
                 '\''
 1049  
                     + key
 1050  
                     + "' doesn't map to a List object: "
 1051  
                     + value
 1052  
                     + ", a "
 1053  
                     + value.getClass().getName());
 1054  
         }
 1055  
         return list;
 1056  
     }
 1057  
 
 1058  
     /**
 1059  
      * {@inheritDoc}
 1060  
      */
 1061  
     public Vector getVector(String key)
 1062  
     {
 1063  
         return getVector(key, new Vector());
 1064  
     }
 1065  
 
 1066  
     /**
 1067  
      * {@inheritDoc}
 1068  
      */
 1069  
     public Vector getVector(String key, Vector defaultValue)
 1070  
     {
 1071  
         Object value = getPropertyDirect(key);
 1072  
         Vector vector = null;
 1073  
 
 1074  
         if (value instanceof String)
 1075  
         {
 1076  
             vector = new Vector(1);
 1077  
             vector.add(value);
 1078  
         }
 1079  
         else if (value instanceof List)
 1080  
         {
 1081  
             vector = new Vector(((List) value).size());
 1082  
 
 1083  
             for (Iterator it = ((List) value).iterator(); it.hasNext(); )
 1084  
             {
 1085  
                 Object obj = it.next();
 1086  
                 vector.add(obj);
 1087  
             }
 1088  
         }
 1089  
         else if (value == null)
 1090  
         {
 1091  
             vector = defaultValue;
 1092  
         }
 1093  
         else
 1094  
         {
 1095  
             throw new ConversionException(
 1096  
                 '\''
 1097  
                     + key
 1098  
                     + "' doesn't map to a Vector object: "
 1099  
                     + value
 1100  
                     + ", a "
 1101  
                     + value.getClass().getName());
 1102  
         }
 1103  
         return vector;
 1104  
     }
 1105  
 
 1106  
     /**
 1107  
      * Returns an object from the store described by the key. If the value is
 1108  
      * a List object, replace it with the first object in the list.
 1109  
      *
 1110  
      * @param key The property key.
 1111  
      *
 1112  
      * @return value Value, transparently resolving a possible List dependency.
 1113  
      */
 1114  
     private Object resolveContainerStore(String key)
 1115  
     {
 1116  
         Object value = getPropertyDirect(key);
 1117  
         if (value != null && value instanceof List)
 1118  
         {
 1119  
             List list = (List) value;
 1120  
             value = list.isEmpty() ? null : list.get(0);
 1121  
         }
 1122  
         return value;
 1123  
     }
 1124  
 
 1125  
     /**
 1126  
      * This class divides into tokens a property value.  Token
 1127  
      * separator is "," but commas into the property value are escaped
 1128  
      * using the backslash in front.
 1129  
      */
 1130  
     static class PropertiesTokenizer extends StringTokenizer
 1131  
     {
 1132  
         /**
 1133  
          * Constructor.
 1134  
          *
 1135  
          * @param string A String.
 1136  
          */
 1137  
         public PropertiesTokenizer(String string)
 1138  
         {
 1139  
             super(string, String.valueOf(DELIMITER));
 1140  
         }
 1141  
 
 1142  
         /**
 1143  
          * Get next token.
 1144  
          *
 1145  
          * @return A String.
 1146  
          */
 1147  
         public String nextToken()
 1148  
         {
 1149  
             StringBuffer buffer = new StringBuffer();
 1150  
 
 1151  
             while (hasMoreTokens())
 1152  
             {
 1153  
                 String token = super.nextToken();
 1154  
                 if (token.endsWith("\\"))
 1155  
                 {
 1156  
                     buffer.append(token.substring(0, token.length() - 1));
 1157  
                     buffer.append(DELIMITER);
 1158  
                 }
 1159  
                 else
 1160  
                 {
 1161  
                     buffer.append(token);
 1162  
                     break;
 1163  
                 }
 1164  
             }
 1165  
             return buffer.toString().trim();
 1166  
         }
 1167  
     } // class PropertiesTokenizer
 1168  
 
 1169  
 }

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