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 package org.apache.logging.log4j.core.config; 018 019 import java.io.File; 020 import java.util.List; 021 022 /** 023 * Configuration monitor that periodically checks the timestamp of the configuration file and calls the 024 * ConfigurationListeners when an update occurs. 025 */ 026 public class FileConfigurationMonitor implements ConfigurationMonitor { 027 028 private static final int MASK = 0x0f; 029 030 private static final int MIN_INTERVAL = 5; 031 032 private static final int MILLIS_PER_SECOND = 1000; 033 034 private final File file; 035 036 private long lastModified; 037 038 private final List<ConfigurationListener> listeners; 039 040 private final int interval; 041 042 private long nextCheck; 043 044 private volatile int counter = 0; 045 046 private final Reconfigurable reconfigurable; 047 048 /** 049 * Constructor. 050 * @param reconfigurable The Configuration that can be reconfigured. 051 * @param file The File to monitor. 052 * @param listeners The List of ConfigurationListeners to notify upon a change. 053 * @param interval The monitor interval in seconds. The minimum interval is 5 seconds. 054 */ 055 public FileConfigurationMonitor(final Reconfigurable reconfigurable, final File file, 056 final List<ConfigurationListener> listeners, 057 final int interval) { 058 this.reconfigurable = reconfigurable; 059 this.file = file; 060 this.lastModified = file.lastModified(); 061 this.listeners = listeners; 062 this.interval = (interval < MIN_INTERVAL ? MIN_INTERVAL : interval) * MILLIS_PER_SECOND; 063 this.nextCheck = System.currentTimeMillis() + interval; 064 } 065 066 /** 067 * Called to determine if the configuration has changed. 068 */ 069 @Override 070 public void checkConfiguration() { 071 if ((++counter & MASK) == 0) { 072 synchronized (this) { 073 final long current = System.currentTimeMillis(); 074 if (current >= nextCheck) { 075 nextCheck = current + interval; 076 if (file.lastModified() > lastModified) { 077 lastModified = file.lastModified(); 078 for (final ConfigurationListener listener : listeners) { 079 listener.onChange(reconfigurable); 080 } 081 } 082 } 083 } 084 } 085 } 086 }