#region Apache Notice
/*****************************************************************************
* $Header: $
* $Revision: $
* $Date: $
*
* iBATIS.NET Data Mapper
* Copyright (C) 2004 - Gilles Bayon
*
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
********************************************************************************/
#endregion
using System;
using System.Collections;
using System.IO;
using System.Threading;
using IBatisNet.Common.Logging;
namespace IBatisNet.Common.Utilities
{
///
/// Represents the method that handles calls from Configure.
///
///
/// obj is a null object in a DaoManager context.
/// obj is the reconfigured sqlMap in a SqlMap context.
///
public delegate void ConfigureHandler(object obj);
///
///
///
public struct StateConfig
{
///
/// Master Config File name.
///
public string FileName;
///
/// Delegate called when a file is changed, use it to rebuild.
///
public ConfigureHandler ConfigureHandler;
}
///
/// Class used to watch config files.
///
///
/// Uses the to monitor
/// changes to a specified file. Because multiple change notifications
/// may be raised when the file is modified, a timer is used to
/// compress the notifications into a single event. The timer
/// waits for time before delivering
/// the event notification. If any further
/// change notifications arrive while the timer is waiting it
/// is reset and waits again for to
/// elaps.
///
public sealed class ConfigWatcherHandler
{
#region Fields
private static readonly ILog _logger = LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType );
///
/// The timer used to compress the notification events.
///
private Timer _timer = null;
///
/// A list of configuration files to watch.
///
private static ArrayList _filesToWatch = new ArrayList();
///
/// The list of FileSystemWatcher.
///
private static ArrayList _filesWatcher = new ArrayList();
///
/// The default amount of time to wait after receiving notification
/// before reloading the config file.
///
private const int TimoutMillis = 500;
#endregion
#region Constructor (s) / Destructor
///
///-
///
///
/// Represent the call context of the SqlMap or DaoManager ConfigureAndWatch method call.
///
///
public ConfigWatcherHandler(TimerCallback onWhatchedFileChange, StateConfig state)
{
for(int index = 0; index < _filesToWatch.Count; index++)
{
FileInfo configFile = (FileInfo)_filesToWatch[index];
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = configFile.DirectoryName;
watcher.Filter = configFile.Name;
// Set the notification filters
watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.FileName;
// Add event handlers. OnChanged will do for all event handlers that fire a FileSystemEventArgs
watcher.Changed += new FileSystemEventHandler(ConfigWatcherHandler_OnChanged);
watcher.Created += new FileSystemEventHandler(ConfigWatcherHandler_OnChanged);
watcher.Deleted += new FileSystemEventHandler(ConfigWatcherHandler_OnChanged);
watcher.Renamed += new RenamedEventHandler(ConfigWatcherHandler_OnRenamed);
// Begin watching.
watcher.EnableRaisingEvents = true;
_filesWatcher.Add( watcher );
// Create the timer that will be used to deliver events. Set as disabled
_timer = new Timer(onWhatchedFileChange, state, Timeout.Infinite, Timeout.Infinite);
}
}
#endregion
#region Methods
///
/// Add a file to be monitored.
///
///
public static void AddFileToWatch(FileInfo configFile)
{
_filesToWatch.Add( configFile );
}
///
/// Reset the list of files being monitored.
///
public static void ClearFilesMonitored()
{
_filesToWatch.Clear();
// Kill all FileSystemWatcher
for(int index = 0; index < _filesWatcher.Count; index++)
{
FileSystemWatcher fileWatcher = (FileSystemWatcher)_filesWatcher[index];
fileWatcher.EnableRaisingEvents = false;
fileWatcher.Dispose();
}
}
///
/// Event handler used by .
///
/// The firing the event.
/// The argument indicates the file that caused the event to be fired.
///
/// This handler reloads the configuration from the file when the event is fired.
///
private void ConfigWatcherHandler_OnChanged(object source, FileSystemEventArgs e)
{
if (_logger.IsDebugEnabled)
{
_logger.Debug("ConfigWatcherHandler : "+e.ChangeType+" [" + e.Name + "]");
}
// Deliver the event in TimoutMillis time
// timer will fire only once
_timer.Change(TimoutMillis, Timeout.Infinite);
}
///
/// Event handler used by .
///
/// The firing the event.
/// The argument indicates the file that caused the event to be fired.
///
/// This handler reloads the configuration from the file when the event is fired.
///
private void ConfigWatcherHandler_OnRenamed(object source, RenamedEventArgs e)
{
if (_logger.IsDebugEnabled)
{
_logger.Debug("ConfigWatcherHandler : " + e.ChangeType + " [" + e.OldName + "/" +e.Name +"]");
}
// Deliver the event in TimoutMillis time
// timer will fire only once
_timer.Change(TimoutMillis, Timeout.Infinite);
}
#endregion
}
}