merged Sys.Web.Services 2.0 support in my branch:
[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 #if !TARGET_JVM
54                 FileSystemWatcher[] watchers;
55 #endif
56                 bool hasChanged;
57 #if NET_2_0
58                 bool used;
59 #endif
60                 object locker = new object ();
61                 
62 #if NET_2_0
63                 public CacheDependency (): this (null, null, null, DateTime.Now)
64                 {
65                 }
66 #endif
67                 
68                 public CacheDependency (string filename): this (new string[] { filename }, null, null, DateTime.Now)
69                 {
70                 }
71                 
72                 public CacheDependency (string[] filenames): this (filenames, null, null, DateTime.Now)
73                 {
74                 }
75                 
76                 public CacheDependency (string filename, DateTime start): this (new string[] { filename }, null, null, start)
77                 {
78                 }
79
80                 public CacheDependency (string [] filenames, DateTime start)
81                         : this (filenames, null, null, start)
82                 {
83                 }
84
85                 public CacheDependency (string[] filenames, string[] cachekeys): this (filenames, cachekeys, null, DateTime.Now)
86                 {
87                 }
88                 
89                 public CacheDependency (string[] filenames, string[] cachekeys, CacheDependency dependency): this (filenames, cachekeys, dependency, DateTime.Now)
90                 {
91                 }
92                 
93                 public CacheDependency (string[] filenames, string[] cachekeys, DateTime start): this (filenames, cachekeys, null, start)
94                 {
95                 }
96                 
97                 public CacheDependency (string[] filenames, string[] cachekeys, CacheDependency dependency, DateTime start)
98                 {
99 #if !TARGET_JVM
100                         if (filenames != null) {
101                                 watchers = new FileSystemWatcher [filenames.Length];
102                                 for (int n=0; n<filenames.Length; n++) {
103                                         FileSystemWatcher watcher = new FileSystemWatcher ();
104                                         if (Directory.Exists (filenames [n])) {
105                                                 watcher.Path = filenames [n];
106                                         } else {
107                                                 string parentPath = Path.GetDirectoryName (filenames [n]);
108                                                 if (parentPath != null && Directory.Exists (parentPath)) {
109                                                         watcher.Path = parentPath;
110                                                         watcher.Filter = Path.GetFileName (filenames [n]);
111                                                 } else
112                                                         continue;
113                                         }
114                                         watcher.Created += new FileSystemEventHandler (OnChanged);
115                                         watcher.Changed += new FileSystemEventHandler (OnChanged);
116                                         watcher.Deleted += new FileSystemEventHandler (OnChanged);
117                                         watcher.Renamed += new RenamedEventHandler (OnChanged);
118                                         watcher.EnableRaisingEvents = true;
119                                         watchers [n] = watcher;
120                                 }
121                         }
122 #endif
123                         this.cachekeys = cachekeys;
124                         this.dependency = dependency;
125                         if (dependency != null)
126                                 dependency.DependencyChanged += new EventHandler (OnChildDependencyChanged);
127                         this.start = start;
128                 }
129
130 #if NET_2_0
131                 public virtual string GetUniqueID ()
132                 {
133                         StringBuilder sb = new StringBuilder ();
134 #if !TARGET_JVM
135                         lock (locker) {
136                                 if (watchers != null)
137                                         foreach (FileSystemWatcher fsw in watchers)
138                                                 if (fsw != null && fsw.Path != null && fsw.Path.Length != 0)
139                                                         sb.AppendFormat ("_{0}", fsw.Path);
140                         }
141 #endif
142
143                         if (cachekeys != null)
144                                 foreach (string key in cachekeys)
145                                         sb.AppendFormat ("_{0}", key);
146                         return sb.ToString ();
147                 }
148 #endif
149                 
150 #if !TARGET_JVM
151                 void OnChanged (object sender, FileSystemEventArgs args)
152                 {
153                         if (DateTime.Now < start)
154                                 return;
155                         hasChanged = true;
156                         DisposeWatchers ();
157                         
158                         if (cache != null)
159                                 cache.CheckExpiration ();
160                 }
161         
162                 void DisposeWatchers ()
163                 {
164                         lock (locker) {
165                                 if (watchers != null) {
166                                         foreach (FileSystemWatcher w in watchers)
167                                                 if (w != null)
168                                                         w.Dispose ();
169                                 }
170                                 watchers = null;
171                         }
172                 }
173 #else
174                 void DisposeWatchers ()
175                 {
176                 }
177 #endif
178                 public void Dispose ()
179                 {
180                         DisposeWatchers ();
181                         if (dependency != null)
182                                 dependency.DependencyChanged -= new EventHandler (OnChildDependencyChanged);
183                         cache = null;
184                 }
185                 
186                 internal void SetCache (Cache c)
187                 {
188                         cache = c;
189 #if NET_2_0
190                         used = c != null;
191 #endif
192                 }
193                 
194 #if NET_2_0
195                 internal bool IsUsed {
196                         get { return used; }
197                 }
198
199                 internal DateTime Start {
200                         get { return start; }
201                         set { start = value; }
202                 }
203 #endif
204                 
205                 public bool HasChanged {
206                         get {
207                                 if (hasChanged)
208                                         return true;
209
210                                 if (DateTime.Now < start)
211                                         return false;
212
213                                 if (cache != null && cachekeys != null) {
214                                         foreach (string key in cachekeys) {
215                                                 if (cache.GetKeyLastChange (key) > start) {
216                                                         hasChanged = true;
217                                                         break;
218                                                 }
219                                         }
220                                 }
221                                 if (hasChanged)
222                                         DisposeWatchers ();
223
224                                 return hasChanged;
225                         }
226                 }
227                 
228                 void OnChildDependencyChanged (object o, EventArgs a)
229                 {
230                         hasChanged = true;
231                         OnDependencyChanged ();
232                 }
233                 
234                 void OnDependencyChanged ()
235                 {
236                         if (DependencyChanged != null)
237                                 DependencyChanged (this, null);
238                 }
239                 
240 #if NET_2_0
241                 internal void SignalDependencyChanged ()
242                 {
243                         OnDependencyChanged ();
244                 }
245 #endif
246                 internal event EventHandler DependencyChanged;
247         }
248 }