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 }