2 // System.IO.DefaultWatcher.cs: default IFileWatcher
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (c) 2004 Novell, Inc. (http://www.novell.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System.Collections;
34 using System.Threading;
37 class DefaultWatcherData {
38 public FileSystemWatcher FSW;
39 public string Directory;
40 public string FileMask;
41 public bool IncludeSubdirs;
43 public DateTime DisabledTime;
44 public Hashtable Files;
48 public string Directory;
49 public FileAttributes Attributes;
50 public bool NotExists;
51 public DateTime CreationTime;
52 public DateTime LastWriteTime;
55 class DefaultWatcher : IFileWatcher
57 static DefaultWatcher instance;
59 static Hashtable watches;
61 private DefaultWatcher ()
65 public static bool GetInstance (out IFileWatcher watcher)
67 lock (typeof (DefaultWatcher)) {
68 if (instance != null) {
73 instance = new DefaultWatcher ();
79 public void StartDispatching (FileSystemWatcher fsw)
81 DefaultWatcherData data;
84 watches = new Hashtable ();
87 thread = new Thread (new ThreadStart (Monitor));
88 thread.IsBackground = true;
94 data = (DefaultWatcherData) watches [fsw];
96 data = new DefaultWatcherData ();
97 data.Files = new Hashtable ();
102 data.Directory = fsw.FullPath;
103 data.FileMask = fsw.MangledFilter;
104 data.IncludeSubdirs = fsw.IncludeSubdirectories;
106 data.DisabledTime = DateTime.MaxValue;
107 UpdateDataAndDispatch (data, false);
111 public void StopDispatching (FileSystemWatcher fsw)
113 DefaultWatcherData data;
115 data = (DefaultWatcherData) watches [fsw];
117 data.Enabled = false;
118 data.DisabledTime = DateTime.Now;
130 if (watches.Count > 0) {
132 ArrayList removed = null;
133 foreach (DefaultWatcherData data in watches.Values) {
134 bool remove = UpdateDataAndDispatch (data, true);
137 removed = new ArrayList ();
143 if (removed != null) {
144 foreach (DefaultWatcherData data in removed)
145 watches.Remove (data.FSW);
164 bool UpdateDataAndDispatch (DefaultWatcherData data, bool dispatch)
167 return (data.DisabledTime != DateTime.MaxValue &&
168 (DateTime.Now - data.DisabledTime).TotalSeconds > 5);
171 DoFiles (data, data.Directory, dispatch);
175 static void DispatchEvents (FileSystemWatcher fsw, FileAction action, string filename)
177 RenamedEventArgs renamed = null;
180 fsw.DispatchEvents (action, filename, ref renamed);
183 System.Threading.Monitor.PulseAll (fsw);
188 void DoFiles (DefaultWatcherData data, string directory, bool dispatch)
190 bool direxists = Directory.Exists (directory);
191 if (direxists && data.IncludeSubdirs) {
192 foreach (string d in Directory.GetDirectories (directory))
193 DoFiles (data, d, dispatch);
196 string [] files = null;
198 files = Directory.GetFileSystemEntries (directory, data.FileMask);
200 files = new string [0];
203 /* Set all as untested */
204 foreach (string filename in data.Files.Keys) {
205 FileData fd = (FileData) data.Files [filename];
206 if (fd.Directory == directory)
211 foreach (string filename in files) {
212 FileData fd = (FileData) data.Files [filename];
214 data.Files.Add (filename, CreateFileData (directory, filename));
216 DispatchEvents (data.FSW, FileAction.Added, filename);
217 } else if (fd.Directory == directory) {
218 fd.NotExists = false;
222 if (!dispatch) // We only initialize the file list
226 ArrayList removed = null;
227 foreach (string filename in data.Files.Keys) {
228 FileData fd = (FileData) data.Files [filename];
231 removed = new ArrayList ();
233 removed.Add (filename);
234 DispatchEvents (data.FSW, FileAction.Removed, filename);
238 if (removed != null) {
239 foreach (string filename in removed)
240 data.Files.Remove (filename);
246 foreach (string filename in data.Files.Keys) {
247 FileData fd = (FileData) data.Files [filename];
248 DateTime creation, write;
250 creation = File.GetCreationTime (filename);
251 write = File.GetLastWriteTime (filename);
255 removed = new ArrayList ();
257 removed.Add (filename);
258 DispatchEvents (data.FSW, FileAction.Removed, filename);
262 if (creation != fd.CreationTime || write != fd.LastWriteTime) {
263 fd.CreationTime = creation;
264 fd.LastWriteTime = write;
265 DispatchEvents (data.FSW, FileAction.Modified, filename);
269 if (removed != null) {
270 foreach (string filename in removed)
271 data.Files.Remove (filename);
276 static FileData CreateFileData (string directory, string filename)
278 FileData fd = new FileData ();
279 string fullpath = Path.Combine (directory, filename);
280 fd.Directory = directory;
281 fd.Attributes = File.GetAttributes (fullpath);
282 fd.CreationTime = File.GetCreationTime (fullpath);
283 fd.LastWriteTime = File.GetLastWriteTime (fullpath);