Implement FileSystemWatcher stub and remove redundand TARGET_JVM ifdefs
[mono.git] / mcs / class / System.Web / System.Web.Caching / CacheDependency.cs
1 //
2 // System.Web.Caching.CachedDependency
3 //
4 // Author(s):
5 //  Lluis Sanchez (lluis@ximian.com)
6 //
7 // (C) 2005 Novell, Inc (http://www.novell.com)
8 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 //
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.Collections;
31 using System.IO;
32 using System.Security.Permissions;
33 #if NET_2_0
34 using System.Text;
35 #endif
36
37 namespace System.Web.Caching
38 {
39 #if NET_2_0
40         // CAS
41         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
42         [AspNetHostingPermission (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
43         public class CacheDependency: IDisposable {
44 #else
45         // CAS - no InheritanceDemand here as the class is sealed
46         [AspNetHostingPermission (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
47         public sealed class CacheDependency: IDisposable {
48 #endif
49                 string[] cachekeys;
50                 CacheDependency dependency;
51                 DateTime start;
52                 Cache cache;
53                 FileSystemWatcher[] watchers;
54                 bool hasChanged;
55 #if NET_2_0
56                 bool used;
57 #endif
58                 object locker = new object ();
59                 
60 #if NET_2_0
61                 public CacheDependency (): this (null, null, null, DateTime.Now)
62                 {
63                 }
64 #endif
65                 
66                 public CacheDependency (string filename): this (new string[] { filename }, null, null, DateTime.Now)
67                 {
68                 }
69                 
70                 public CacheDependency (string[] filenames): this (filenames, null, null, DateTime.Now)
71                 {
72                 }
73                 
74                 public CacheDependency (string filename, DateTime start): this (new string[] { filename }, null, null, start)
75                 {
76                 }
77
78                 public CacheDependency (string [] filenames, DateTime start)
79                         : this (filenames, null, null, start)
80                 {
81                 }
82
83                 public CacheDependency (string[] filenames, string[] cachekeys): this (filenames, cachekeys, null, DateTime.Now)
84                 {
85                 }
86                 
87                 public CacheDependency (string[] filenames, string[] cachekeys, CacheDependency dependency): this (filenames, cachekeys, dependency, DateTime.Now)
88                 {
89                 }
90                 
91                 public CacheDependency (string[] filenames, string[] cachekeys, DateTime start): this (filenames, cachekeys, null, start)
92                 {
93                 }
94                 
95                 public CacheDependency (string[] filenames, string[] cachekeys, CacheDependency dependency, DateTime start)
96                 {
97                         if (filenames != null) {
98                                 watchers = new FileSystemWatcher [filenames.Length];
99                                 for (int n=0; n<filenames.Length; n++) {
100                                         FileSystemWatcher watcher = new FileSystemWatcher ();
101                                         if (Directory.Exists (filenames [n])) {
102                                                 watcher.Path = filenames [n];
103                                         } else {
104                                                 string parentPath = Path.GetDirectoryName (filenames [n]);
105                                                 if (parentPath != null && Directory.Exists (parentPath)) {
106                                                         watcher.Path = parentPath;
107                                                         watcher.Filter = Path.GetFileName (filenames [n]);
108                                                 } else
109                                                         continue;
110                                         }
111                                         watcher.Created += new FileSystemEventHandler (OnChanged);
112                                         watcher.Changed += new FileSystemEventHandler (OnChanged);
113                                         watcher.Deleted += new FileSystemEventHandler (OnChanged);
114                                         watcher.Renamed += new RenamedEventHandler (OnChanged);
115                                         watcher.EnableRaisingEvents = true;
116                                         watchers [n] = watcher;
117                                 }
118                         }
119                         this.cachekeys = cachekeys;
120                         this.dependency = dependency;
121                         if (dependency != null)
122                                 dependency.DependencyChanged += new EventHandler (OnChildDependencyChanged);
123                         this.start = start;
124                 }
125
126 #if NET_2_0
127                 public virtual string GetUniqueID ()
128                 {
129                         StringBuilder sb = new StringBuilder ();
130                         lock (locker) {
131                                 if (watchers != null)
132                                         foreach (FileSystemWatcher fsw in watchers)
133                                                 if (fsw != null && fsw.Path != null && fsw.Path.Length != 0)
134                                                         sb.AppendFormat ("_{0}", fsw.Path);
135                         }
136
137                         if (cachekeys != null)
138                                 foreach (string key in cachekeys)
139                                         sb.AppendFormat ("_{0}", key);
140                         return sb.ToString ();
141                 }
142 #endif
143                 
144                 void OnChanged (object sender, FileSystemEventArgs args)
145                 {
146                         if (DateTime.Now < start)
147                                 return;
148                         hasChanged = true;
149                         DisposeWatchers ();
150                         
151                         if (cache != null)
152                                 cache.CheckExpiration ();
153                 }
154         
155                 void DisposeWatchers ()
156                 {
157                         lock (locker) {
158                                 if (watchers != null) {
159                                         foreach (FileSystemWatcher w in watchers)
160                                                 if (w != null)
161                                                         w.Dispose ();
162                                 }
163                                 watchers = null;
164                         }
165                 }
166                 public void Dispose ()
167                 {
168                         DisposeWatchers ();
169                         if (dependency != null)
170                                 dependency.DependencyChanged -= new EventHandler (OnChildDependencyChanged);
171                         cache = null;
172                 }
173                 
174                 internal void SetCache (Cache c)
175                 {
176                         cache = c;
177 #if NET_2_0
178                         used = c != null;
179 #endif
180                 }
181                 
182 #if NET_2_0
183                 internal bool IsUsed {
184                         get { return used; }
185                 }
186
187                 internal DateTime Start {
188                         get { return start; }
189                         set { start = value; }
190                 }
191 #endif
192                 
193                 public bool HasChanged {
194                         get {
195                                 if (hasChanged)
196                                         return true;
197
198                                 if (DateTime.Now < start)
199                                         return false;
200
201                                 if (cache != null && cachekeys != null) {
202                                         foreach (string key in cachekeys) {
203                                                 if (cache.GetKeyLastChange (key) > start) {
204                                                         hasChanged = true;
205                                                         break;
206                                                 }
207                                         }
208                                 }
209                                 if (hasChanged)
210                                         DisposeWatchers ();
211
212                                 return hasChanged;
213                         }
214                 }
215                 
216                 void OnChildDependencyChanged (object o, EventArgs a)
217                 {
218                         hasChanged = true;
219                         OnDependencyChanged ();
220                 }
221                 
222                 void OnDependencyChanged ()
223                 {
224                         if (DependencyChanged != null)
225                                 DependencyChanged (this, null);
226                 }
227                 
228 #if NET_2_0
229                 internal void SignalDependencyChanged ()
230                 {
231                         OnDependencyChanged ();
232                 }
233 #endif
234                 internal event EventHandler DependencyChanged;
235         }
236 }