Coverage Report - org.apache.commons.configuration.PropertyConverter
 
Classes in this File Line Coverage Branch Coverage Complexity
PropertyConverter
96%
232/241
100%
84/84
7,68
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *     http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 
 18  
 package org.apache.commons.configuration;
 19  
 
 20  
 import java.awt.Color;
 21  
 import java.lang.reflect.Array;
 22  
 import java.lang.reflect.Constructor;
 23  
 import java.lang.reflect.InvocationTargetException;
 24  
 import java.lang.reflect.Method;
 25  
 import java.math.BigDecimal;
 26  
 import java.math.BigInteger;
 27  
 import java.net.InetAddress;
 28  
 import java.net.MalformedURLException;
 29  
 import java.net.URL;
 30  
 import java.net.UnknownHostException;
 31  
 import java.text.ParseException;
 32  
 import java.text.SimpleDateFormat;
 33  
 import java.util.ArrayList;
 34  
 import java.util.Calendar;
 35  
 import java.util.Collection;
 36  
 import java.util.Date;
 37  
 import java.util.Iterator;
 38  
 import java.util.List;
 39  
 import java.util.Locale;
 40  
 
 41  
 import org.apache.commons.collections.IteratorUtils;
 42  
 import org.apache.commons.collections.iterators.IteratorChain;
 43  
 import org.apache.commons.collections.iterators.SingletonIterator;
 44  
 import org.apache.commons.lang.BooleanUtils;
 45  
 import org.apache.commons.lang.StringUtils;
 46  
 import org.apache.commons.lang.SystemUtils;
 47  
 
 48  
 /**
 49  
  * A utility class to convert the configuration properties into any type.
 50  
  *
 51  
  * @author Emmanuel Bourg
 52  
  * @version $Revision: 589380 $, $Date: 2007-10-28 17:37:35 +0100 (So, 28 Okt 2007) $
 53  
  * @since 1.1
 54  
  */
 55  
 public final class PropertyConverter
 56  
 {
 57  
     /** Constant for the list delimiter as char.*/
 58  
     static final char LIST_ESC_CHAR = '\\';
 59  
 
 60  
     /** Constant for the list delimiter escaping character as string.*/
 61  60
     static final String LIST_ESCAPE = String.valueOf(LIST_ESC_CHAR);
 62  
 
 63  
     /** Constant for the prefix of hex numbers.*/
 64  
     private static final String HEX_PREFIX = "0x";
 65  
 
 66  
     /** Constant for the radix of hex numbers.*/
 67  
     private static final int HEX_RADIX = 16;
 68  
 
 69  
     /** Constant for the Java version 1.5.*/
 70  
     private static final float JAVA_VERSION_1_5 = 1.5f;
 71  
 
 72  
     /** Constant for the argument classes of the Number constructor that takes a String. */
 73  187
     private static final Class[] CONSTR_ARGS = {String.class};
 74  
 
 75  
     /** The fully qualified name of {@link javax.mail.internet.InternetAddress} */
 76  
     private static final String INTERNET_ADDRESS_CLASSNAME = "javax.mail.internet.InternetAddress";
 77  
 
 78  
     /**
 79  
      * Private constructor prevents instances from being created.
 80  
      */
 81  
     private PropertyConverter()
 82  0
     {
 83  
         // to prevent instanciation...
 84  0
     }
 85  
 
 86  
     /**
 87  
      * Converts the specified value to the target class. If the class is a
 88  
      * primitive type (Integer.TYPE, Boolean.TYPE, etc) the value returned
 89  
      * will use the wrapper type (Integer.class, Boolean.class, etc).
 90  
      *
 91  
      * @param cls   the target class of the converted value
 92  
      * @param value the value to convert
 93  
      * @param params optional parameters used for the conversion
 94  
      * @return the converted value
 95  
      * @throws ConversionException if the value is not compatible with the requested type
 96  
      *
 97  
      * @since 1.5
 98  
      */
 99  
     static Object to(Class cls, Object value, Object[] params) throws ConversionException
 100  
     {
 101  378
         if (Boolean.class.equals(cls) || Boolean.TYPE.equals(cls))
 102  
         {
 103  29
             return toBoolean(value);
 104  
         }
 105  349
         else if (Number.class.isAssignableFrom(cls) || cls.isPrimitive())
 106  
         {
 107  224
             if (Integer.class.equals(cls) || Integer.TYPE.equals(cls))
 108  
             {
 109  28
                 return toInteger(value);
 110  
             }
 111  196
             else if (Long.class.equals(cls) || Long.TYPE.equals(cls))
 112  
             {
 113  28
                 return toLong(value);
 114  
             }
 115  168
             else if (Byte.class.equals(cls) || Byte.TYPE.equals(cls))
 116  
             {
 117  28
                 return toByte(value);
 118  
             }
 119  140
             else if (Short.class.equals(cls) || Short.TYPE.equals(cls))
 120  
             {
 121  28
                 return toShort(value);
 122  
             }
 123  112
             else if (Float.class.equals(cls) || Float.TYPE.equals(cls))
 124  
             {
 125  28
                 return toFloat(value);
 126  
             }
 127  84
             else if (Double.class.equals(cls) || Double.TYPE.equals(cls))
 128  
             {
 129  28
                 return toDouble(value);
 130  
             }
 131  56
             else if (BigInteger.class.equals(cls))
 132  
             {
 133  28
                 return toBigInteger(value);
 134  
             }
 135  28
             else if (BigDecimal.class.equals(cls))
 136  
             {
 137  28
                 return toBigDecimal(value);
 138  
             }
 139  
         }
 140  125
         else if (Date.class.equals(cls))
 141  
         {
 142  8
             return toDate(value, (String) params[0]);
 143  
         }
 144  117
         else if (Calendar.class.equals(cls))
 145  
         {
 146  8
             return toCalendar(value, (String) params[0]);
 147  
         }
 148  109
         else if (URL.class.equals(cls))
 149  
         {
 150  31
             return toURL(value);
 151  
         }
 152  78
         else if (Locale.class.equals(cls))
 153  
         {
 154  36
             return toLocale(value);
 155  
         }
 156  42
         else if (isEnum(cls))
 157  
         {
 158  0
             return toEnum(value, cls);
 159  
         }
 160  42
         else if (Color.class.equals(cls))
 161  
         {
 162  32
             return toColor(value);
 163  
         }
 164  10
         else if (cls.getName().equals(INTERNET_ADDRESS_CLASSNAME))
 165  
         {
 166  5
             return toInternetAddress(value);
 167  
         }
 168  5
         else if (InetAddress.class.isAssignableFrom(cls))
 169  
         {
 170  5
             return toInetAddress(value);
 171  
         }
 172  
 
 173  0
         throw new ConversionException("The value '" + value + "' (" + value.getClass() + ")"
 174  
                 + " can't be converted to a " + cls.getName() + " object");
 175  
     }
 176  
 
 177  
     /**
 178  
      * Convert the specified object into a Boolean. Internally the
 179  
      * <code>org.apache.commons.lang.BooleanUtils</code> class from the
 180  
      * <a href="http://commons.apache.org/lang/">Commons Lang</a>
 181  
      * project is used to perform this conversion. This class accepts some more
 182  
      * tokens for the boolean value of <b>true</b>, e.g. <code>yes</code> and
 183  
      * <code>on</code>. Please refer to the documentation of this class for more
 184  
      * details.
 185  
      *
 186  
      * @param value the value to convert
 187  
      * @return the converted value
 188  
      * @throws ConversionException thrown if the value cannot be converted to a boolean
 189  
      */
 190  
     public static Boolean toBoolean(Object value) throws ConversionException
 191  
     {
 192  125
         if (value instanceof Boolean)
 193  
         {
 194  41
             return (Boolean) value;
 195  
         }
 196  84
         else if (value instanceof String)
 197  
         {
 198  81
             Boolean b = BooleanUtils.toBooleanObject((String) value);
 199  81
             if (b == null)
 200  
             {
 201  5
                 throw new ConversionException("The value " + value + " can't be converted to a Boolean object");
 202  
             }
 203  76
             return b;
 204  
         }
 205  
         else
 206  
         {
 207  3
             throw new ConversionException("The value " + value + " can't be converted to a Boolean object");
 208  
         }
 209  
     }
 210  
 
 211  
     /**
 212  
      * Convert the specified object into a Byte.
 213  
      *
 214  
      * @param value the value to convert
 215  
      * @return the converted value
 216  
      * @throws ConversionException thrown if the value cannot be converted to a byte
 217  
      */
 218  
     public static Byte toByte(Object value) throws ConversionException
 219  
     {
 220  46
         Number n = toNumber(value, Byte.class);
 221  40
         if (n instanceof Byte)
 222  
         {
 223  38
             return (Byte) n;
 224  
         }
 225  
         else
 226  
         {
 227  2
             return new Byte(n.byteValue());
 228  
         }
 229  
     }
 230  
 
 231  
     /**
 232  
      * Convert the specified object into a Short.
 233  
      *
 234  
      * @param value the value to convert
 235  
      * @return the converted value
 236  
      * @throws ConversionException thrown if the value cannot be converted to a short
 237  
      */
 238  
     public static Short toShort(Object value) throws ConversionException
 239  
     {
 240  50
         Number n = toNumber(value, Short.class);
 241  44
         if (n instanceof Short)
 242  
         {
 243  43
             return (Short) n;
 244  
         }
 245  
         else
 246  
         {
 247  1
             return new Short(n.shortValue());
 248  
         }
 249  
     }
 250  
 
 251  
     /**
 252  
      * Convert the specified object into an Integer.
 253  
      *
 254  
      * @param value the value to convert
 255  
      * @return the converted value
 256  
      * @throws ConversionException thrown if the value cannot be converted to an integer
 257  
      */
 258  
     public static Integer toInteger(Object value) throws ConversionException
 259  
     {
 260  86
         Number n = toNumber(value, Integer.class);
 261  82
         if (n instanceof Integer)
 262  
         {
 263  81
             return (Integer) n;
 264  
         }
 265  
         else
 266  
         {
 267  1
             return new Integer(n.intValue());
 268  
         }
 269  
     }
 270  
 
 271  
     /**
 272  
      * Convert the specified object into a Long.
 273  
      *
 274  
      * @param value the value to convert
 275  
      * @return the converted value
 276  
      * @throws ConversionException thrown if the value cannot be converted to a Long
 277  
      */
 278  
     public static Long toLong(Object value) throws ConversionException
 279  
     {
 280  47
         Number n = toNumber(value, Long.class);
 281  41
         if (n instanceof Long)
 282  
         {
 283  38
             return (Long) n;
 284  
         }
 285  
         else
 286  
         {
 287  3
             return new Long(n.longValue());
 288  
         }
 289  
     }
 290  
 
 291  
     /**
 292  
      * Convert the specified object into a Float.
 293  
      *
 294  
      * @param value the value to convert
 295  
      * @return the converted value
 296  
      * @throws ConversionException thrown if the value cannot be converted to a Float
 297  
      */
 298  
     public static Float toFloat(Object value) throws ConversionException
 299  
     {
 300  45
         Number n = toNumber(value, Float.class);
 301  39
         if (n instanceof Float)
 302  
         {
 303  38
             return (Float) n;
 304  
         }
 305  
         else
 306  
         {
 307  1
             return new Float(n.floatValue());
 308  
         }
 309  
     }
 310  
 
 311  
     /**
 312  
      * Convert the specified object into a Double.
 313  
      *
 314  
      * @param value the value to convert
 315  
      * @return the converted value
 316  
      * @throws ConversionException thrown if the value cannot be converted to a Double
 317  
      */
 318  
     public static Double toDouble(Object value) throws ConversionException
 319  
     {
 320  48
         Number n = toNumber(value, Double.class);
 321  42
         if (n instanceof Double)
 322  
         {
 323  41
             return (Double) n;
 324  
         }
 325  
         else
 326  
         {
 327  1
             return new Double(n.doubleValue());
 328  
         }
 329  
     }
 330  
 
 331  
     /**
 332  
      * Convert the specified object into a BigInteger.
 333  
      *
 334  
      * @param value the value to convert
 335  
      * @return the converted value
 336  
      * @throws ConversionException thrown if the value cannot be converted to a BigInteger
 337  
      */
 338  
     public static BigInteger toBigInteger(Object value) throws ConversionException
 339  
     {
 340  37
         Number n = toNumber(value, BigInteger.class);
 341  31
         if (n instanceof BigInteger)
 342  
         {
 343  30
             return (BigInteger) n;
 344  
         }
 345  
         else
 346  
         {
 347  1
             return BigInteger.valueOf(n.longValue());
 348  
         }
 349  
     }
 350  
 
 351  
     /**
 352  
      * Convert the specified object into a BigDecimal.
 353  
      *
 354  
      * @param value the value to convert
 355  
      * @return the converted value
 356  
      * @throws ConversionException thrown if the value cannot be converted to a BigDecimal
 357  
      */
 358  
     public static BigDecimal toBigDecimal(Object value) throws ConversionException
 359  
     {
 360  36
         Number n = toNumber(value, BigDecimal.class);
 361  30
         if (n instanceof BigDecimal)
 362  
         {
 363  29
             return (BigDecimal) n;
 364  
         }
 365  
         else
 366  
         {
 367  1
             return new BigDecimal(n.doubleValue());
 368  
         }
 369  
     }
 370  
 
 371  
     /**
 372  
      * Tries to convert the specified object into a number object. This method
 373  
      * is used by the conversion methods for number types. Note that the return
 374  
      * value is not in always of the specified target class, but only if a new
 375  
      * object has to be created.
 376  
      *
 377  
      * @param value the value to be converted (must not be <b>null</b>)
 378  
      * @param targetClass the target class of the conversion (must be derived
 379  
      * from <code>java.lang.Number</code>)
 380  
      * @return the converted number
 381  
      * @throws ConversionException if the object cannot be converted
 382  
      */
 383  
     static Number toNumber(Object value, Class targetClass) throws ConversionException
 384  
     {
 385  403
         if (value instanceof Number)
 386  
         {
 387  101
             return (Number) value;
 388  
         }
 389  
         else
 390  
         {
 391  302
             String str = value.toString();
 392  302
             if (str.startsWith(HEX_PREFIX))
 393  
             {
 394  
                 try
 395  
                 {
 396  7
                     return new BigInteger(str.substring(HEX_PREFIX.length()), HEX_RADIX);
 397  
                 }
 398  1
                 catch (NumberFormatException nex)
 399  
                 {
 400  1
                     throw new ConversionException("Could not convert " + str
 401  
                             + " to " + targetClass.getName()
 402  
                             + "! Invalid hex number.", nex);
 403  
                 }
 404  
             }
 405  
 
 406  
             try
 407  
             {
 408  295
                 Constructor constr = targetClass.getConstructor(CONSTR_ARGS);
 409  294
                 return (Number) constr.newInstance(new Object[]{str});
 410  
             }
 411  47
             catch (InvocationTargetException itex)
 412  
             {
 413  47
                 throw new ConversionException("Could not convert " + str
 414  
                         + " to " + targetClass.getName(), itex
 415  
                         .getTargetException());
 416  
             }
 417  1
             catch (Exception ex)
 418  
             {
 419  
                 // Treat all possible exceptions the same way
 420  1
                 throw new ConversionException(
 421  
                         "Conversion error when trying to convert " + str
 422  
                                 + " to " + targetClass.getName(), ex);
 423  
             }
 424  
         }
 425  
     }
 426  
 
 427  
     /**
 428  
      * Convert the specified object into an URL.
 429  
      *
 430  
      * @param value the value to convert
 431  
      * @return the converted value
 432  
      * @throws ConversionException thrown if the value cannot be converted to an URL
 433  
      */
 434  
     public static URL toURL(Object value) throws ConversionException
 435  
     {
 436  31
         if (value instanceof URL)
 437  
         {
 438  11
             return (URL) value;
 439  
         }
 440  20
         else if (value instanceof String)
 441  
         {
 442  
             try
 443  
             {
 444  18
                 return new URL((String) value);
 445  
             }
 446  2
             catch (MalformedURLException e)
 447  
             {
 448  2
                 throw new ConversionException("The value " + value + " can't be converted to an URL", e);
 449  
             }
 450  
         }
 451  
         else
 452  
         {
 453  2
             throw new ConversionException("The value " + value + " can't be converted to an URL");
 454  
         }
 455  
     }
 456  
 
 457  
     /**
 458  
      * Convert the specified object into a Locale.
 459  
      *
 460  
      * @param value the value to convert
 461  
      * @return the converted value
 462  
      * @throws ConversionException thrown if the value cannot be converted to a Locale
 463  
      */
 464  
     public static Locale toLocale(Object value) throws ConversionException
 465  
     {
 466  36
         if (value instanceof Locale)
 467  
         {
 468  10
             return (Locale) value;
 469  
         }
 470  26
         else if (value instanceof String)
 471  
         {
 472  24
             List elements = split((String) value, '_');
 473  24
             int size = elements.size();
 474  
 
 475  24
             if (size >= 1 && (((String) elements.get(0)).length() == 2 || ((String) elements.get(0)).length() == 0))
 476  
             {
 477  22
                 String language = (String) elements.get(0);
 478  22
                 String country = (String) ((size >= 2) ? elements.get(1) : "");
 479  22
                 String variant = (String) ((size >= 3) ? elements.get(2) : "");
 480  
 
 481  22
                 return new Locale(language, country, variant);
 482  
             }
 483  
             else
 484  
             {
 485  2
                 throw new ConversionException("The value " + value + " can't be converted to a Locale");
 486  
             }
 487  
         }
 488  
         else
 489  
         {
 490  2
             throw new ConversionException("The value " + value + " can't be converted to a Locale");
 491  
         }
 492  
     }
 493  
 
 494  
     /**
 495  
      * Split a string on the specified delimiter. To be removed when
 496  
      * commons-lang has a better replacement available (Tokenizer?).
 497  
      *
 498  
      * todo: replace with a commons-lang equivalent
 499  
      *
 500  
      * @param s          the string to split
 501  
      * @param delimiter  the delimiter
 502  
      * @return a list with the single tokens
 503  
      */
 504  
     public static List split(String s, char delimiter)
 505  
     {
 506  14899
         if (s == null)
 507  
         {
 508  1
             return new ArrayList();
 509  
         }
 510  
 
 511  14898
         List list = new ArrayList();
 512  
 
 513  14898
         StringBuffer token = new StringBuffer();
 514  14898
         int begin = 0;
 515  14898
         boolean inEscape = false;
 516  
 
 517  182690
         while (begin < s.length())
 518  
         {
 519  167792
             char c = s.charAt(begin);
 520  167792
             if (inEscape)
 521  
             {
 522  
                 // last character was the escape marker
 523  
                 // can current character be escaped?
 524  4856
                 if (c != delimiter && c != LIST_ESC_CHAR)
 525  
                 {
 526  
                     // no, also add escape character
 527  3600
                     token.append(LIST_ESC_CHAR);
 528  
                 }
 529  4856
                 token.append(c);
 530  4856
                 inEscape = false;
 531  4856
             }
 532  
 
 533  
             else
 534  
             {
 535  162936
                 if (c == delimiter)
 536  
                 {
 537  
                     // found a list delimiter -> add token and reset buffer
 538  4142
                     list.add(token.toString().trim());
 539  4142
                     token = new StringBuffer();
 540  4142
                 }
 541  158794
                 else if (c == LIST_ESC_CHAR)
 542  
                 {
 543  
                     // eventually escape next character
 544  4879
                     inEscape = true;
 545  4879
                 }
 546  
                 else
 547  
                 {
 548  153915
                     token.append(c);
 549  
                 }
 550  
             }
 551  
 
 552  167792
             begin++;
 553  167792
         }
 554  
 
 555  
         // Trailing delimiter?
 556  14898
         if (inEscape)
 557  
         {
 558  23
             token.append(LIST_ESC_CHAR);
 559  
         }
 560  
         // Add last token
 561  14898
         list.add(token.toString().trim());
 562  
 
 563  14898
         return list;
 564  
     }
 565  
 
 566  
     /**
 567  
      * Escapes the delimiters that might be contained in the given string. This
 568  
      * method ensures that list delimiter characters that are part of a
 569  
      * property's value are correctly escaped when a configuration is saved to a
 570  
      * file. Otherwise when loaded again the property will be treated as a list
 571  
      * property. A single backslash will also be escaped.
 572  
      *
 573  
      * @param s the string with the value
 574  
      * @param delimiter the list delimiter to use
 575  
      * @return the correctly esaped string
 576  
      */
 577  
     public static String escapeDelimiters(String s, char delimiter)
 578  
     {
 579  628
         String s1 = StringUtils.replace(s, LIST_ESCAPE, LIST_ESCAPE + LIST_ESCAPE);
 580  628
         return StringUtils.replace(s1, String.valueOf(delimiter), LIST_ESCAPE + delimiter);
 581  
     }
 582  
 
 583  
     /**
 584  
      * Convert the specified object into a Color. If the value is a String,
 585  
      * the format allowed is (#)?[0-9A-F]{6}([0-9A-F]{2})?. Examples:
 586  
      * <ul>
 587  
      *   <li>FF0000 (red)</li>
 588  
      *   <li>0000FFA0 (semi transparent blue)</li>
 589  
      *   <li>#CCCCCC (gray)</li>
 590  
      *   <li>#00FF00A0 (semi transparent green)</li>
 591  
      * </ul>
 592  
      *
 593  
      * @param value the value to convert
 594  
      * @return the converted value
 595  
      * @throws ConversionException thrown if the value cannot be converted to a Color
 596  
      */
 597  
     public static Color toColor(Object value) throws ConversionException
 598  
     {
 599  32
         if (value instanceof Color)
 600  
         {
 601  10
             return (Color) value;
 602  
         }
 603  22
         else if (value instanceof String && !StringUtils.isBlank((String) value))
 604  
         {
 605  20
             String color = ((String) value).trim();
 606  
 
 607  20
             int[] components = new int[3];
 608  
 
 609  
             // check the size of the string
 610  20
             int minlength = components.length * 2;
 611  20
             if (color.length() < minlength)
 612  
             {
 613  0
                 throw new ConversionException("The value " + value + " can't be converted to a Color");
 614  
             }
 615  
 
 616  
             // remove the leading #
 617  20
             if (color.startsWith("#"))
 618  
             {
 619  2
                 color = color.substring(1);
 620  
             }
 621  
 
 622  
             try
 623  
             {
 624  
                 // parse the components
 625  74
                 for (int i = 0; i < components.length; i++)
 626  
                 {
 627  56
                     components[i] = Integer.parseInt(color.substring(2 * i, 2 * i + 2), HEX_RADIX);
 628  
                 }
 629  
 
 630  
                 // parse the transparency
 631  
                 int alpha;
 632  18
                 if (color.length() >= minlength + 2)
 633  
                 {
 634  1
                     alpha = Integer.parseInt(color.substring(minlength, minlength + 2), HEX_RADIX);
 635  1
                 }
 636  
                 else
 637  
                 {
 638  17
                     alpha = Color.black.getAlpha();
 639  
                 }
 640  
 
 641  18
                 return new Color(components[0], components[1], components[2], alpha);
 642  
             }
 643  2
             catch (Exception e)
 644  
             {
 645  2
                 throw new ConversionException("The value " + value + " can't be converted to a Color", e);
 646  
             }
 647  
         }
 648  
         else
 649  
         {
 650  2
             throw new ConversionException("The value " + value + " can't be converted to a Color");
 651  
         }
 652  
     }
 653  
 
 654  
     /**
 655  
      * Convert the specified value into an internet address.
 656  
      *
 657  
      * @param value the value to convert
 658  
      * @return the converted value
 659  
      * @throws ConversionException thrown if the value cannot be converted to a InetAddress
 660  
      *
 661  
      * @since 1.5
 662  
      */
 663  
     static InetAddress toInetAddress(Object value) throws ConversionException
 664  
     {
 665  5
         if (value instanceof InetAddress)
 666  
         {
 667  1
             return (InetAddress) value;
 668  
         }
 669  4
         else if (value instanceof String)
 670  
         {
 671  
             try
 672  
             {
 673  3
                 return InetAddress.getByName((String) value);
 674  
             }
 675  1
             catch (UnknownHostException e)
 676  
             {
 677  1
                 throw new ConversionException("The value " + value + " can't be converted to a InetAddress", e);
 678  
             }
 679  
         }
 680  
         else
 681  
         {
 682  1
             throw new ConversionException("The value " + value + " can't be converted to a InetAddress");
 683  
         }
 684  
     }
 685  
 
 686  
     /**
 687  
      * Convert the specified value into an email address.
 688  
      *
 689  
      * @param value the value to convert
 690  
      * @return the converted value
 691  
      * @throws ConversionException thrown if the value cannot be converted to an email address
 692  
      *
 693  
      * @since 1.5
 694  
      */
 695  
     static Object toInternetAddress(Object value) throws ConversionException
 696  
     {
 697  5
         if (value.getClass().getName().equals(INTERNET_ADDRESS_CLASSNAME))
 698  
         {
 699  1
             return value;
 700  
         }
 701  4
         else if (value instanceof String)
 702  
         {
 703  
             try
 704  
             {
 705  3
                 Constructor ctor = Class.forName(INTERNET_ADDRESS_CLASSNAME).getConstructor(new Class[] {String.class});
 706  3
                 return ctor.newInstance(new Object[] {value});
 707  
             }
 708  1
             catch (Exception e)
 709  
             {
 710  1
                 throw new ConversionException("The value " + value + " can't be converted to a InternetAddress", e);
 711  
             }
 712  
         }
 713  
         else
 714  
         {
 715  1
             throw new ConversionException("The value " + value + " can't be converted to a InternetAddress");
 716  
         }
 717  
     }
 718  
 
 719  
     /**
 720  
      * Calls Class.isEnum() on Java 5, returns false on older JRE.
 721  
      */
 722  
     static boolean isEnum(Class cls)
 723  
     {
 724  42
         if (!SystemUtils.isJavaVersionAtLeast(JAVA_VERSION_1_5))
 725  
         {
 726  0
             return false;
 727  
         }
 728  
 
 729  
         try
 730  
         {
 731  42
             Method isEnumMethod = Class.class.getMethod("isEnum", new Class[] {});
 732  42
             return ((Boolean) isEnumMethod.invoke(cls, new Object[] {})).booleanValue();
 733  
         }
 734  0
         catch (Exception e)
 735  
         {
 736  
             // impossible
 737  0
             throw new RuntimeException(e.getMessage());
 738  
         }
 739  
     }
 740  
 
 741  
     /**
 742  
      * Convert the specified value into a Java 5 enum.
 743  
      *
 744  
      * @param value the value to convert
 745  
      * @param cls   the type of the enumeration
 746  
      * @return the converted value
 747  
      * @throws ConversionException thrown if the value cannot be converted to an enumeration
 748  
      *
 749  
      * @since 1.5
 750  
      */
 751  
     static Object toEnum(Object value, Class cls) throws ConversionException
 752  
     {
 753  5
         if (value.getClass().equals(cls))
 754  
         {
 755  1
             return value;
 756  
         }
 757  4
         else if (value instanceof String)
 758  
         {
 759  
             try
 760  
             {
 761  2
                 Method valueOfMethod = cls.getMethod("valueOf", new Class[] {String.class});
 762  2
                 return valueOfMethod.invoke(null, new Object[] {value});
 763  
             }
 764  1
             catch (Exception e)
 765  
             {
 766  1
                 throw new ConversionException("The value " + value + " can't be converted to a " + cls.getName());
 767  
             }
 768  
         }
 769  2
         else if (value instanceof Number)
 770  
         {
 771  
             try
 772  
             {
 773  2
                 Method valuesMethod = cls.getMethod("values", new Class[] {});
 774  2
                 Object valuesArray = valuesMethod.invoke(null, new Object[] {});
 775  
 
 776  2
                 return Array.get(valuesArray, ((Number) value).intValue());
 777  
             }
 778  1
             catch (Exception e)
 779  
             {
 780  1
                 throw new ConversionException("The value " + value + " can't be converted to a " + cls.getName());
 781  
             }
 782  
         }
 783  
         else
 784  
         {
 785  0
             throw new ConversionException("The value " + value + " can't be converted to a " + cls.getName());
 786  
         }
 787  
     }
 788  
 
 789  
     /**
 790  
      * Convert the specified object into a Date.
 791  
      *
 792  
      * @param value  the value to convert
 793  
      * @param format the DateFormat pattern to parse String values
 794  
      * @return the converted value
 795  
      * @throws ConversionException thrown if the value cannot be converted to a Calendar
 796  
      */
 797  
     public static Date toDate(Object value, String format) throws ConversionException
 798  
     {
 799  49
         if (value instanceof Date)
 800  
         {
 801  15
             return (Date) value;
 802  
         }
 803  34
         else if (value instanceof Calendar)
 804  
         {
 805  5
             return ((Calendar) value).getTime();
 806  
         }
 807  29
         else if (value instanceof String)
 808  
         {
 809  
             try
 810  
             {
 811  26
                 return new SimpleDateFormat(format).parse((String) value);
 812  
             }
 813  3
             catch (ParseException e)
 814  
             {
 815  3
                 throw new ConversionException("The value " + value + " can't be converted to a Date", e);
 816  
             }
 817  
         }
 818  
         else
 819  
         {
 820  3
             throw new ConversionException("The value " + value + " can't be converted to a Date");
 821  
         }
 822  
     }
 823  
 
 824  
     /**
 825  
      * Convert the specified object into a Calendar.
 826  
      *
 827  
      * @param value  the value to convert
 828  
      * @param format the DateFormat pattern to parse String values
 829  
      * @return the converted value
 830  
      * @throws ConversionException thrown if the value cannot be converted to a Calendar
 831  
      */
 832  
     public static Calendar toCalendar(Object value, String format) throws ConversionException
 833  
     {
 834  49
         if (value instanceof Calendar)
 835  
         {
 836  10
             return (Calendar) value;
 837  
         }
 838  39
         else if (value instanceof Date)
 839  
         {
 840  10
             Calendar calendar = Calendar.getInstance();
 841  10
             calendar.setTime((Date) value);
 842  10
             return calendar;
 843  
         }
 844  29
         else if (value instanceof String)
 845  
         {
 846  
             try
 847  
             {
 848  26
                 Calendar calendar = Calendar.getInstance();
 849  26
                 calendar.setTime(new SimpleDateFormat(format).parse((String) value));
 850  23
                 return calendar;
 851  
             }
 852  3
             catch (ParseException e)
 853  
             {
 854  3
                 throw new ConversionException("The value " + value + " can't be converted to a Calendar", e);
 855  
             }
 856  
         }
 857  
         else
 858  
         {
 859  3
             throw new ConversionException("The value " + value + " can't be converted to a Calendar");
 860  
         }
 861  
     }
 862  
 
 863  
     /**
 864  
      * Return an iterator over the simple values of a composite value. The value
 865  
      * specified is handled depending on its type:
 866  
      * <ul>
 867  
      *   <li>Strings are checked for delimiter characters and splitted if necessary.</li>
 868  
      *   <li>For collections the single elements are checked.</li>
 869  
      *   <li>Arrays are treated like collections.</li>
 870  
      *   <li>All other types are directly inserted.</li>
 871  
      *   <li>Recursive combinations are supported, e.g. a collection containing array that contain strings.</li>
 872  
      * </ul>
 873  
      *
 874  
      * @param value     the value to "split"
 875  
      * @param delimiter the delimiter for String values
 876  
      * @return an iterator for accessing the single values
 877  
      */
 878  
     public static Iterator toIterator(Object value, char delimiter)
 879  
     {
 880  37625
         if (value == null)
 881  
         {
 882  5
             return IteratorUtils.emptyIterator();
 883  
         }
 884  37620
         if (value instanceof String)
 885  
         {
 886  28539
             String s = (String) value;
 887  28539
             if (s.indexOf(delimiter) > 0)
 888  
             {
 889  2431
                 return split((String) value, delimiter).iterator();
 890  
             }
 891  
             else
 892  
             {
 893  26108
                 return new SingletonIterator(value);
 894  
             }
 895  
         }
 896  9081
         else if (value instanceof Collection)
 897  
         {
 898  747
             return toIterator(((Collection) value).iterator(), delimiter);
 899  
         }
 900  8334
         else if (value.getClass().isArray())
 901  
         {
 902  8
             return toIterator(IteratorUtils.arrayIterator(value), delimiter);
 903  
         }
 904  8326
         else if (value instanceof Iterator)
 905  
         {
 906  755
             Iterator iterator = (Iterator) value;
 907  755
             IteratorChain chain = new IteratorChain();
 908  2563
             while (iterator.hasNext())
 909  
             {
 910  1808
                 chain.addIterator(toIterator(iterator.next(), delimiter));
 911  1808
             }
 912  755
             return chain;
 913  
         }
 914  
         else
 915  
         {
 916  7571
             return new SingletonIterator(value);
 917  
         }
 918  
     }
 919  
 
 920  
     /**
 921  
      * Performs interpolation of the specified value. This method checks if the
 922  
      * given value contains variables of the form <code>${...}</code>. If
 923  
      * this is the case, all occurrances will be substituted by their current
 924  
      * values.
 925  
      *
 926  
      * @param value the value to be interpolated
 927  
      * @param config the current configuration object
 928  
      * @return the interpolated value
 929  
      */
 930  
     public static Object interpolate(Object value, AbstractConfiguration config)
 931  
     {
 932  2866
         if (value instanceof String)
 933  
         {
 934  2077
             return config.getSubstitutor().replace((String) value);
 935  
         }
 936  
         else
 937  
         {
 938  789
             return value;
 939  
         }
 940  
     }
 941  
 }