Coverage report

  %line %branch
org.apache.commons.configuration.AbstractFileConfiguration
92% 
100% 

 1  
 /*
 2  
  * Copyright 2004-2005 The Apache Software Foundation.
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License")
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 
 17  
 package org.apache.commons.configuration;
 18  
 
 19  
 import java.io.File;
 20  
 import java.io.FileOutputStream;
 21  
 import java.io.IOException;
 22  
 import java.io.InputStream;
 23  
 import java.io.InputStreamReader;
 24  
 import java.io.OutputStream;
 25  
 import java.io.OutputStreamWriter;
 26  
 import java.io.Reader;
 27  
 import java.io.UnsupportedEncodingException;
 28  
 import java.io.Writer;
 29  
 import java.net.URL;
 30  
 import java.util.Iterator;
 31  
 
 32  
 import org.apache.commons.configuration.reloading.InvariantReloadingStrategy;
 33  
 import org.apache.commons.configuration.reloading.ReloadingStrategy;
 34  
 import org.apache.commons.lang.StringUtils;
 35  
 
 36  
 /**
 37  
  * <p>Partial implementation of the <code>FileConfiguration</code> interface.
 38  
  * Developpers of file based configuration may want to extend this class,
 39  
  * the two methods left to implement are <code>{@link FileConfiguration#load(Reader)}</code>
 40  
  * and <code>{@link FileConfiguration#save(Writer)}.</p>
 41  
  * <p>This base class already implements a couple of ways to specify the location
 42  
  * of the file this configuration is based on. The following possibilities
 43  
  * exist:
 44  
  * <ul><li>URLs: With the method <code>setURL()</code> a full URL to the
 45  
  * configuration source can be specified. This is the most flexible way. Note
 46  
  * that the <code>save()</code> methods support only <em>file:</em> URLs.</li>
 47  
  * <li>Files: The <code>setFile()</code> method allows to specify the
 48  
  * configuration source as a file. This can be either a relative or an
 49  
  * absolute file. In the former case the file is resolved based on the current
 50  
  * directory.</li>
 51  
  * <li>As file paths in string form: With the <code>setPath()</code> method a
 52  
  * full path to a configuration file can be provided as a string.</li>
 53  
  * <li>Separated as base path and file name: This is the native form in which
 54  
  * the location is stored. The base path is a string defining either a local
 55  
  * directory or a URL. It can be set using the <code>setBasePath()</code>
 56  
  * method. The file name, non surprisingly, defines the name of the configuration
 57  
  * file.</li></ul></p>
 58  
  * <p>Note that the <code>load()</code> methods do not wipe out the configuration's
 59  
  * content before the new configuration file is loaded. Thus it is very easy to
 60  
  * construct a union configuration by simply loading multiple configuration
 61  
  * files, e.g.</p>
 62  
  * <p><pre>
 63  
  * config.load(configFile1);
 64  
  * config.load(configFile2);
 65  
  * </pre></p>
 66  
  * <p>After executing this code fragment, the resulting configuration will
 67  
  * contain both the properties of configFile1 and configFile2. On the other
 68  
  * hand, if the current configuration file is to be reloaded, <code>clear()</code>
 69  
  * should be called first. Otherwise the properties are doubled. This behavior
 70  
  * is analogous to the behavior of the <code>load(InputStream)</code> method
 71  
  * in <code>java.util.Properties</code>.</p>
 72  
  *
 73  
  * @author Emmanuel Bourg
 74  
  * @version $Revision$, $Date: 2005-12-14 20:59:07 +0100 (Wed, 14 Dec 2005) $
 75  
  * @since 1.0-rc2
 76  
  */
 77  
 public abstract class AbstractFileConfiguration extends BaseConfiguration implements FileConfiguration
 78  
 {
 79  
     /** Stores the file name.*/
 80  
     protected String fileName;
 81  
 
 82  
     /** Stores the base path.*/
 83  
     protected String basePath;
 84  
 
 85  
     /** The auto save flag.*/
 86  
     protected boolean autoSave;
 87  
 
 88  
     /** Holds a reference to the reloading strategy.*/
 89  
     protected ReloadingStrategy strategy;
 90  
 
 91  
     /** A lock object for protecting reload operations.*/
 92  1720
     private Object reloadLock = new Object();
 93  
 
 94  
     /** Stores the encoding of the configuration file.*/
 95  
     private String encoding;
 96  
 
 97  
     /** Stores the URL from which the configuration file was loaded.*/
 98  
     private URL sourceURL;
 99  
 
 100  
     /** A counter that prohibits reloading.*/
 101  
     private int noReload;
 102  
 
 103  
     /**
 104  
      * Default constructor
 105  
      *
 106  
      * @since 1.1
 107  
      */
 108  
     public AbstractFileConfiguration()
 109  1720
     {
 110  1720
         setReloadingStrategy(new InvariantReloadingStrategy());
 111  1720
     }
 112  
 
 113  
     /**
 114  
      * Creates and loads the configuration from the specified file. The passed
 115  
      * in string must be a valid file name, either absolute or relativ.
 116  
      *
 117  
      * @param fileName The name of the file to load.
 118  
      *
 119  
      * @throws ConfigurationException Error while loading the file
 120  
      * @since 1.1
 121  
      */
 122  
     public AbstractFileConfiguration(String fileName) throws ConfigurationException
 123  
     {
 124  579
         this();
 125  
 
 126  
         // store the file name
 127  579
         setPath(fileName);
 128  
 
 129  
         // load the file
 130  579
         load();
 131  573
     }
 132  
 
 133  
     /**
 134  
      * Creates and loads the configuration from the specified file.
 135  
      *
 136  
      * @param file The file to load.
 137  
      * @throws ConfigurationException Error while loading the file
 138  
      * @since 1.1
 139  
      */
 140  
     public AbstractFileConfiguration(File file) throws ConfigurationException
 141  
     {
 142  15
         this();
 143  
 
 144  
         // set the file and update the url, the base path and the file name
 145  15
         setFile(file);
 146  
 
 147  
         // load the file
 148  15
         if (file.exists())
 149  
         {
 150  12
             load();
 151  
         }
 152  12
     }
 153  
 
 154  
     /**
 155  
      * Creates and loads the configuration from the specified URL.
 156  
      *
 157  
      * @param url The location of the file to load.
 158  
      * @throws ConfigurationException Error while loading the file
 159  
      * @since 1.1
 160  
      */
 161  
     public AbstractFileConfiguration(URL url) throws ConfigurationException
 162  
     {
 163  3
         this();
 164  
 
 165  
         // set the URL and update the base path and the file name
 166  3
         setURL(url);
 167  
 
 168  
         // load the file
 169  3
         load();
 170  3
     }
 171  
 
 172  
     /**
 173  
      * Load the configuration from the underlying location.
 174  
      *
 175  
      * @throws ConfigurationException if loading of the configuration fails
 176  
      */
 177  
     public void load() throws ConfigurationException
 178  
     {
 179  1236
         if (sourceURL != null)
 180  
         {
 181  44
             load(sourceURL);
 182  
         }
 183  
         else
 184  
         {
 185  1192
             load(getFileName());
 186  
         }
 187  1200
     }
 188  
 
 189  
     /**
 190  
      * Locate the specified file and load the configuration. This does not
 191  
      * change the source of the configuration (i.e. the internally maintained file name).
 192  
      * Use one of the setter methods for this purpose.
 193  
      *
 194  
      * @param fileName the name of the file to be loaded
 195  
      * @throws ConfigurationException if an error occurs
 196  
      */
 197  
     public void load(String fileName) throws ConfigurationException
 198  
     {
 199  
         try
 200  
         {
 201  1207
             URL url = ConfigurationUtils.locate(basePath, fileName);
 202  
 
 203  1207
             if (url == null)
 204  
             {
 205  27
                 throw new ConfigurationException("Cannot locate configuration source " + fileName);
 206  
             }
 207  1180
             load(url);
 208  1168
         }
 209  
         catch (ConfigurationException e)
 210  
         {
 211  39
             throw e;
 212  
         }
 213  
         catch (Exception e)
 214  
         {
 215  0
             throw new ConfigurationException(e.getMessage(), e);
 216  
         }
 217  1168
     }
 218  
 
 219  
     /**
 220  
      * Load the configuration from the specified file. This does not change
 221  
      * the source of the configuration (i.e. the internally maintained file
 222  
      * name). Use one of the setter methods for this purpose.
 223  
      *
 224  
      * @param file the file to load
 225  
      * @throws ConfigurationException if an error occurs
 226  
      */
 227  
     public void load(File file) throws ConfigurationException
 228  
     {
 229  
         try
 230  
         {
 231  36
             load(file.toURL());
 232  27
         }
 233  
         catch (ConfigurationException e)
 234  
         {
 235  9
             throw e;
 236  
         }
 237  
         catch (Exception e)
 238  
         {
 239  0
             throw new ConfigurationException(e.getMessage(), e);
 240  
         }
 241  27
     }
 242  
 
 243  
     /**
 244  
      * Load the configuration from the specified URL. This does not change the
 245  
      * source of the configuration (i.e. the internally maintained file name).
 246  
      * Use on of the setter methods for this purpose.
 247  
      *
 248  
      * @param url the URL of the file to be loaded
 249  
      * @throws ConfigurationException if an error occurs
 250  
      */
 251  
     public void load(URL url) throws ConfigurationException
 252  
     {
 253  1710
         if (sourceURL == null)
 254  
         {
 255  1216
             if (StringUtils.isEmpty(getBasePath()))
 256  
             {
 257  
                 // ensure that we have a valid base path
 258  186
                 setBasePath(url.toString());
 259  
             }
 260  1216
             sourceURL = url;
 261  
         }
 262  
 
 263  
         // throw an exception if the target URL is a directory
 264  1710
         File file = ConfigurationUtils.fileFromURL(url);
 265  1710
         if (file != null && file.isDirectory())
 266  
         {
 267  12
             throw new ConfigurationException("Cannot load a configuration from a directory");
 268  
         }
 269  
 
 270  1698
         InputStream in = null;
 271  
 
 272  
         try
 273  
         {
 274  1698
             in = url.openStream();
 275  1698
             load(in);
 276  1689
         }
 277  
         catch (ConfigurationException e)
 278  
         {
 279  9
             throw e;
 280  
         }
 281  
         catch (Exception e)
 282  
         {
 283  0
             throw new ConfigurationException(e.getMessage(), e);
 284  
         }
 285  
         finally
 286  
         {
 287  
             // close the input stream
 288  9
             try
 289  
             {
 290  1698
                 if (in != null)
 291  
                 {
 292  1698
                     in.close();
 293  
                 }
 294  1698
             }
 295  
             catch (IOException e)
 296  
             {
 297  0
                 e.printStackTrace();
 298  1698
             }
 299  
         }
 300  1689
     }
 301  
 
 302  
     /**
 303  
      * Load the configuration from the specified stream, using the encoding
 304  
      * returned by {@link #getEncoding()}.
 305  
      *
 306  
      * @param in the input stream
 307  
      *
 308  
      * @throws ConfigurationException if an error occurs during the load operation
 309  
      */
 310  
     public void load(InputStream in) throws ConfigurationException
 311  
     {
 312  1251
         load(in, getEncoding());
 313  1248
     }
 314  
 
 315  
     /**
 316  
      * Load the configuration from the specified stream, using the specified
 317  
      * encoding. If the encoding is null the default encoding is used.
 318  
      *
 319  
      * @param in the input stream
 320  
      * @param encoding the encoding used. <code>null</code> to use the default encoding
 321  
      *
 322  
      * @throws ConfigurationException if an error occurs during the load operation
 323  
      */
 324  
     public void load(InputStream in, String encoding) throws ConfigurationException
 325  
     {
 326  1254
         Reader reader = null;
 327  
 
 328  1254
         if (encoding != null)
 329  
         {
 330  
             try
 331  
             {
 332  207
                 reader = new InputStreamReader(in, encoding);
 333  207
             }
 334  
             catch (UnsupportedEncodingException e)
 335  
             {
 336  0
                 throw new ConfigurationException(
 337  
                         "The requested encoding is not supported, try the default encoding.", e);
 338  
             }
 339  
         }
 340  
 
 341  1254
         if (reader == null)
 342  
         {
 343  1047
             reader = new InputStreamReader(in);
 344  
         }
 345  
 
 346  1254
         load(reader);
 347  1251
     }
 348  
 
 349  
     /**
 350  
      * Save the configuration. Before this method can be called a valid file
 351  
      * name must have been set.
 352  
      *
 353  
      * @throws ConfigurationException if an error occurs or no file name has
 354  
      * been set yet
 355  
      */
 356  
     public void save() throws ConfigurationException
 357  
     {
 358  51
         if (getFileName() == null)
 359  
         {
 360  12
             throw new ConfigurationException("No file name has been set!");
 361  
         }
 362  
 
 363  39
         if (sourceURL != null)
 364  
         {
 365  15
             save(sourceURL);
 366  
         }
 367  
         else
 368  
         {
 369  24
             save(fileName);
 370  
         }
 371  39
         strategy.init();
 372  39
     }
 373  
 
 374  
     /**
 375  
      * Save the configuration to the specified file. This doesn't change the
 376  
      * source of the configuration, use setFileName() if you need it.
 377  
      *
 378  
      * @param fileName the file name
 379  
      *
 380  
      * @throws ConfigurationException if an error occurs during the save operation
 381  
      */
 382  
     public void save(String fileName) throws ConfigurationException
 383  
     {
 384  
         try
 385  
         {
 386  42
             File file = ConfigurationUtils.getFile(basePath, fileName);
 387  42
             if (file == null)
 388  
             {
 389  3
                 throw new ConfigurationException("Invalid file name for save: " + fileName);
 390  
             }
 391  39
             save(file);
 392  39
         }
 393  
         catch (ConfigurationException e)
 394  
         {
 395  3
             throw e;
 396  
         }
 397  
         catch (Exception e)
 398  
         {
 399  0
             throw new ConfigurationException(e.getMessage(), e);
 400  
         }
 401  39
     }
 402  
 
 403  
     /**
 404  
      * Save the configuration to the specified URL if it's a file URL.
 405  
      * This doesn't change the source of the configuration, use setURL()
 406  
      * if you need it.
 407  
      *
 408  
      * @param url the URL
 409  
      *
 410  
      * @throws ConfigurationException if an error occurs during the save operation
 411  
      */
 412  
     public void save(URL url) throws ConfigurationException
 413  
     {
 414  21
         File file = ConfigurationUtils.fileFromURL(url);
 415  21
         if (file != null)
 416  
         {
 417  18
             save(file);
 418  
         }
 419  
         else
 420  
         {
 421  3
             throw new ConfigurationException("Could not save to URL " + url);
 422  
         }
 423  18
     }
 424  
 
 425  
     /**
 426  
      * Save the configuration to the specified file. The file is created
 427  
      * automatically if it doesn't exist. This doesn't change the source
 428  
      * of the configuration, use {@link #setFile} if you need it.
 429  
      *
 430  
      * @param file the target file
 431  
      *
 432  
      * @throws ConfigurationException if an error occurs during the save operation
 433  
      */
 434  
     public void save(File file) throws ConfigurationException
 435  
     {
 436  81
         OutputStream out = null;
 437  
 
 438  
         try
 439  
         {
 440  
             // create the file if necessary
 441  81
             createPath(file);
 442  81
             out = new FileOutputStream(file);
 443  81
             save(out);
 444  81
         }
 445  
         catch (IOException e)
 446  
         {
 447  0
             throw new ConfigurationException(e.getMessage(), e);
 448  
         }
 449  
         finally
 450  
         {
 451  
             // close the output stream
 452  0
             try
 453  
             {
 454  81
                 if (out != null)
 455  
                 {
 456  81
                     out.close();
 457  
                 }
 458  81
             }
 459  
             catch (IOException e)
 460  
             {
 461  0
                 e.printStackTrace();
 462  81
             }
 463  
         }
 464  81
     }
 465  
 
 466  
     /**
 467  
      * Save the configuration to the specified stream, using the encoding
 468  
      * returned by {@link #getEncoding()}.
 469  
      *
 470  
      * @param out the output stream
 471  
      *
 472  
      * @throws ConfigurationException if an error occurs during the save operation
 473  
      */
 474  
     public void save(OutputStream out) throws ConfigurationException
 475  
     {
 476  84
         save(out, getEncoding());
 477  84
     }
 478  
 
 479  
     /**
 480  
      * Save the configuration to the specified stream, using the specified
 481  
      * encoding. If the encoding is null the default encoding is used.
 482  
      *
 483  
      * @param out the output stream
 484  
      * @param encoding the encoding to use
 485  
      * @throws ConfigurationException if an error occurs during the save operation
 486  
      */
 487  
     public void save(OutputStream out, String encoding) throws ConfigurationException
 488  
     {
 489  87
         Writer writer = null;
 490  
 
 491  87
         if (encoding != null)
 492  
         {
 493  
             try
 494  
             {
 495  42
                 writer = new OutputStreamWriter(out, encoding);
 496  42
             }
 497  
             catch (UnsupportedEncodingException e)
 498  
             {
 499  0
                 throw new ConfigurationException(
 500  
                         "The requested encoding is not supported, try the default encoding.", e);
 501  
             }
 502  
         }
 503  
 
 504  87
         if (writer == null)
 505  
         {
 506  45
             writer = new OutputStreamWriter(out);
 507  
         }
 508  
 
 509  87
         save(writer);
 510  87
     }
 511  
 
 512  
     /**
 513  
      * Return the name of the file.
 514  
      *
 515  
      * @return the file name
 516  
      */
 517  
     public String getFileName()
 518  
     {
 519  1579
         return fileName;
 520  
     }
 521  
 
 522  
     /**
 523  
      * Set the name of the file. The passed in file name should not contain a
 524  
      * path. Use <code>{@link AbstractFileConfiguration#setPath(String)
 525  
      * setPath()}</code> to set a full qualified file name.
 526  
      *
 527  
      * @param fileName the name of the file
 528  
      */
 529  
     public void setFileName(String fileName)
 530  
     {
 531  1396
         sourceURL = null;
 532  1396
         this.fileName = fileName;
 533  1396
     }
 534  
 
 535  
     /**
 536  
      * Return the base path.
 537  
      *
 538  
      * @return the base path
 539  
      */
 540  
     public String getBasePath()
 541  
     {
 542  1744
         return basePath;
 543  
     }
 544  
 
 545  
     /**
 546  
      * Set the base path. Relative configurations are loaded from this path. The
 547  
      * base path can be either a path to a directory or a URL.
 548  
      *
 549  
      * @param basePath the base path.
 550  
      */
 551  
     public void setBasePath(String basePath)
 552  
     {
 553  1315
         sourceURL = null;
 554  1315
         this.basePath = basePath;
 555  1315
     }
 556  
 
 557  
     /**
 558  
      * Return the file where the configuration is stored. If the base path is a
 559  
      * URL with a protocol different than &quot;file&quot;, the return value
 560  
      * will not point to a valid file object.
 561  
      *
 562  
      * @return the file where the configuration is stored; this can be <b>null</b>
 563  
      */
 564  
     public File getFile()
 565  
     {
 566  33
         if (getFileName() == null)
 567  
         {
 568  3
             return null;
 569  
         }
 570  
         else
 571  
         {
 572  30
             if (sourceURL != null)
 573  
             {
 574  3
                 return ConfigurationUtils.fileFromURL(sourceURL);
 575  
             }
 576  
             else
 577  
             {
 578  27
                 return ConfigurationUtils.getFile(getBasePath(), getFileName());
 579  
             }
 580  
         }
 581  
     }
 582  
 
 583  
     /**
 584  
      * Set the file where the configuration is stored. The passed in file is
 585  
      * made absolute if it is not yet. Then the file's path component becomes
 586  
      * the base path and its name component becomes the file name.
 587  
      *
 588  
      * @param file the file where the configuration is stored
 589  
      */
 590  
     public void setFile(File file)
 591  
     {
 592  924
         sourceURL = null;
 593  924
         setFileName(file.getName());
 594  924
         setBasePath((file.getParentFile() != null) ? file.getParentFile()
 595  
                 .getAbsolutePath() : null);
 596  924
     }
 597  
 
 598  
     /**
 599  
      * Returns the full path to the file this configuration is based on. The
 600  
      * return value is valid only if this configuration is based on a file on
 601  
      * the local disk.
 602  
      *
 603  
      * @return the full path to the configuration file
 604  
      */
 605  
     public String getPath()
 606  
     {
 607  6
         return getFile().getAbsolutePath();
 608  
     }
 609  
 
 610  
     /**
 611  
      * Sets the location of this configuration as a full path name. The passed
 612  
      * in path should represent a valid file name.
 613  
      *
 614  
      * @param path the full path name of the configuration file
 615  
      */
 616  
     public void setPath(String path)
 617  
     {
 618  582
         setFile(new File(path));
 619  582
     }
 620  
 
 621  
     /**
 622  
      * Return the URL where the configuration is stored.
 623  
      *
 624  
      * @return the configuration's location as URL
 625  
      */
 626  
     public URL getURL()
 627  
     {
 628  592
         return (sourceURL != null) ? sourceURL
 629  
                 : ConfigurationUtils.locate(getBasePath(), getFileName());
 630  
     }
 631  
 
 632  
     /**
 633  
      * Set the location of this configuration as a URL. For loading this can be
 634  
      * an arbitrary URL with a supported protocol. If the configuration is to
 635  
      * be saved, too, a URL with the &quot;file&quot; protocol should be
 636  
      * provided.
 637  
      *
 638  
      * @param url the location of this configuration as URL
 639  
      */
 640  
     public void setURL(URL url)
 641  
     {
 642  16
         setBasePath(ConfigurationUtils.getBasePath(url));
 643  16
         setFileName(ConfigurationUtils.getFileName(url));
 644  16
         sourceURL = url;
 645  6
     }
 646  
 
 647  
     public void setAutoSave(boolean autoSave)
 648  1554
     {
 649  2331
         this.autoSave = autoSave;
 650  777
     }
 651  
 
 652  
     public boolean isAutoSave()
 653  778
     {
 654  389
         return autoSave;
 655  
     }
 656  
 
 657  
     /**
 658  
      * Save the configuration if the automatic persistence is enabled
 659  
      * and if a file is specified.
 660  
      */
 661  
     protected void possiblySave()
 662  19196
     {
 663  9598
         if (autoSave && fileName != null)
 664  
         {
 665  
             try
 666  10
             {
 667  15
                 save();
 668  5
             }
 669  
             catch (ConfigurationException e)
 670  
             {
 671  0
                 throw new ConfigurationRuntimeException("Failed to auto-save", e);
 672  
             }
 673  19196
         }
 674  9598
     }
 675  
 
 676  
     protected void addPropertyDirect(String key, Object obj)
 677  18816
     {
 678  28224
         super.addPropertyDirect(key, obj);
 679  28224
         possiblySave();
 680  9408
     }
 681  
 
 682  
     public void clearProperty(String key)
 683  60
     {
 684  90
         super.clearProperty(key);
 685  90
         possiblySave();
 686  30
     }
 687  
 
 688  
     public ReloadingStrategy getReloadingStrategy()
 689  6
     {
 690  3
         return strategy;
 691  
     }
 692  
 
 693  
     public void setReloadingStrategy(ReloadingStrategy strategy)
 694  1160
     {
 695  1741
         this.strategy = strategy;
 696  1741
         strategy.setConfiguration(this);
 697  1741
         strategy.init();
 698  581
     }
 699  
 
 700  
     public void reload()
 701  22532
     {
 702  11266
         synchronized (reloadLock)
 703  22532
         {
 704  11266
             if (noReload == 0)
 705  
             {
 706  
                 try
 707  22122
                 {
 708  11061
                     enterNoReload(); // avoid reentrant calls
 709  22122
 
 710  11061
                     if (strategy.reloadingRequired())
 711  6
                     {
 712  9
                         clear();
 713  3
                         load();
 714  
 
 715  6
                         // notify the strategy
 716  3
                         strategy.reloadingPerformed();
 717  22122
                     }
 718  11061
                 }
 719  
                 catch (Exception e)
 720  
                 {
 721  0
                     e.printStackTrace();
 722  
                     // todo rollback the changes if the file can't be reloaded
 723  0
                 }
 724  
                 finally
 725  
                 {
 726  0
                     exitNoReload();
 727  
                 }
 728  22532
             }
 729  33798
         }
 730  11266
     }
 731  
 
 732  
     /**
 733  
      * Enters the &quot;No reloading mode&quot;. As long as this mode is active
 734  
      * no reloading will be performed. This is necessary for some
 735  
      * implementations of <code>save()</code> in derived classes, which may
 736  
      * cause a reload while accessing the properties to save. This may cause the
 737  
      * whole configuration to be erased. To avoid this, this method can be
 738  
      * called first. After a call to this method there always must be a
 739  
      * corresponding call of <code>{@link #exitNoReload()}</code> later! (If
 740  
      * necessary, <code>finally</code> blocks must be used to ensure this.
 741  
      */
 742  
     protected void enterNoReload()
 743  22146
     {
 744  11073
         synchronized (reloadLock)
 745  22146
         {
 746  33219
             noReload++;
 747  33219
         }
 748  11073
     }
 749  
 
 750  
     /**
 751  
      * Leaves the &quot;No reloading mode&quot;.
 752  
      *
 753  
      * @see #enterNoReload()
 754  
      */
 755  
     protected void exitNoReload()
 756  22146
     {
 757  11073
         synchronized (reloadLock)
 758  22146
         {
 759  11073
             if (noReload > 0) // paranoia check
 760  22146
             {
 761  11073
                 noReload--;
 762  22146
             }
 763  33219
         }
 764  11073
     }
 765  
 
 766  
     public Object getProperty(String key)
 767  19702
     {
 768  29553
         reload();
 769  9851
         return super.getProperty(key);
 770  
     }
 771  
 
 772  
     public boolean isEmpty()
 773  12
     {
 774  18
         reload();
 775  6
         return super.isEmpty();
 776  
     }
 777  
 
 778  
     public boolean containsKey(String key)
 779  646
     {
 780  969
         reload();
 781  323
         return super.containsKey(key);
 782  
     }
 783  
 
 784  
     public Iterator getKeys()
 785  112
     {
 786  168
         reload();
 787  56
         return super.getKeys();
 788  
     }
 789  
 
 790  
     /**
 791  
      * Create the path to the specified file.
 792  
      *
 793  
      * @param file the target file
 794  
      */
 795  
     private void createPath(File file)
 796  54
     {
 797  27
         if (file != null)
 798  
         {
 799  54
             // create the path to the file if the file doesn't exist
 800  27
             if (!file.exists())
 801  40
             {
 802  60
                 File parent = file.getParentFile();
 803  20
                 if (parent != null && !parent.exists())
 804  6
                 {
 805  3
                     parent.mkdirs();
 806  
                 }
 807  
             }
 808  54
         }
 809  27
     }
 810  
 
 811  
     public String getEncoding()
 812  938
     {
 813  469
         return encoding;
 814  
     }
 815  
 
 816  
     public void setEncoding(String encoding)
 817  530
     {
 818  796
         this.encoding = encoding;
 819  266
     }
 820  
 }

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