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.configuration2.reloading;
19  
20  import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
21  import org.apache.commons.configuration2.io.FileHandler;
22  import org.apache.commons.configuration2.io.FileSystem;
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.commons.vfs2.FileObject;
26  import org.apache.commons.vfs2.FileSystemException;
27  import org.apache.commons.vfs2.FileSystemManager;
28  import org.apache.commons.vfs2.VFS;
29  
30  /**
31   * <p>
32   * A file-based reloading strategy that uses <a href="https://commons.apache.org/vfs/">Commons VFS</a> to determine when
33   * a file was changed.
34   * </p>
35   * <p>
36   * This reloading strategy is very similar to {@link FileHandlerReloadingDetector}, except for the fact that it uses VFS
37   * and thus can deal with a variety of different configuration sources.
38   * </p>
39   * <p>
40   * This strategy only works with FileConfiguration instances.
41   * </p>
42   *
43   * @since 1.7
44   */
45  public class VFSFileHandlerReloadingDetector extends FileHandlerReloadingDetector {
46      /** Stores the logger. */
47      private final Log log = LogFactory.getLog(getClass());
48  
49      /**
50       * Creates a new instance of {@code VFSFileHandlerReloadingDetector} and initializes it with an empty
51       * {@code FileHandler} object.
52       */
53      public VFSFileHandlerReloadingDetector() {
54      }
55  
56      /**
57       * Creates a new instance of {@code VFSFileHandlerReloadingDetector} and initializes it with the given
58       * {@code FileHandler} object and the given refresh delay.
59       *
60       * @param handler the {@code FileHandler}
61       * @param refreshDelay the refresh delay
62       */
63      public VFSFileHandlerReloadingDetector(final FileHandler handler, final long refreshDelay) {
64          super(handler, refreshDelay);
65      }
66  
67      /**
68       * Creates a new instance of {@code VFSFileHandlerReloadingDetector} and initializes it with the given
69       * {@code FileHandler} object.
70       *
71       * @param handler the {@code FileHandler}
72       */
73      public VFSFileHandlerReloadingDetector(final FileHandler handler) {
74          super(handler);
75      }
76  
77      /**
78       * {@inheritDoc} This implementation uses Commons VFS to obtain a {@code FileObject} and read the date of the last
79       * modification.
80       */
81      @Override
82      protected long getLastModificationDate() {
83          final FileObject file = getFileObject();
84          try {
85              if (file == null || !file.exists()) {
86                  return 0;
87              }
88  
89              return file.getContent().getLastModifiedTime();
90          } catch (final FileSystemException ex) {
91              log.error("Unable to get last modified time for" + file.getName().getURI(), ex);
92              return 0;
93          }
94      }
95  
96      /**
97       * Gets the file that is monitored by this strategy. Note that the return value can be <b>null </b> under some
98       * circumstances.
99       *
100      * @return the monitored file
101      */
102     protected FileObject getFileObject() {
103         if (!getFileHandler().isLocationDefined()) {
104             return null;
105         }
106 
107         try {
108             final FileSystemManager fsManager = VFS.getManager();
109             final String uri = resolveFileURI();
110             if (uri == null) {
111                 throw new ConfigurationRuntimeException("Unable to determine file to monitor");
112             }
113             return fsManager.resolveFile(uri);
114         } catch (final FileSystemException fse) {
115             final String msg = "Unable to monitor " + getFileHandler().getURL().toString();
116             log.error(msg);
117             throw new ConfigurationRuntimeException(msg, fse);
118         }
119     }
120 
121     /**
122      * Resolves the URI of the monitored file.
123      *
124      * @return the URI of the monitored file or <b>null</b> if it cannot be resolved
125      */
126     protected String resolveFileURI() {
127         final FileSystem fs = getFileHandler().getFileSystem();
128         return fs.getPath(null, getFileHandler().getURL(), getFileHandler().getBasePath(), getFileHandler().getFileName());
129     }
130 }