New tests.
[mono.git] / mcs / class / System.Runtime.Caching / System.Runtime.Caching / FileChangeNotificationSystemEntry.cs
1 //
2 // FileChangeNotificationSystemEntry.cs
3 //
4 // Authors:
5 //      Marek Habersack <mhabersack@novell.com>
6 //
7 // Copyright (C) 2010 Novell, Inc. (http://novell.com/)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.Runtime.Caching.Hosting;
32 using System.Text;
33
34 namespace System.Runtime.Caching
35 {
36         // This class is NOT thread-safe - the caller needs to assure access serialization when
37         // calling Add/Remove
38         sealed class FileChangeNotificationSystemEntry : IDisposable
39         {
40                 string watchedDirPath;
41                 FileChangeNotificationSystem owner;
42                 FileSystemWatcher watcher;
43                 SortedDictionary <string, bool> filePaths;
44
45                 SortedDictionary <string, bool> FilePaths {
46                         get {
47                                 if (filePaths == null)
48                                         filePaths = new SortedDictionary <string, bool> (Helpers.StringComparer);
49                                 return filePaths;
50                         }
51                 }
52
53                 public bool IsEmpty {
54                         get { return (filePaths == null || filePaths.Count == 0); }
55                 }
56                 
57                 public FileChangeNotificationSystemEntry (string dirPath, FileChangeNotificationSystem owner)
58                 {
59                         if (String.IsNullOrEmpty (dirPath))
60                                 throw new ArgumentNullException ("dirPath");
61
62                         if (owner == null)
63                                 throw new ArgumentNullException ("owner");
64                         
65                         watchedDirPath = dirPath;
66                         this.owner = owner;
67                 }
68                 
69                 public void Add (string filePath)
70                 {
71                         if (String.IsNullOrEmpty (filePath))
72                                 return;
73
74                         bool start = false;
75                         try {
76                                 if (watcher == null) {
77                                         watcher = new FileSystemWatcher (watchedDirPath);
78                                         watcher.IncludeSubdirectories = false;
79                                         watcher.Filter = String.Empty;
80                                         watcher.NotifyFilter = NotifyFilters.FileName |
81                                                 NotifyFilters.DirectoryName |
82                                                 NotifyFilters.Size |
83                                                 NotifyFilters.LastWrite |
84                                                 NotifyFilters.CreationTime;
85                                         watcher.Changed += OnChanged;
86                                         watcher.Created += OnChanged;
87                                         watcher.Deleted += OnChanged;
88                                         watcher.Renamed += OnRenamed;
89                                 } else if (watcher.EnableRaisingEvents) {
90                                         Stop ();
91                                         start = true;
92                                 }
93                         
94                                 SortedDictionary <string, bool> filePaths = FilePaths;
95                                 if (filePaths.ContainsKey (filePath))
96                                         return;
97
98                                 filePaths.Add (filePath, true);
99                         } finally {
100                                 if (start)
101                                         Start ();
102                         }
103                 }
104
105                 public void Remove (string filePath)
106                 {
107                         if (filePath == null)
108                                 return;
109
110                         bool start = false;
111                         try {
112                                 if (watcher != null && watcher.EnableRaisingEvents) {
113                                         Stop ();
114                                         start = true;
115                                 }
116                                 
117                                 SortedDictionary <string, bool> filePaths = FilePaths;
118                                 if (!filePaths.ContainsKey (filePath))
119                                         return;
120
121                                 filePaths.Remove (filePath);
122                         } finally {
123                                 if (start)
124                                         Start ();
125                         }
126                 }
127                 
128                 public void Start ()
129                 {
130                         if (watcher == null)
131                                 return;
132
133                         watcher.EnableRaisingEvents = true;
134                 }
135
136                 public void Stop ()
137                 {
138                         if (watcher == null)
139                                 return;
140
141                         watcher.EnableRaisingEvents = false;
142                 }
143
144                 public void Dispose ()
145                 {
146                         if (watcher == null)
147                                 return;
148
149                         try {
150                                 Stop ();
151                         } finally {     
152                                 watcher.Dispose ();
153                         }
154                 }
155
156                 void IDisposable.Dispose ()
157                 {
158                         Dispose ();
159                 }
160                 
161                 void OnChanged (object source, FileSystemEventArgs e)
162                 {
163                         string fullPath = e.FullPath;
164                         if (owner == null || filePaths == null || !filePaths.ContainsKey (fullPath))
165                                 return;
166                         
167                         owner.OnChanged (e.ChangeType, fullPath, null);
168                 }
169
170                 void OnRenamed (object source, RenamedEventArgs e)
171                 {
172                         string fullPath = e.FullPath;
173                         if (owner == null || filePaths == null || !filePaths.ContainsKey (fullPath))
174                                 return;
175
176                         owner.OnChanged (e.ChangeType, e.OldFullPath, e.FullPath);
177                 }
178         }
179 }