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 org.apache.commons.configuration.ConfigurationRuntimeException;
21  import org.apache.commons.configuration.FileConfiguration;
22  import org.apache.commons.configuration.FileSystem;
23  import org.apache.commons.configuration.FileSystemBased;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.commons.vfs2.FileObject;
27  import org.apache.commons.vfs2.FileSystemException;
28  import org.apache.commons.vfs2.FileSystemManager;
29  import org.apache.commons.vfs2.VFS;
30  
31  /**
32   * <p>
33   * A file-based reloading strategy that uses <a
34   * href="http://commons.apache.org/vfs/">Commons VFS</a> to determine when a
35   * file was changed.
36   * </p>
37   * <p>
38   * This reloading strategy is very similar to
39   * {@link FileChangedReloadingStrategy}, except for the fact that it uses VFS
40   * and thus can deal with a variety of different configuration sources.
41   * </p>
42   * <p>
43   * This strategy only works with FileConfiguration instances.
44   * </p>
45   *
46   * @author <a
47   *         href="http://commons.apache.org/configuration/team-list.html">Commons
48   *         Configuration team</a>
49   * @version $Id: VFSFileChangedReloadingStrategy.java 1162383 2011-08-27 15:57:11Z oheger $
50   * @since 1.7
51   */
52  public class VFSFileChangedReloadingStrategy implements ReloadingStrategy
53  {
54      /** Constant for the default refresh delay.*/
55      private static final int DEFAULT_REFRESH_DELAY = 5000;
56  
57      /** Stores a reference to the configuration to be monitored.*/
58      protected FileConfiguration configuration;
59  
60      /** The last time the configuration file was modified. */
61      protected long lastModified;
62  
63      /** The last time the file was checked for changes. */
64      protected long lastChecked;
65  
66      /** The minimum delay in milliseconds between checks. */
67      protected long refreshDelay = DEFAULT_REFRESH_DELAY;
68  
69      /** A flag whether a reload is required.*/
70      private boolean reloading;
71  
72      /** Stores the logger.*/
73      private Log log = LogFactory.getLog(getClass());
74  
75      public void setConfiguration(FileConfiguration configuration)
76      {
77          this.configuration = configuration;
78      }
79  
80      public void init()
81      {
82          if (configuration.getURL() == null && configuration.getFileName() == null)
83          {
84              return;
85          }
86          if (this.configuration == null)
87          {
88              throw new IllegalStateException("No configuration has been set for this strategy");
89          }
90          updateLastModified();
91      }
92  
93      public boolean reloadingRequired()
94      {
95          if (!reloading)
96          {
97              long now = System.currentTimeMillis();
98  
99              if (now > lastChecked + refreshDelay)
100             {
101                 lastChecked = now;
102                 if (hasChanged())
103                 {
104                     reloading = true;
105                 }
106             }
107         }
108 
109         return reloading;
110     }
111 
112     public void reloadingPerformed()
113     {
114         updateLastModified();
115     }
116 
117     /**
118      * Return the minimal time in milliseconds between two reloadings.
119      *
120      * @return the refresh delay (in milliseconds)
121      */
122     public long getRefreshDelay()
123     {
124         return refreshDelay;
125     }
126 
127     /**
128      * Set the minimal time between two reloadings.
129      *
130      * @param refreshDelay refresh delay in milliseconds
131      */
132     public void setRefreshDelay(long refreshDelay)
133     {
134         this.refreshDelay = refreshDelay;
135     }
136 
137     /**
138      * Update the last modified time.
139      */
140     protected void updateLastModified()
141     {
142         FileObject file = getFile();
143         if (file != null)
144         {
145             try
146             {
147                 lastModified = file.getContent().getLastModifiedTime();
148             }
149             catch (FileSystemException fse)
150             {
151                 log.error("Unable to get last modified time for" + file.getName().getURI());
152             }
153         }
154         reloading = false;
155     }
156 
157     /**
158      * Check if the configuration has changed since the last time it was loaded.
159      *
160      * @return a flag whether the configuration has changed
161      */
162     protected boolean hasChanged()
163     {
164         FileObject file = getFile();
165         try
166         {
167             if (file == null || !file.exists())
168             {
169                 return false;
170             }
171 
172             return file.getContent().getLastModifiedTime() > lastModified;
173         }
174         catch (FileSystemException ex)
175         {
176             log.error("Unable to get last modified time for" + file.getName().getURI());
177             return false;
178         }
179     }
180 
181     /**
182      * Returns the file that is monitored by this strategy. Note that the return
183      * value can be <b>null </b> under some circumstances.
184      *
185      * @return the monitored file
186      */
187     protected FileObject getFile()
188     {
189         try
190         {
191             FileSystemManager fsManager = VFS.getManager();
192             FileSystem fs = ((FileSystemBased) configuration).getFileSystem();
193             String uri = fs.getPath(null, configuration.getURL(), configuration.getBasePath(),
194                 configuration.getFileName());
195             if (uri == null)
196             {
197                 throw new ConfigurationRuntimeException("Unable to determine file to monitor");
198             }
199             return fsManager.resolveFile(uri);
200         }
201         catch (FileSystemException fse)
202         {
203             String msg = "Unable to monitor " + configuration.getURL().toString();
204             log.error(msg);
205             throw new ConfigurationRuntimeException(msg, fse);
206         }
207     }
208 }