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