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
; // If NoWildcards, contains the full path to the file.
41 public bool IncludeSubdirs
;
43 public bool NoWildcards
;
44 public DateTime DisabledTime
;
45 public Hashtable Files
;
49 public string Directory
;
50 public FileAttributes Attributes
;
51 public bool NotExists
;
52 public DateTime CreationTime
;
53 public DateTime LastWriteTime
;
56 class DefaultWatcher
: IFileWatcher
58 static DefaultWatcher instance
;
60 static Hashtable watches
;
62 private DefaultWatcher ()
66 public static bool GetInstance (out IFileWatcher watcher
)
68 lock (typeof (DefaultWatcher
)) {
69 if (instance
!= null) {
74 instance
= new DefaultWatcher ();
80 public void StartDispatching (FileSystemWatcher fsw
)
82 DefaultWatcherData data
;
85 watches
= new Hashtable ();
88 thread
= new Thread (new ThreadStart (Monitor
));
89 thread
.IsBackground
= true;
95 data
= (DefaultWatcherData
) watches
[fsw
];
97 data
= new DefaultWatcherData ();
98 data
.Files
= new Hashtable ();
103 data
.Directory
= fsw
.FullPath
;
104 data
.NoWildcards
= !fsw
.Pattern
.HasWildcard
;
105 if (data
.NoWildcards
)
106 data
.FileMask
= Path
.Combine (data
.Directory
, fsw
.MangledFilter
);
108 data
.FileMask
= fsw
.MangledFilter
;
110 data
.IncludeSubdirs
= fsw
.IncludeSubdirectories
;
112 data
.DisabledTime
= DateTime
.MaxValue
;
113 UpdateDataAndDispatch (data
, false);
117 public void StopDispatching (FileSystemWatcher fsw
)
119 DefaultWatcherData data
;
121 data
= (DefaultWatcherData
) watches
[fsw
];
123 data
.Enabled
= false;
124 data
.DisabledTime
= DateTime
.Now
;
136 if (watches
.Count
> 0) {
138 ArrayList removed
= null;
139 foreach (DefaultWatcherData data
in watches
.Values
) {
140 bool remove = UpdateDataAndDispatch (data
, true);
143 removed
= new ArrayList ();
149 if (removed
!= null) {
150 foreach (DefaultWatcherData data
in removed
)
151 watches
.Remove (data
.FSW
);
170 bool UpdateDataAndDispatch (DefaultWatcherData data
, bool dispatch
)
173 return (data
.DisabledTime
!= DateTime
.MaxValue
&&
174 (DateTime
.Now
- data
.DisabledTime
).TotalSeconds
> 5);
177 DoFiles (data
, data
.Directory
, dispatch
);
181 static void DispatchEvents (FileSystemWatcher fsw
, FileAction action
, string filename
)
183 RenamedEventArgs renamed
= null;
186 fsw
.DispatchEvents (action
, filename
, ref renamed
);
189 System
.Threading
.Monitor
.PulseAll (fsw
);
194 static string [] NoStringsArray
= new string [0];
195 void DoFiles (DefaultWatcherData data
, string directory
, bool dispatch
)
197 bool direxists
= Directory
.Exists (directory
);
198 if (direxists
&& data
.IncludeSubdirs
) {
199 foreach (string d
in Directory
.GetDirectories (directory
))
200 DoFiles (data
, d
, dispatch
);
203 string [] files
= null;
205 files
= NoStringsArray
;
206 } else if (!data
.NoWildcards
) {
207 files
= Directory
.GetFileSystemEntries (directory
, data
.FileMask
);
209 // The pattern does not have wildcards
210 if (File
.Exists (data
.FileMask
))
211 files
= new string [] { data.FileMask }
;
213 files
= NoStringsArray
;
216 /* Set all as untested */
217 foreach (string filename
in data
.Files
.Keys
) {
218 FileData fd
= (FileData
) data
.Files
[filename
];
219 if (fd
.Directory
== directory
)
224 foreach (string filename
in files
) {
225 FileData fd
= (FileData
) data
.Files
[filename
];
228 data
.Files
.Add (filename
, CreateFileData (directory
, filename
));
230 // The file might have been removed in the meanwhile
231 data
.Files
.Remove (filename
);
236 DispatchEvents (data
.FSW
, FileAction
.Added
, filename
);
237 } else if (fd
.Directory
== directory
) {
238 fd
.NotExists
= false;
242 if (!dispatch
) // We only initialize the file list
246 ArrayList removed
= null;
247 foreach (string filename
in data
.Files
.Keys
) {
248 FileData fd
= (FileData
) data
.Files
[filename
];
251 removed
= new ArrayList ();
253 removed
.Add (filename
);
254 DispatchEvents (data
.FSW
, FileAction
.Removed
, filename
);
258 if (removed
!= null) {
259 foreach (string filename
in removed
)
260 data
.Files
.Remove (filename
);
266 foreach (string filename
in data
.Files
.Keys
) {
267 FileData fd
= (FileData
) data
.Files
[filename
];
268 DateTime creation
, write
;
270 creation
= File
.GetCreationTime (filename
);
271 write
= File
.GetLastWriteTime (filename
);
275 removed
= new ArrayList ();
277 removed
.Add (filename
);
278 DispatchEvents (data
.FSW
, FileAction
.Removed
, filename
);
282 if (creation
!= fd
.CreationTime
|| write
!= fd
.LastWriteTime
) {
283 fd
.CreationTime
= creation
;
284 fd
.LastWriteTime
= write
;
285 DispatchEvents (data
.FSW
, FileAction
.Modified
, filename
);
289 if (removed
!= null) {
290 foreach (string filename
in removed
)
291 data
.Files
.Remove (filename
);
296 static FileData
CreateFileData (string directory
, string filename
)
298 FileData fd
= new FileData ();
299 string fullpath
= Path
.Combine (directory
, filename
);
300 fd
.Directory
= directory
;
301 fd
.Attributes
= File
.GetAttributes (fullpath
);
302 fd
.CreationTime
= File
.GetCreationTime (fullpath
);
303 fd
.LastWriteTime
= File
.GetLastWriteTime (fullpath
);