Coverage Report - org.apache.commons.configuration.ConfigurationUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ConfigurationUtils
85%
153/179
100%
39/39
4,65
ConfigurationUtils$1
100%
2/2
N/A
4,65
 
 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.io.File;
 21  
 import java.io.IOException;
 22  
 import java.io.InputStream;
 23  
 import java.io.PrintStream;
 24  
 import java.io.PrintWriter;
 25  
 import java.io.StringWriter;
 26  
 import java.lang.reflect.InvocationTargetException;
 27  
 import java.lang.reflect.Method;
 28  
 import java.net.MalformedURLException;
 29  
 import java.net.URL;
 30  
 import java.net.URLDecoder;
 31  
 import java.util.Iterator;
 32  
 
 33  
 import org.apache.commons.configuration.event.ConfigurationErrorEvent;
 34  
 import org.apache.commons.configuration.event.ConfigurationErrorListener;
 35  
 import org.apache.commons.configuration.event.EventSource;
 36  
 import org.apache.commons.lang.StringUtils;
 37  
 import org.apache.commons.logging.Log;
 38  
 import org.apache.commons.logging.LogFactory;
 39  
 
 40  
 /**
 41  
  * Miscellaneous utility methods for configurations.
 42  
  *
 43  
  * @see ConfigurationConverter Utility methods to convert configurations.
 44  
  *
 45  
  * @author <a href="mailto:herve.quiroz@esil.univ-mrs.fr">Herve Quiroz</a>
 46  
  * @author <a href="mailto:oliver.heger@t-online.de">Oliver Heger</a>
 47  
  * @author Emmanuel Bourg
 48  
  * @version $Revision: 567771 $, $Date: 2007-08-20 19:57:08 +0200 (Mo, 20 Aug 2007) $
 49  
  */
 50  
 public final class ConfigurationUtils
 51  
 {
 52  
     /** Constant for the file URL protocol.*/
 53  
     static final String PROTOCOL_FILE = "file";
 54  
 
 55  
     /** Constant for the resource path separator.*/
 56  
     static final String RESOURCE_PATH_SEPARATOR = "/";
 57  
 
 58  
     /** Constant for the name of the clone() method.*/
 59  
     private static final String METHOD_CLONE = "clone";
 60  
 
 61  
     /** The logger.*/
 62  64
     private static Log log = LogFactory.getLog(ConfigurationUtils.class);
 63  
 
 64  
     /**
 65  
      * Private constructor. Prevents instances from being created.
 66  
      */
 67  
     private ConfigurationUtils()
 68  0
     {
 69  
         // to prevent instanciation...
 70  0
     }
 71  
 
 72  
     /**
 73  
      * Dump the configuration key/value mappings to some ouput stream.
 74  
      *
 75  
      * @param configuration the configuration
 76  
      * @param out the output stream to dump the configuration to
 77  
      */
 78  
     public static void dump(Configuration configuration, PrintStream out)
 79  
     {
 80  0
         dump(configuration, new PrintWriter(out));
 81  0
     }
 82  
 
 83  
     /**
 84  
      * Dump the configuration key/value mappings to some writer.
 85  
      *
 86  
      * @param configuration the configuration
 87  
      * @param out the writer to dump the configuration to
 88  
      */
 89  
     public static void dump(Configuration configuration, PrintWriter out)
 90  
     {
 91  5
         Iterator keys = configuration.getKeys();
 92  11
         while (keys.hasNext())
 93  
         {
 94  6
             String key = (String) keys.next();
 95  6
             Object value = configuration.getProperty(key);
 96  6
             out.print(key);
 97  6
             out.print("=");
 98  6
             out.print(value);
 99  
 
 100  6
             if (keys.hasNext())
 101  
             {
 102  2
                 out.println();
 103  
             }
 104  6
         }
 105  
 
 106  5
         out.flush();
 107  5
     }
 108  
 
 109  
     /**
 110  
      * Get a string representation of the key/value mappings of a
 111  
      * configuration.
 112  
      *
 113  
      * @param configuration the configuration
 114  
      * @return a string representation of the configuration
 115  
      */
 116  
     public static String toString(Configuration configuration)
 117  
     {
 118  5
         StringWriter writer = new StringWriter();
 119  5
         dump(configuration, new PrintWriter(writer));
 120  5
         return writer.toString();
 121  
     }
 122  
 
 123  
     /**
 124  
      * <p>Copy all properties from the source configuration to the target
 125  
      * configuration. Properties in the target configuration are replaced with
 126  
      * the properties with the same key in the source configuration.</p>
 127  
      * <p><em>Note:</em> This method is not able to handle some specifics of
 128  
      * configurations derived from <code>AbstractConfiguration</code> (e.g.
 129  
      * list delimiters). For a full support of all of these features the
 130  
      * <code>copy()</code> method of <code>AbstractConfiguration</code> should
 131  
      * be used. In a future release this method might become deprecated.</p>
 132  
      *
 133  
      * @param source the source configuration
 134  
      * @param target the target configuration
 135  
      * @since 1.1
 136  
      */
 137  
     public static void copy(Configuration source, Configuration target)
 138  
     {
 139  54
         Iterator keys = source.getKeys();
 140  1162
         while (keys.hasNext())
 141  
         {
 142  1108
             String key = (String) keys.next();
 143  1108
             target.setProperty(key, source.getProperty(key));
 144  1108
         }
 145  54
     }
 146  
 
 147  
     /**
 148  
      * <p>Append all properties from the source configuration to the target
 149  
      * configuration. Properties in the source configuration are appended to
 150  
      * the properties with the same key in the target configuration.</p>
 151  
      * <p><em>Note:</em> This method is not able to handle some specifics of
 152  
      * configurations derived from <code>AbstractConfiguration</code> (e.g.
 153  
      * list delimiters). For a full support of all of these features the
 154  
      * <code>copy()</code> method of <code>AbstractConfiguration</code> should
 155  
      * be used. In a future release this method might become deprecated.</p>
 156  
      *
 157  
      * @param source the source configuration
 158  
      * @param target the target configuration
 159  
      * @since 1.1
 160  
      */
 161  
     public static void append(Configuration source, Configuration target)
 162  
     {
 163  1
         Iterator keys = source.getKeys();
 164  3
         while (keys.hasNext())
 165  
         {
 166  2
             String key = (String) keys.next();
 167  2
             target.addProperty(key, source.getProperty(key));
 168  2
         }
 169  1
     }
 170  
 
 171  
     /**
 172  
      * Converts the passed in configuration to a hierarchical one. If the
 173  
      * configuration is already hierarchical, it is directly returned. Otherwise
 174  
      * all properties are copied into a new hierarchical configuration.
 175  
      *
 176  
      * @param conf the configuration to convert
 177  
      * @return the new hierarchical configuration (the result is <b>null</b> if
 178  
      * and only if the passed in configuration is <b>null</b>)
 179  
      * @since 1.3
 180  
      */
 181  
     public static HierarchicalConfiguration convertToHierarchical(
 182  
             Configuration conf)
 183  
     {
 184  94
         if (conf == null)
 185  
         {
 186  1
             return null;
 187  
         }
 188  
 
 189  93
         if (conf instanceof HierarchicalConfiguration)
 190  
         {
 191  48
             return (HierarchicalConfiguration) conf;
 192  
         }
 193  
         else
 194  
         {
 195  45
             HierarchicalConfiguration hc = new HierarchicalConfiguration();
 196  
             // Workaround for problem with copy()
 197  45
             boolean delimiterParsingStatus = hc.isDelimiterParsingDisabled();
 198  45
             hc.setDelimiterParsingDisabled(true);
 199  45
             ConfigurationUtils.copy(conf, hc);
 200  45
             hc.setDelimiterParsingDisabled(delimiterParsingStatus);
 201  45
             return hc;
 202  
         }
 203  
     }
 204  
 
 205  
     /**
 206  
      * Clones the given configuration object if this is possible. If the passed
 207  
      * in configuration object implements the <code>Cloneable</code>
 208  
      * interface, its <code>clone()</code> method will be invoked. Otherwise
 209  
      * an exception will be thrown.
 210  
      *
 211  
      * @param config the configuration object to be cloned (can be <b>null</b>)
 212  
      * @return the cloned configuration (<b>null</b> if the argument was
 213  
      * <b>null</b>, too)
 214  
      * @throws ConfigurationRuntimeException if cloning is not supported for
 215  
      * this object
 216  
      * @since 1.3
 217  
      */
 218  
     public static Configuration cloneConfiguration(Configuration config)
 219  
             throws ConfigurationRuntimeException
 220  
     {
 221  12
         if (config == null)
 222  
         {
 223  1
             return null;
 224  
         }
 225  
         else
 226  
         {
 227  
             try
 228  
             {
 229  11
                 return (Configuration) clone(config);
 230  
             }
 231  2
             catch (CloneNotSupportedException cnex)
 232  
             {
 233  2
                 throw new ConfigurationRuntimeException(cnex);
 234  
             }
 235  
         }
 236  
     }
 237  
 
 238  
     /**
 239  
      * An internally used helper method for cloning objects. This implementation
 240  
      * is not very sophisticated nor efficient. Maybe it can be replaced by an
 241  
      * implementation from Commons Lang later. The method checks whether the
 242  
      * passed in object implements the <code>Cloneable</code> interface. If
 243  
      * this is the case, the <code>clone()</code> method is invoked by
 244  
      * reflection. Errors that occur during the cloning process are re-thrown as
 245  
      * runtime exceptions.
 246  
      *
 247  
      * @param obj the object to be cloned
 248  
      * @return the cloned object
 249  
      * @throws CloneNotSupportedException if the object cannot be cloned
 250  
      */
 251  
     static Object clone(Object obj) throws CloneNotSupportedException
 252  
     {
 253  23
         if (obj instanceof Cloneable)
 254  
         {
 255  
             try
 256  
             {
 257  21
                 Method m = obj.getClass().getMethod(METHOD_CLONE, null);
 258  21
                 return m.invoke(obj, null);
 259  
             }
 260  0
             catch (NoSuchMethodException nmex)
 261  
             {
 262  0
                 throw new CloneNotSupportedException(
 263  
                         "No clone() method found for class"
 264  
                                 + obj.getClass().getName());
 265  
             }
 266  0
             catch (IllegalAccessException iaex)
 267  
             {
 268  0
                 throw new ConfigurationRuntimeException(iaex);
 269  
             }
 270  0
             catch (InvocationTargetException itex)
 271  
             {
 272  0
                 throw new ConfigurationRuntimeException(itex);
 273  
             }
 274  
         }
 275  
         else
 276  
         {
 277  2
             throw new CloneNotSupportedException(obj.getClass().getName()
 278  
                     + " does not implement Cloneable");
 279  
         }
 280  
     }
 281  
 
 282  
     /**
 283  
      * Constructs a URL from a base path and a file name. The file name can
 284  
      * be absolute, relative or a full URL. If necessary the base path URL is
 285  
      * applied.
 286  
      *
 287  
      * @param basePath the base path URL (can be <b>null</b>)
 288  
      * @param file the file name
 289  
      * @return the resulting URL
 290  
      * @throws MalformedURLException if URLs are invalid
 291  
      */
 292  
     public static URL getURL(String basePath, String file) throws MalformedURLException
 293  
     {
 294  8
         File f = new File(file);
 295  8
         if (f.isAbsolute()) // already absolute?
 296  
         {
 297  2
             return f.toURL();
 298  
         }
 299  
 
 300  
         try
 301  
         {
 302  6
             if (basePath == null)
 303  
             {
 304  2
                 return new URL(file);
 305  
             }
 306  
             else
 307  
             {
 308  4
                 URL base = new URL(basePath);
 309  3
                 return new URL(base, file);
 310  
             }
 311  
         }
 312  2
         catch (MalformedURLException uex)
 313  
         {
 314  2
             return constructFile(basePath, file).toURL();
 315  
         }
 316  
     }
 317  
 
 318  
     /**
 319  
      * Helper method for constructing a file object from a base path and a
 320  
      * file name. This method is called if the base path passed to
 321  
      * <code>getURL()</code> does not seem to be a valid URL.
 322  
      *
 323  
      * @param basePath the base path
 324  
      * @param fileName the file name
 325  
      * @return the resulting file
 326  
      */
 327  
     static File constructFile(String basePath, String fileName)
 328  
     {
 329  553
         File file = null;
 330  
 
 331  553
         File absolute = null;
 332  553
         if (fileName != null)
 333  
         {
 334  553
             absolute = new File(fileName);
 335  
         }
 336  
 
 337  553
         if (StringUtils.isEmpty(basePath) || (absolute != null && absolute.isAbsolute()))
 338  
         {
 339  57
             file = new File(fileName);
 340  57
         }
 341  
         else
 342  
         {
 343  496
             StringBuffer fName = new StringBuffer();
 344  496
             fName.append(basePath);
 345  
 
 346  
             // My best friend. Paranoia.
 347  496
             if (!basePath.endsWith(File.separator))
 348  
             {
 349  496
                 fName.append(File.separator);
 350  
             }
 351  
 
 352  
             //
 353  
             // We have a relative path, and we have
 354  
             // two possible forms here. If we have the
 355  
             // "./" form then just strip that off first
 356  
             // before continuing.
 357  
             //
 358  496
             if (fileName.startsWith("." + File.separator))
 359  
             {
 360  0
                 fName.append(fileName.substring(2));
 361  0
             }
 362  
             else
 363  
             {
 364  496
                 fName.append(fileName);
 365  
             }
 366  
 
 367  496
             file = new File(fName.toString());
 368  
         }
 369  
 
 370  553
         return file;
 371  
     }
 372  
 
 373  
     /**
 374  
      * Return the location of the specified resource by searching the user home
 375  
      * directory, the current classpath and the system classpath.
 376  
      *
 377  
      * @param name the name of the resource
 378  
      *
 379  
      * @return the location of the resource
 380  
      */
 381  
     public static URL locate(String name)
 382  
     {
 383  0
         return locate(null, name);
 384  
     }
 385  
 
 386  
     /**
 387  
      * Return the location of the specified resource by searching the user home
 388  
      * directory, the current classpath and the system classpath.
 389  
      *
 390  
      * @param base the base path of the resource
 391  
      * @param name the name of the resource
 392  
      *
 393  
      * @return the location of the resource
 394  
      */
 395  
     public static URL locate(String base, String name)
 396  
     {
 397  1140
         if (log.isDebugEnabled())
 398  
         {
 399  0
             StringBuffer buf = new StringBuffer();
 400  0
             buf.append("ConfigurationUtils.locate(): base is ").append(base);
 401  0
             buf.append(", name is ").append(name);
 402  0
             log.debug(buf.toString());
 403  
         }
 404  
 
 405  1140
         if (name == null)
 406  
         {
 407  
             // undefined, always return null
 408  4
             return null;
 409  
         }
 410  
 
 411  1136
         URL url = null;
 412  
 
 413  
         // attempt to create an URL directly
 414  
         try
 415  
         {
 416  1136
             if (base == null)
 417  
             {
 418  329
                 url = new URL(name);
 419  0
             }
 420  
             else
 421  
             {
 422  807
                 URL baseURL = new URL(base);
 423  410
                 url = new URL(baseURL, name);
 424  
 
 425  
                 // check if the file exists
 426  408
                 InputStream in = null;
 427  
                 try
 428  
                 {
 429  408
                     in = url.openStream();
 430  
                 }
 431  
                 finally
 432  
                 {
 433  408
                     if (in != null)
 434  
                     {
 435  390
                         in.close();
 436  390
                     }
 437  18
                 }
 438  
             }
 439  
 
 440  390
             log.debug("Loading configuration from the URL " + url);
 441  
         }
 442  746
         catch (IOException e)
 443  
         {
 444  746
             url = null;
 445  390
         }
 446  
 
 447  
         // attempt to load from an absolute path
 448  1136
         if (url == null)
 449  
         {
 450  746
             File file = new File(name);
 451  746
             if (file.isAbsolute() && file.exists()) // already absolute?
 452  
             {
 453  
                 try
 454  
                 {
 455  282
                     url = file.toURL();
 456  282
                     log.debug("Loading configuration from the absolute path " + name);
 457  
                 }
 458  0
                 catch (MalformedURLException e)
 459  
                 {
 460  0
                     log.warn("Could not obtain URL from file", e);
 461  282
                 }
 462  
             }
 463  
         }
 464  
 
 465  
         // attempt to load from the base directory
 466  1136
         if (url == null)
 467  
         {
 468  
             try
 469  
             {
 470  464
                 File file = constructFile(base, name);
 471  464
                 if (file != null && file.exists())
 472  
                 {
 473  413
                     url = file.toURL();
 474  
                 }
 475  
 
 476  464
                 if (url != null)
 477  
                 {
 478  413
                     log.debug("Loading configuration from the path " + file);
 479  
                 }
 480  
             }
 481  0
             catch (MalformedURLException e)
 482  
             {
 483  0
                 log.warn("Could not obtain URL from file", e);
 484  464
             }
 485  
         }
 486  
 
 487  
         // attempt to load from the user home directory
 488  1136
         if (url == null)
 489  
         {
 490  
             try
 491  
             {
 492  51
                 File file = constructFile(System.getProperty("user.home"), name);
 493  51
                 if (file != null && file.exists())
 494  
                 {
 495  1
                     url = file.toURL();
 496  
                 }
 497  
 
 498  51
                 if (url != null)
 499  
                 {
 500  1
                     log.debug("Loading configuration from the home path " + file);
 501  
                 }
 502  
 
 503  
             }
 504  0
             catch (MalformedURLException e)
 505  
             {
 506  0
                 log.warn("Could not obtain URL from file", e);
 507  51
             }
 508  
         }
 509  
 
 510  
         // attempt to load from classpath
 511  1136
         if (url == null)
 512  
         {
 513  50
             url = locateFromClasspath(name);
 514  
         }
 515  1136
         return url;
 516  
     }
 517  
 
 518  
     /**
 519  
      * Tries to find a resource with the given name in the classpath.
 520  
      * @param resourceName the name of the resource
 521  
      * @return the URL to the found resource or <b>null</b> if the resource
 522  
      * cannot be found
 523  
      */
 524  
     static URL locateFromClasspath(String resourceName)
 525  
     {
 526  50
         URL url = null;
 527  
         // attempt to load from the context classpath
 528  50
         ClassLoader loader = Thread.currentThread().getContextClassLoader();
 529  50
         if (loader != null)
 530  
         {
 531  49
             url = loader.getResource(resourceName);
 532  
 
 533  49
             if (url != null)
 534  
             {
 535  20
                 log.debug("Loading configuration from the context classpath (" + resourceName + ")");
 536  
             }
 537  
         }
 538  
 
 539  
         // attempt to load from the system classpath
 540  50
         if (url == null)
 541  
         {
 542  30
             url = ClassLoader.getSystemResource(resourceName);
 543  
 
 544  30
             if (url != null)
 545  
             {
 546  0
                 log.debug("Loading configuration from the system classpath (" + resourceName + ")");
 547  
             }
 548  
         }
 549  50
         return url;
 550  
     }
 551  
 
 552  
     /**
 553  
      * Return the path without the file name, for example http://xyz.net/foo/bar.xml
 554  
      * results in http://xyz.net/foo/
 555  
      *
 556  
      * @param url the URL from which to extract the path
 557  
      * @return the path component of the passed in URL
 558  
      */
 559  
     static String getBasePath(URL url)
 560  
     {
 561  20
         if (url == null)
 562  
         {
 563  0
             return null;
 564  
         }
 565  
 
 566  20
         String s = url.toString();
 567  
 
 568  20
         if (s.endsWith("/") || StringUtils.isEmpty(url.getPath()))
 569  
         {
 570  3
             return s;
 571  
         }
 572  
         else
 573  
         {
 574  17
             return s.substring(0, s.lastIndexOf("/") + 1);
 575  
         }
 576  
     }
 577  
 
 578  
     /**
 579  
      * Extract the file name from the specified URL.
 580  
      *
 581  
      * @param url the URL from which to extract the file name
 582  
      * @return the extracted file name
 583  
      */
 584  
     static String getFileName(URL url)
 585  
     {
 586  18
         if (url == null)
 587  
         {
 588  1
             return null;
 589  
         }
 590  
 
 591  17
         String path = url.getPath();
 592  
 
 593  17
         if (path.endsWith("/") || StringUtils.isEmpty(path))
 594  
         {
 595  1
             return null;
 596  
         }
 597  
         else
 598  
         {
 599  16
             return path.substring(path.lastIndexOf("/") + 1);
 600  
         }
 601  
     }
 602  
 
 603  
     /**
 604  
      * Tries to convert the specified base path and file name into a file object.
 605  
      * This method is called e.g. by the save() methods of file based
 606  
      * configurations. The parameter strings can be relative files, absolute
 607  
      * files and URLs as well. This implementation checks first whether the passed in
 608  
      * file name is absolute. If this is the case, it is returned. Otherwise
 609  
      * further checks are performed whether the base path and file name can be
 610  
      * combined to a valid URL or a valid file name. <em>Note:</em> The test
 611  
      * if the passed in file name is absolute is performed using
 612  
      * <code>java.io.File.isAbsolute()</code>. If the file name starts with a
 613  
      * slash, this method will return <b>true</b> on Unix, but <b>false</b> on
 614  
      * Windows. So to ensure correct behavior for relative file names on all
 615  
      * platforms you should never let relative paths start with a slash. E.g.
 616  
      * in a configuration definition file do not use something like that:
 617  
      * <pre>
 618  
      * &lt;properties fileName="/subdir/my.properties"/&gt;
 619  
      * </pre>
 620  
      * Under Windows this path would be resolved relative to the configuration
 621  
      * definition file. Under Unix this would be treated as an absolute path
 622  
      * name.
 623  
      *
 624  
      * @param basePath the base path
 625  
      * @param fileName the file name
 626  
      * @return the file object (<b>null</b> if no file can be obtained)
 627  
      */
 628  
     public static File getFile(String basePath, String fileName)
 629  
     {
 630  
         // Check if the file name is absolute
 631  49
         File f = new File(fileName);
 632  49
         if (f.isAbsolute())
 633  
         {
 634  8
             return f;
 635  
         }
 636  
 
 637  
         // Check if URLs are involved
 638  
         URL url;
 639  
         try
 640  
         {
 641  41
             url = new URL(new URL(basePath), fileName);
 642  
         }
 643  38
         catch (MalformedURLException mex1)
 644  
         {
 645  
             try
 646  
             {
 647  38
                 url = new URL(fileName);
 648  
             }
 649  36
             catch (MalformedURLException mex2)
 650  
             {
 651  36
                 url = null;
 652  2
             }
 653  3
         }
 654  
 
 655  41
         if (url != null)
 656  
         {
 657  5
             return fileFromURL(url);
 658  
         }
 659  
 
 660  36
         return constructFile(basePath, fileName);
 661  
     }
 662  
 
 663  
     /**
 664  
      * Tries to convert the specified URL to a file object. If this fails,
 665  
      * <b>null</b> is returned.
 666  
      *
 667  
      * @param url the URL
 668  
      * @return the resulting file object
 669  
      */
 670  
     public static File fileFromURL(URL url)
 671  
     {
 672  1421
         if (PROTOCOL_FILE.equals(url.getProtocol()))
 673  
         {
 674  1415
             return new File(URLDecoder.decode(url.getPath()));
 675  
         }
 676  
         else
 677  
         {
 678  6
             return null;
 679  
         }
 680  
     }
 681  
 
 682  
     /**
 683  
      * Enables runtime exceptions for the specified configuration object. This
 684  
      * method can be used for configuration implementations that may face errors
 685  
      * on normal property access, e.g. <code>DatabaseConfiguration</code> or
 686  
      * <code>JNDIConfiguration</code>. Per default such errors are simply
 687  
      * logged and then ignored. This implementation will register a special
 688  
      * <code>{@link ConfigurationErrorListener}</code> that throws a runtime
 689  
      * exception (namely a <code>ConfigurationRuntimeException</code>) on
 690  
      * each received error event.
 691  
      *
 692  
      * @param src the configuration, for which runtime exceptions are to be
 693  
      * enabled; this configuration must be derived from
 694  
      * <code>{@link EventSource}</code>
 695  
      */
 696  
     public static void enableRuntimeExceptions(Configuration src)
 697  
     {
 698  3
         if (!(src instanceof EventSource))
 699  
         {
 700  2
             throw new IllegalArgumentException(
 701  
                     "Configuration must be derived from EventSource!");
 702  
         }
 703  1
         ((EventSource) src).addErrorListener(new ConfigurationErrorListener()
 704  
         {
 705  1
             public void configurationError(ConfigurationErrorEvent event)
 706  
             {
 707  
                 // Throw a runtime exception
 708  1
                 throw new ConfigurationRuntimeException(event.getCause());
 709  
             }
 710  
         });
 711  1
     }
 712  
 }