| |||||||||||||||||
Source File | Conditionals | Statements | Methods | TOTAL | |||||||||||||
Utilities\ConfigWatcherHandler.cs | 50.0 % | 76.0 % | 60.0 % | 68.4 % |
|
1 | ||
2 | #region Apache Notice | |
3 | /***************************************************************************** | |
4 | * $Header: $ | |
5 | * $Revision: $ | |
6 | * $Date: $ | |
7 | * | |
8 | * iBATIS.NET Data Mapper | |
9 | * Copyright (C) 2004 - Gilles Bayon | |
10 | * | |
11 | * | |
12 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
13 | * you may not use this file except in compliance with the License. | |
14 | * You may obtain a copy of the License at | |
15 | * | |
16 | * http://www.apache.org/licenses/LICENSE-2.0 | |
17 | * | |
18 | * Unless required by applicable law or agreed to in writing, software | |
19 | * distributed under the License is distributed on an "AS IS" BASIS, | |
20 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
21 | * See the License for the specific language governing permissions and | |
22 | * limitations under the License. | |
23 | * | |
24 | ********************************************************************************/ | |
25 | #endregion | |
26 | ||
27 | using System; | |
28 | using System.Collections; | |
29 | using System.IO; | |
30 | using System.Threading; | |
31 | ||
32 | using log4net; | |
33 | ||
34 | namespace IBatisNet.Common.Utilities | |
35 | { | |
36 | ||
37 | /// <summary> | |
38 | /// Represents the method that handles calls from Configure. | |
39 | /// </summary> | |
40 | /// <remarks> | |
41 | /// obj is a null object in a DaoManager context. | |
42 | /// obj is the reconfigured sqlMap in a SqlMap context. | |
43 | /// </remarks> | |
44 | public delegate void ConfigureHandler(object obj); | |
45 | ||
46 | /// <summary> | |
47 | /// | |
48 | /// </summary> | |
49 | public struct StateConfig | |
50 | { | |
51 | /// <summary> | |
52 | /// Master Config File name. | |
53 | /// </summary> | |
54 | public string fileName; | |
55 | /// <summary> | |
56 | /// Delegate called when a file is changed, use it to rebuild. | |
57 | /// </summary> | |
58 | public ConfigureHandler configureHandler; | |
59 | } | |
60 | ||
61 | /// <summary> | |
62 | /// Class used to watch config files. | |
63 | /// </summary> | |
64 | /// <remarks> | |
65 | /// Uses the <see cref="FileSystemWatcher"/> to monitor | |
66 | /// changes to a specified file. Because multiple change notifications | |
67 | /// may be raised when the file is modified, a timer is used to | |
68 | /// compress the notifications into a single event. The timer | |
69 | /// waits for <see cref="TimoutMillis"/> time before delivering | |
70 | /// the event notification. If any further <see cref="FileSystemWatcher"/> | |
71 | /// change notifications arrive while the timer is waiting it | |
72 | /// is reset and waits again for <see cref="TimoutMillis"/> to | |
73 | /// elaps. | |
74 | /// </remarks> | |
75 | public sealed class ConfigWatcherHandler | |
76 | { | |
77 | #region Fields | |
78 | private static readonly ILog _logger = LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType ); | |
79 | ||
80 | /// <summary> | |
81 | /// The timer used to compress the notification events. | |
82 | /// </summary> | |
83 | private Timer _timer = null; | |
84 | ||
85 | /// <summary> | |
86 | /// A list of configuration files to watch. | |
87 | /// </summary> | |
88 | private static ArrayList _filesToWatch = new ArrayList(); | |
89 | ||
90 | /// <summary> | |
91 | /// The list of FileSystemWatcher. | |
92 | /// </summary> | |
93 | private static ArrayList _filesWatcher = new ArrayList(); | |
94 | ||
95 | /// <summary> | |
96 | /// The default amount of time to wait after receiving notification | |
97 | /// before reloading the config file. | |
98 | /// </summary> | |
99 | private const int TimoutMillis = 500; | |
100 | #endregion | |
101 | ||
102 | #region Constructor (s) / Destructor | |
103 | /// <summary> | |
104 | ///- | |
105 | /// </summary> | |
106 | /// <param name="state"> | |
107 | /// Represent the call context of the SqlMap or DaoManager ConfigureAndWatch method call. | |
108 | /// </param> | |
109 | /// <param name="onWhatchedFileChange"></param> | |
110 | 170 | public ConfigWatcherHandler(TimerCallback onWhatchedFileChange, StateConfig state) |
111 | { | |
112 | 340 | for(int index = 0; index < _filesToWatch.Count; index++) |
113 | { | |
114 | 170 | FileInfo configFile = (FileInfo)_filesToWatch[index]; |
115 | ||
116 | // Create a new FileSystemWatcher and set its properties. | |
117 | 170 | FileSystemWatcher watcher = new FileSystemWatcher(); |
118 | ||
119 | 170 | watcher.Path = configFile.DirectoryName; |
120 | 170 | watcher.Filter = configFile.Name; |
121 | ||
122 | // Set the notification filters | |
123 | 170 | watcher.NotifyFilter = NotifyFilters.CreationTime | NotifyFilters.LastWrite | NotifyFilters.FileName; |
124 | ||
125 | // Add event handlers. OnChanged will do for all event handlers that fire a FileSystemEventArgs | |
126 | 170 | watcher.Changed += new FileSystemEventHandler(ConfigWatcherHandler_OnChanged); |
127 | 170 | watcher.Created += new FileSystemEventHandler(ConfigWatcherHandler_OnChanged); |
128 | 170 | watcher.Deleted += new FileSystemEventHandler(ConfigWatcherHandler_OnChanged); |
129 | 170 | watcher.Renamed += new RenamedEventHandler(ConfigWatcherHandler_OnRenamed); |
130 | ||
131 | // Begin watching. | |
132 | 170 | watcher.EnableRaisingEvents = true; |
133 | ||
134 | 170 | _filesWatcher.Add( watcher ); |
135 | ||
136 | // Create the timer that will be used to deliver events. Set as disabled | |
137 | 170 | _timer = new Timer(onWhatchedFileChange, state, Timeout.Infinite, Timeout.Infinite); |
138 | } | |
139 | } | |
140 | #endregion | |
141 | ||
142 | #region Methods | |
143 | /// <summary> | |
144 | /// Add a file to be monitored. | |
145 | /// </summary> | |
146 | /// <param name="configFile"></param> | |
147 | 2040 | public static void AddFileToWatch(FileInfo configFile) |
148 | { | |
149 | 2040 | _filesToWatch.Add( configFile ); |
150 | } | |
151 | ||
152 | ||
153 | /// <summary> | |
154 | /// Reset the list of files being monitored. | |
155 | /// </summary> | |
156 | 170 | public static void ClearFilesMonitored() |
157 | { | |
158 | 170 | _filesToWatch.Clear(); |
159 | ||
160 | // Kill all FileSystemWatcher | |
161 | 14535 | for(int index = 0; index < _filesWatcher.Count; index++) |
162 | { | |
163 | 14365 | FileSystemWatcher fileWatcher = (FileSystemWatcher)_filesWatcher[index]; |
164 | ||
165 | 14365 | fileWatcher.EnableRaisingEvents = false; |
166 | 14365 | fileWatcher.Dispose(); |
167 | } | |
168 | } | |
169 | ||
170 | /// <summary> | |
171 | /// Event handler used by <see cref="ConfigWatcherHandler"/>. | |
172 | /// </summary> | |
173 | /// <param name="source">The <see cref="FileSystemWatcher"/> firing the event.</param> | |
174 | /// <param name="e">The argument indicates the file that caused the event to be fired.</param> | |
175 | /// <remarks> | |
176 | /// This handler reloads the configuration from the file when the event is fired. | |
177 | /// </remarks> | |
178 | 0 | private void ConfigWatcherHandler_OnChanged(object source, FileSystemEventArgs e) |
179 | { | |
180 | if (_logger.IsDebugEnabled) | |
181 | { | |
182 | _logger.Debug("ConfigWatcherHandler : "+e.ChangeType+" [" + e.Name + "]"); | |
183 | } | |
184 | ||
185 | // Deliver the event in TimoutMillis time | |
186 | // timer will fire only once | |
187 | _timer.Change(TimoutMillis, Timeout.Infinite); | |
188 | } | |
189 | ||
190 | /// <summary> | |
191 | /// Event handler used by <see cref="ConfigWatcherHandler"/>. | |
192 | /// </summary> | |
193 | /// <param name="source">The <see cref="FileSystemWatcher"/> firing the event.</param> | |
194 | /// <param name="e">The argument indicates the file that caused the event to be fired.</param> | |
195 | /// <remarks> | |
196 | /// This handler reloads the configuration from the file when the event is fired. | |
197 | /// </remarks> | |
198 | 0 | private void ConfigWatcherHandler_OnRenamed(object source, RenamedEventArgs e) |
199 | { | |
200 | if (_logger.IsDebugEnabled) | |
201 | { | |
202 | _logger.Debug("ConfigWatcherHandler : " + e.ChangeType + " [" + e.OldName + "/" +e.Name +"]"); | |
203 | } | |
204 | ||
205 | // Deliver the event in TimoutMillis time | |
206 | // timer will fire only once | |
207 | _timer.Change(TimoutMillis, Timeout.Infinite); | |
208 | } | |
209 | #endregion | |
210 | ||
211 | } | |
212 | } | |
213 |
|