@Override public void run() { for (Map.Entry<String, ConfigFileInfo> entry : watchedFileMap.entrySet()) { String filePath = entry.getKey(); ConfigFileInfo configFileInfo = entry.getValue(); try { File file = new File(filePath); long lastModified = file.lastModified(); Preconditions.checkArgument(lastModified > 0L); if (lastModified != configFileInfo.lastModifiedTimestampMillis) { configFileInfo.lastModifiedTimestampMillis = lastModified; ByteSource byteSource = Files.asByteSource(file); HashCode newContentHash = byteSource.hash(HASH_FUNCTION); if (!newContentHash.equals(configFileInfo.contentHash)) { configFileInfo.contentHash = newContentHash; LOG.info("File {} was modified at {}, notifying watchers.", filePath, lastModified); byte[] newContents = byteSource.read(); for (Function<byte[], Void> watchers : configFileInfo.changeWatchers) { try { watchers.apply(newContents); } catch (Exception e) { LOG.error( "Exception in watcher callback for {}, ignoring. New file contents were: {}", filePath, new String(newContents, Charsets.UTF_8), e); } } } else { LOG.info( "File {} was modified at {} but content hash is unchanged.", filePath, lastModified); } } else { LOG.debug("File {} not modified since {}", filePath, lastModified); } } catch (Exception e) { // We catch and log exceptions related to the update of any specific file, but // move on so others aren't affected. Issues can happen for example if the watcher // races with an external file replace operation; in that case, the next run should // pick up the update. // TODO: Consider adding a metric to track this so we can alert on failures. LOG.error("Config update check failed for {}", filePath, e); } } }
public static void main(String[] args) throws IOException, SAXException, ParserConfigurationException { RemoteFileChecker remoteFileChecker = new RemoteFileChecker(); ContentRemover contentRemover = new ContentRemover(); while (true) { ConfigFileInfo configFileInfo = new ConfigurationFileParser().parseConfigFile(); boolean remoteFileExists = remoteFileChecker.checkIfRemoteFileExists(configFileInfo.getRemoteUrl()); if (remoteFileExists) { contentRemover.remove(configFileInfo); try { Thread.sleep(ONE_HOUR); } catch (InterruptedException e) { } } } }