    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *     http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 * Unless required by applicable law or agreed to in writing, software
    012 * distributed under the License is distributed on an "AS IS" BASIS,
    013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 * See the License for the specific language governing permissions and
    015 * limitations under the License.
    016 */
    017
    018package org.apache.commons.configuration2.reloading;
    019
    020import org.apache.commons.configuration2.ex.ConfigurationRuntimeException;
    021import org.apache.commons.configuration2.io.FileHandler;
    022import org.apache.commons.configuration2.io.FileSystem;
    023import org.apache.commons.logging.Log;
    024import org.apache.commons.logging.LogFactory;
    025import org.apache.commons.vfs2.FileObject;
    026import org.apache.commons.vfs2.FileSystemException;
    027import org.apache.commons.vfs2.FileSystemManager;
    028import org.apache.commons.vfs2.VFS;
    029
    030/**
    031 * <p>
    032 * A file-based reloading strategy that uses <a
    033 * href="http://commons.apache.org/vfs/">Commons VFS</a> to determine when a
    034 * file was changed.
    035 * </p>
    036 * <p>
    037 * This reloading strategy is very similar to
    038 * {@link FileHandlerReloadingDetector}, except for the fact that it uses VFS
    039 * and thus can deal with a variety of different configuration sources.
    040 * </p>
    041 * <p>
    042 * This strategy only works with FileConfiguration instances.
    043 * </p>
    044 *
    045 * @author <a
    046 *         href="http://commons.apache.org/configuration/team-list.html">Commons
    047 *         Configuration team</a>
    048 * @version $Id: VFSFileHandlerReloadingDetector.java 1842194 2018-09-27 22:24:23Z ggregory $
    049 * @since 1.7
    050 */
    051public class VFSFileHandlerReloadingDetector extends FileHandlerReloadingDetector
    052{
    053    /** Stores the logger.*/
    054    private final Log log = LogFactory.getLog(getClass());
    055
    056    /**
    057     * Creates a new instance of {@code VFSFileHandlerReloadingDetector} and
    058     * initializes it with an empty {@code FileHandler} object.
    059     */
    060    public VFSFileHandlerReloadingDetector()
    061    {
    062        super();
    063    }
    064
    065    /**
    066     * Creates a new instance of {@code VFSFileHandlerReloadingDetector} and
    067     * initializes it with the given {@code FileHandler} object and the given
    068     * refresh delay.
    069     *
    070     * @param handler the {@code FileHandler}
    071     * @param refreshDelay the refresh delay
    072     */
    073    public VFSFileHandlerReloadingDetector(final FileHandler handler,
    074            final long refreshDelay)
    075    {
    076        super(handler, refreshDelay);
    077    }
    078
    079    /**
    080     * Creates a new instance of {@code VFSFileHandlerReloadingDetector} and
    081     * initializes it with the given {@code FileHandler} object.
    082     *
    083     * @param handler the {@code FileHandler}
    084     */
    085    public VFSFileHandlerReloadingDetector(final FileHandler handler)
    086    {
    087        super(handler);
    088    }
    089
    090    /**
    091     * {@inheritDoc} This implementation uses Commons VFS to obtain a
    092     * {@code FileObject} and read the date of the last modification.
    093     */
    094    @Override
    095    protected long getLastModificationDate()
    096    {
    097        final FileObject file = getFileObject();
    098        try
    099        {
    100            if (file == null || !file.exists())
    101            {
    102                return 0;
    103            }
    104
    105            return file.getContent().getLastModifiedTime();
    106        }
    107        catch (final FileSystemException ex)
    108        {
    109            log.error("Unable to get last modified time for"
    110                    + file.getName().getURI(), ex);
    111            return 0;
    112        }
    113    }
    114
    115    /**
    116     * Returns the file that is monitored by this strategy. Note that the return
    117     * value can be <b>null </b> under some circumstances.
    118     *
    119     * @return the monitored file
    120     */
    121    protected FileObject getFileObject()
    122    {
    123        if (!getFileHandler().isLocationDefined())
    124        {
    125            return null;
    126        }
    127
    128        try
    129        {
    130            final FileSystemManager fsManager = VFS.getManager();
    131            final String uri = resolveFileURI();
    132            if (uri == null)
    133            {
    134                throw new ConfigurationRuntimeException("Unable to determine file to monitor");
    135            }
    136            return fsManager.resolveFile(uri);
    137        }
    138        catch (final FileSystemException fse)
    139        {
    140            final String msg = "Unable to monitor " + getFileHandler().getURL().toString();
    141            log.error(msg);
    142            throw new ConfigurationRuntimeException(msg, fse);
    143        }
    144    }
    145
    146    /**
    147     * Resolves the URI of the monitored file.
    148     *
    149     * @return the URI of the monitored file or <b>null</b> if it cannot be
    150     *         resolved
    151     */
    152    protected String resolveFileURI()
    153    {
    154        final FileSystem fs = getFileHandler().getFileSystem();
    155        final String uri =
    156                fs.getPath(null, getFileHandler().getURL(), getFileHandler()
    157                        .getBasePath(), getFileHandler().getFileName());
    158        return uri;
    159    }
    160}