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 */ 017package org.apache.logging.log4j.core.util; 018 019import org.apache.logging.log4j.Logger; 020import org.apache.logging.log4j.core.AbstractLifeCycle; 021import org.apache.logging.log4j.core.config.Configuration; 022import org.apache.logging.log4j.core.config.ConfigurationScheduler; 023import org.apache.logging.log4j.status.StatusLogger; 024 025import java.io.File; 026import java.util.Map; 027import java.util.concurrent.ConcurrentHashMap; 028import java.util.concurrent.ConcurrentMap; 029import java.util.concurrent.ScheduledExecutorService; 030import java.util.concurrent.ScheduledFuture; 031import java.util.concurrent.TimeUnit; 032 033/** 034 * Manages FileWatchers. 035 */ 036public class WatchManager extends AbstractLifeCycle { 037 038 private static final long serialVersionUID = 8998356999926962686L; 039 private static Logger logger = StatusLogger.getLogger(); 040 private final ConcurrentMap<File, FileMonitor> watchers = new ConcurrentHashMap<>(); 041 private int intervalSeconds = 0; 042 private ScheduledFuture<?> future; 043 private ConfigurationScheduler scheduler; 044 045 public WatchManager(ConfigurationScheduler scheduler) { 046 this.scheduler = scheduler; 047 } 048 049 public void setIntervalSeconds(int intervalSeconds) { 050 if (!isStarted()) { 051 if (this.intervalSeconds > 0 && intervalSeconds == 0) { 052 scheduler.decrementScheduledItems(); 053 } else if (this.intervalSeconds == 0 && intervalSeconds > 0) { 054 scheduler.incrementScheduledItems(); 055 } 056 this.intervalSeconds = intervalSeconds; 057 } 058 } 059 060 public int getIntervalSeconds() { 061 return this.intervalSeconds; 062 } 063 064 @Override 065 public void start() { 066 super.start(); 067 if (intervalSeconds > 0) { 068 future = scheduler.scheduleWithFixedDelay(new WatchWorker(), intervalSeconds, intervalSeconds, 069 TimeUnit.SECONDS); 070 } 071 } 072 073 @Override 074 public void stop() { 075 future.cancel(true); 076 super.stop(); 077 } 078 079 public void watchFile(File file, FileWatcher watcher) { 080 watchers.put(file, new FileMonitor(file.lastModified(), watcher)); 081 082 } 083 084 private class WatchWorker implements Runnable { 085 086 @Override 087 public void run() { 088 for (Map.Entry<File, FileMonitor> entry : watchers.entrySet()) { 089 File file = entry.getKey(); 090 FileMonitor fileMonitor = entry.getValue(); 091 long lastModfied = file.lastModified(); 092 if (lastModfied > fileMonitor.lastModified) { 093 logger.info("File {} was modified", file.toString()); 094 fileMonitor.lastModified = lastModfied; 095 fileMonitor.fileWatcher.fileModified(file); 096 } 097 } 098 } 099 } 100 101 private class FileMonitor { 102 private final FileWatcher fileWatcher; 103 private long lastModified; 104 105 public FileMonitor(long lastModified, FileWatcher fileWatcher) { 106 this.fileWatcher = fileWatcher; 107 this.lastModified = lastModified; 108 } 109 } 110}