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