This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mcs / class / System.Web / System.Web.Caching / CacheDependency.cs
1 // 
2 // System.Web.Caching.CacheDependency
3 //
4 // Authors:
5 //      Patrik Torstensson
6 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 //
8 // (c) 2003 Ximian, Inc. (http://www.ximian.com)
9 //
10
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31 using System;
32 using System.IO;
33 using System.Web;
34
35 namespace System.Web.Caching
36 {
37         internal class CacheDependencyChangedArgs : EventArgs
38         {
39                 string key;
40
41                 public CacheDependencyChangedArgs (string key)
42                 {
43                         this.key = key;
44                 }
45
46                 public string Key {
47                         get { return key; }
48                 }
49         }
50
51         internal delegate void CacheDependencyChangedHandler (object sender, CacheDependencyChangedArgs args);
52
53         public sealed class CacheDependency : IDisposable
54         {
55                 static string [] noStrings = new string [0];
56                 static CacheDependency noDependency = new CacheDependency ();
57                 DateTime start;
58                 bool changed;
59                 bool disposed;
60                 CacheEntry [] entries;
61                 CacheItemRemovedCallback removedDelegate;
62                 FileSystemWatcher [] watchers;
63
64                 private CacheDependency ()
65                 {
66                 }
67
68                 public CacheDependency (string filename)
69                         : this (filename, DateTime.MaxValue)
70                 {
71                 }
72
73                 public CacheDependency (string filename, DateTime start)
74                         : this (new string [] {filename}, null, null, start)
75                 {
76                 }
77
78                 public CacheDependency (string [] filenames)
79                         : this (filenames, null, null, DateTime.MaxValue)
80                 {
81                 }
82
83                 public CacheDependency (string [] filenames, DateTime start)
84                         : this (filenames, null, null, start)
85                 {
86                 }
87
88                 public CacheDependency (string [] filenames, string [] cachekeys)
89                         : this (filenames, cachekeys, null, DateTime.MaxValue)
90                 {
91                 }
92
93                 public CacheDependency (string [] filenames, string [] cachekeys, DateTime start)
94                         : this (filenames, cachekeys, null, start)
95                 {
96                 }
97
98                 public CacheDependency (string [] filenames, string [] cachekeys, CacheDependency dependency)
99                         : this (filenames, cachekeys, dependency, DateTime.MaxValue)
100                 {
101                 }
102
103                 public CacheDependency (string [] filenames,
104                                         string [] cachekeys,
105                                         CacheDependency dependency,
106                                         DateTime start)
107                 {
108                         Cache cache = HttpRuntime.Cache;
109
110                         this.start = start;
111                         if (filenames == null)
112                                 filenames = noStrings;
113
114                         foreach (string file in filenames) {
115                                 if (file == null)
116                                         throw new ArgumentNullException ("filenames");
117                         }
118
119                         if (cachekeys == null)
120                                 cachekeys = noStrings;
121
122                         int missing_keys = 0;
123                         foreach (string ck in cachekeys) {
124                                 if (ck == null)
125                                         throw new ArgumentNullException ("cachekeys");
126                                 if (cache.GetEntry (ck) == null)
127                                         missing_keys++;
128                         }
129
130                         if (dependency == null)
131                                 dependency = noDependency;
132
133
134                         this.changed = dependency.changed;
135                         if (changed == true)
136                                 return;
137
138                         int nentries = cachekeys.Length + ((dependency.entries == null) ? 0 :
139                                                                   dependency.entries.Length) - missing_keys;
140
141                         if (nentries != 0) {
142                                 this.removedDelegate = new CacheItemRemovedCallback (CacheItemRemoved);
143                                 this.entries = new CacheEntry [nentries];
144                                 
145                                 int i = 0;
146                                 if (dependency.entries != null) {
147                                         foreach (CacheEntry entry in dependency.entries) {
148                                                 entry._onRemoved += removedDelegate;
149                                                 entries [i++] = entry;
150                                         }
151                                 }
152
153                                 for (int c=0; c<cachekeys.Length; c++) {
154                                         CacheEntry entry = cache.GetEntry (cachekeys [c]);
155                                         if (entry == null)
156                                                 continue;
157                                         entry._onRemoved += removedDelegate;
158                                         entries [i++] = entry;
159                                 }
160                         }
161
162                         if (filenames.Length > 0) {
163                                 watchers = new FileSystemWatcher [filenames.Length];
164                                 for (int i=0; i<filenames.Length; i++)
165                                         watchers [i] = CreateWatcher (filenames [i]);
166                         }
167                 }
168
169                 private FileSystemWatcher CreateWatcher (string file)
170                 {
171                         FileSystemWatcher watcher = new FileSystemWatcher ();
172
173                         watcher.Path = Path.GetFullPath (Path.GetDirectoryName (file));
174                         watcher.Filter = Path.GetFileName (file);
175
176                         watcher.Changed += new FileSystemEventHandler (OnFileChanged);
177                         watcher.Created += new FileSystemEventHandler (OnFileChanged);
178                         watcher.Deleted += new FileSystemEventHandler (OnFileChanged);
179
180                         watcher.EnableRaisingEvents = true;
181
182                         return watcher;
183                 }
184
185                 private void OnFileChanged (object sender, FileSystemEventArgs e)
186                 {
187                         OnChanged (sender, e);
188                 }
189
190                 void CacheItemRemoved (string key, object value, CacheItemRemovedReason reason)
191                 {
192                         OnChanged (this, EventArgs.Empty);
193                 }
194
195                 void OnChanged (object sender, EventArgs args)
196                 {
197                         if (changed || disposed)
198                                 return;
199
200                         changed = true;
201                         if (Changed != null)
202                                 Changed (this, new CacheDependencyChangedArgs (null));
203                 }
204
205                 public void Dispose ()
206                 {
207                         for (int i=0; i<watchers.Length; i++)
208                                 watchers [i].Dispose ();
209                 }
210
211                 public bool HasChanged
212                 {
213                         get { return changed; }
214                 }
215
216                 internal CacheEntry [] GetCacheEntries ()
217                 {
218                         return entries;
219                 }
220
221                 internal event CacheDependencyChangedHandler Changed;
222         }
223 }
224