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.