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 * https://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.
59 *
60 * @param handler the {@code FileHandler}
61 */
62 public VFSFileHandlerReloadingDetector(final FileHandler handler) {
63 super(handler);
64 }
65
66 /**
67 * Creates a new instance of {@code VFSFileHandlerReloadingDetector} and initializes it with the given
68 * {@code FileHandler} object and the given refresh delay.
69 *
70 * @param handler the {@code FileHandler}
71 * @param refreshDelay the refresh delay
72 */
73 public VFSFileHandlerReloadingDetector(final FileHandler handler, final long refreshDelay) {
74 super(handler, refreshDelay);
75 }
76
77 /**
78 * Gets the file that is monitored by this strategy. Note that the return value can be <strong>null </strong> under some
79 * circumstances.
80 *
81 * @return the monitored file
82 */
83 protected FileObject getFileObject() {
84 if (!getFileHandler().isLocationDefined()) {
85 return null;
86 }
87
88 try {
89 final FileSystemManager fsManager = VFS.getManager();
90 final String uri = resolveFileURI();
91 if (uri == null) {
92 throw new ConfigurationRuntimeException("Unable to determine file to monitor");
93 }
94 return fsManager.resolveFile(uri);
95 } catch (final FileSystemException fse) {
96 final String msg = "Unable to monitor " + getFileHandler().getURL().toString();
97 log.error(msg);
98 throw new ConfigurationRuntimeException(msg, fse);
99 }
100 }
101
102 /**
103 * {@inheritDoc} This implementation uses Commons VFS to obtain a {@code FileObject} and read the date of the last
104 * modification.
105 */
106 @Override
107 protected long getLastModificationDate() {
108 final FileObject file = getFileObject();
109 try {
110 if (file == null || !file.exists()) {
111 return 0;
112 }
113
114 return file.getContent().getLastModifiedTime();
115 } catch (final FileSystemException ex) {
116 log.error("Unable to get last modified time for" + file.getName().getURI(), ex);
117 return 0;
118 }
119 }
120
121 /**
122 * Resolves the URI of the monitored file.
123 *
124 * @return the URI of the monitored file or <strong>null</strong> 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 }