View Javadoc

    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.reloading;
    19
    20  import java.io.File;
    21  import java.net.MalformedURLException;
    22  import java.net.URL;
    23
    24  import org.apache.commons.configuration.ConfigurationUtils;
    25  import org.apache.commons.configuration.FileConfiguration;
    26
    27  /***
    28   * <p>A reloading strategy that will reload the configuration every time its
    29   * underlying file is changed.</p>
    30   * <p>This reloading strategy does not actively monitor a configuration file,
    31   * but is triggered by its associated configuration whenever properties are
    32   * accessed. It then checks the configuration file's last modification date
    33   * and causes a reload if this has changed.</p>
    34   * <p>To avoid permanent disc access on successive property lookups a refresh
    35   * delay can be specified. This has the effect that the configuration file's
    36   * last modification date is only checked once in this delay period. The default
    37   * value for this refresh delay is 5 seconds.</p>
    38   * <p>This strategy only works with FileConfiguration instances.</p>
    39   *
    40   * @author Emmanuel Bourg
    41   * @version $Revision: 606798 $, $Date: 2007-12-25 20:05:58 +0100 (Di, 25 Dez 2007) $
    42   * @since 1.1
    43   */
    44  public class FileChangedReloadingStrategy implements ReloadingStrategy
    45  {
    46      /*** Constant for the jar URL protocol.*/
    47      private static final String JAR_PROTOCOL = "jar";
    48
    49      /*** Constant for the default refresh delay.*/
    50      private static final int DEFAULT_REFRESH_DELAY = 5000;
    51
    52      /*** Stores a reference to the configuration to be monitored.*/
    53      protected FileConfiguration configuration;
    54
    55      /*** The last time the configuration file was modified. */
    56      protected long lastModified;
    57
    58      /*** The last time the file was checked for changes. */
    59      protected long lastChecked;
    60
    61      /*** The minimum delay in milliseconds between checks. */
    62      protected long refreshDelay = DEFAULT_REFRESH_DELAY;
    63
    64      /*** A flag whether a reload is required.*/
    65      private boolean reloading;
    66
    67      public void setConfiguration(FileConfiguration configuration)
    68      {
    69          this.configuration = configuration;
    70      }
    71
    72      public void init()
    73      {
    74          updateLastModified();
    75      }
    76
    77      public boolean reloadingRequired()
    78      {
    79          if (!reloading)
    80          {
    81              long now = System.currentTimeMillis();
    82
    83              if (now > lastChecked + refreshDelay)
    84              {
    85                  lastChecked = now;
    86                  if (hasChanged())
    87                  {
    88                      reloading = true;
    89                  }
    90              }
    91          }
    92
    93          return reloading;
    94      }
    95
    96      public void reloadingPerformed()
    97      {
    98          updateLastModified();
    99      }
    100
    101     /***
    102      * Return the minimal time in milliseconds between two reloadings.
    103      *
    104      * @return the refresh delay (in milliseconds)
    105      */
    106     public long getRefreshDelay()
    107     {
    108         return refreshDelay;
    109     }
    110
    111     /***
    112      * Set the minimal time between two reloadings.
    113      *
    114      * @param refreshDelay refresh delay in milliseconds
    115      */
    116     public void setRefreshDelay(long refreshDelay)
    117     {
    118         this.refreshDelay = refreshDelay;
    119     }
    120
    121     /***
    122      * Update the last modified time.
    123      */
    124     protected void updateLastModified()
    125     {
    126         File file = getFile();
    127         if (file != null)
    128         {
    129             lastModified = file.lastModified();
    130         }
    131         reloading = false;
    132     }
    133
    134     /***
    135      * Check if the configuration has changed since the last time it was loaded.
    136      *
    137      * @return a flag whether the configuration has changed
    138      */
    139     protected boolean hasChanged()
    140     {
    141         File file = getFile();
    142         if (file == null || !file.exists())
    143         {
    144             return false;
    145         }
    146
    147         return file.lastModified() > lastModified;
    148     }
    149
    150     /***
    151      * Returns the file that is monitored by this strategy. Note that the return
    152      * value can be <b>null </b> under some circumstances.
    153      *
    154      * @return the monitored file
    155      */
    156     protected File getFile()
    157     {
    158         return (configuration.getURL() != null) ? fileFromURL(configuration
    159                 .getURL()) : configuration.getFile();
    160     }
    161
    162     /***
    163      * Helper method for transforming a URL into a file object. This method
    164      * handles file: and jar: URLs.
    165      *
    166      * @param url the URL to be converted
    167      * @return the resulting file or <b>null </b>
    168      */
    169     private File fileFromURL(URL url)
    170     {
    171         if (JAR_PROTOCOL.equals(url.getProtocol()))
    172         {
    173             String path = url.getPath();
    174             try
    175             {
    176                 return ConfigurationUtils.fileFromURL(new URL(path.substring(0,
    177                         path.indexOf('!'))));
    178             }
    179             catch (MalformedURLException mex)
    180             {
    181                 return null;
    182             }
    183         }
    184         else
    185         {
    186             return ConfigurationUtils.fileFromURL(url);
    187         }
    188     }
    189 }