Merge pull request #2962 from marek-safar/referencesource-submodule-move
[mono.git] / mcs / class / referencesource / System.Web / httpapplicationstate.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="httpapplicationstate.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>                                                                
5 //------------------------------------------------------------------------------
6
7 /*
8  * Application State Dictionary class
9  * 
10  * Copyright (c) 1999 Microsoft Corporation
11  */
12
13 namespace System.Web {
14     using System.Threading;
15     using System.Runtime.InteropServices;
16     using System.Security.Permissions;
17
18     using System.Collections;
19     using System.Collections.Specialized;
20     using System.Web;
21     using System.Web.Util;
22
23     //
24     //  Application state collection
25     //
26     
27
28     /// <devdoc>
29     ///    <para>
30     ///       The HttpApplicationState class enables developers to
31     ///       share global information across multiple requests, sessions, and pipelines
32     ///       within an ASP.NET application. (An ASP.NET application is the sum of all files, pages,
33     ///       handlers, modules, and code
34     ///       within the scope of a virtual directory and its
35     ///       subdirectories on a single web server).
36     ///    </para>
37     /// </devdoc>
38     public sealed class HttpApplicationState : NameObjectCollectionBase {
39         // app lock with auto-unlock feature
40         private HttpApplicationStateLock _lock = new HttpApplicationStateLock();
41
42         // static object collections
43         private HttpStaticObjectsCollection _applicationStaticObjects;
44         private HttpStaticObjectsCollection _sessionStaticObjects;
45
46         internal HttpApplicationState() : this(null, null) {
47         }
48
49         internal HttpApplicationState(HttpStaticObjectsCollection applicationStaticObjects,
50                                       HttpStaticObjectsCollection sessionStaticObjects) 
51             : base(Misc.CaseInsensitiveInvariantKeyComparer) {
52             _applicationStaticObjects = applicationStaticObjects;
53
54             if (_applicationStaticObjects == null)
55                 _applicationStaticObjects = new HttpStaticObjectsCollection();
56
57             _sessionStaticObjects = sessionStaticObjects;
58
59             if (_sessionStaticObjects == null)
60                 _sessionStaticObjects = new HttpStaticObjectsCollection();
61         }
62
63         //
64         // Internal accessor to session static objects collection
65         //
66
67         internal HttpStaticObjectsCollection SessionStaticObjects {
68             get { return _sessionStaticObjects;}
69         }
70
71         //
72         // Implementation of standard collection stuff
73         //
74
75
76         /// <devdoc>
77         ///    <para>Gets
78         ///       the number of item objects in the application state collection.</para>
79         /// </devdoc>
80         public override int Count {
81             get {
82                 int c = 0;
83                 _lock.AcquireRead(); 
84                 try {
85                     c = base.Count;
86                 }
87                 finally {
88                     _lock.ReleaseRead();
89                 }
90
91                 return c;
92             }
93         }
94
95         // modifying methods
96
97
98         /// <devdoc>
99         ///    <para>
100         ///       Adds
101         ///       a new state object to the application state collection.
102         ///    </para>
103         /// </devdoc>
104         public void Add(String name, Object value) {
105             _lock.AcquireWrite(); 
106             try {
107                 BaseAdd(name, value);
108             }
109             finally {
110                 _lock.ReleaseWrite();
111             }
112         }
113
114
115         /// <devdoc>
116         ///    <para>Updates an HttpApplicationState value within the collection.</para>
117         /// </devdoc>
118         public void Set(String name, Object value) {
119             _lock.AcquireWrite(); 
120             try {
121                 BaseSet(name, value);
122             }
123             finally {
124                 _lock.ReleaseWrite();
125             }
126         }
127
128
129         /// <devdoc>
130         ///    <para>Removes
131         ///       an
132         ///       object from the application state collection by name.</para>
133         /// </devdoc>
134         public void Remove(String name) {
135             _lock.AcquireWrite(); 
136             try {
137                 BaseRemove(name);
138             }
139             finally {
140                 _lock.ReleaseWrite();
141             }
142         }
143
144
145         /// <devdoc>
146         ///    <para>Removes
147         ///       an
148         ///       object from the application state collection by name.</para>
149         /// </devdoc>
150         public void RemoveAt(int index) {
151             _lock.AcquireWrite(); 
152             try {
153                 BaseRemoveAt(index);
154             }
155             finally {
156                 _lock.ReleaseWrite();
157             }
158         }
159
160
161         /// <devdoc>
162         ///    <para>
163         ///       Removes
164         ///       all objects from the application state collection.
165         ///    </para>
166         /// </devdoc>
167         public void Clear() {
168             _lock.AcquireWrite(); 
169             try {
170                 BaseClear();
171             }
172             finally {
173                 _lock.ReleaseWrite();
174             }
175         }
176
177
178         /// <devdoc>
179         ///    <para>
180         ///       Removes
181         ///       all objects from the application state collection.
182         ///    </para>
183         /// </devdoc>
184         public void RemoveAll() {
185             Clear();
186         }
187
188         // access by key
189
190
191         /// <devdoc>
192         ///    <para>
193         ///       Enables user to retrieve application state object by name.
194         ///    </para>
195         /// </devdoc>
196         public Object Get(String name) {
197             Object obj = null;
198             _lock.AcquireRead(); 
199             try {
200                 obj = BaseGet(name);
201             }
202             finally {
203                 _lock.ReleaseRead();
204             }
205
206             return obj;
207         }
208
209
210         /// <devdoc>
211         ///    <para>Enables
212         ///       a user to add/remove/update a single application state object.</para>
213         /// </devdoc>
214         public Object this[String name]
215         {
216             get { return Get(name);}
217             set { Set(name, value);}
218         }
219
220         // access by index
221
222
223         /// <devdoc>
224         ///    <para>
225         ///       Enables user
226         ///       to retrieve a single application state object by index.
227         ///    </para>
228         /// </devdoc>
229         public Object Get(int index) {
230             Object obj = null;
231
232             _lock.AcquireRead(); 
233             try {
234                 obj = BaseGet(index);
235             }
236             finally {
237                 _lock.ReleaseRead();
238             }
239
240             return obj;
241         }
242
243
244         /// <devdoc>
245         ///    <para>
246         ///       Enables user to retrieve an application state object name by index.
247         ///    </para>
248         /// </devdoc>
249         public String GetKey(int index) {
250             String s = null;
251             _lock.AcquireRead(); 
252             try {
253                 s = BaseGetKey(index);
254             }
255             finally {
256                 _lock.ReleaseRead();
257             }
258
259             return s;
260         }
261
262
263         /// <devdoc>
264         ///    <para>
265         ///       Enables
266         ///       user to retrieve an application state object by index.
267         ///    </para>
268         /// </devdoc>
269         public Object this[int index]
270         {
271             get { return Get(index);}
272         }
273
274         // access to keys and values as arrays
275         
276
277         /// <devdoc>
278         ///    <para>
279         ///       Enables user
280         ///       to retrieve all application state object names in collection.
281         ///    </para>
282         /// </devdoc>
283         public String[] AllKeys {
284             get {
285                 String [] allKeys = null;
286
287                 _lock.AcquireRead(); 
288                 try {
289                     allKeys = BaseGetAllKeys();
290                 }
291                 finally {
292                     _lock.ReleaseRead();
293                 }
294
295                 return allKeys;
296             }
297         }
298
299         //
300         // Public properties
301         //
302
303
304         /// <devdoc>
305         ///    <para>
306         ///       Returns "this". Provided for legacy ASP compatibility.
307         ///    </para>
308         /// </devdoc>
309         public HttpApplicationState Contents {
310             get { return this;}
311         }
312
313
314         /// <devdoc>
315         ///    <para>
316         ///       Exposes all objects declared via an &lt;object
317         ///       runat=server&gt;&lt;/object&gt; tag within the ASP.NET application file.
318         ///    </para>
319         /// </devdoc>
320         public HttpStaticObjectsCollection StaticObjects {
321             get { return _applicationStaticObjects;}
322         }
323
324         //
325         //  Locking support
326         //
327
328
329         /// <devdoc>
330         ///    <para>
331         ///       Locks
332         ///       access to all application state variables. Facilitates access
333         ///       synchronization.
334         ///    </para>
335         /// </devdoc>
336         public void Lock() {
337             _lock.AcquireWrite();
338         }
339
340
341         /// <devdoc>
342         ///    <para>
343         ///       Unocks access to all application state variables. Facilitates access
344         ///       synchronization.
345         ///    </para>
346         /// </devdoc>
347         public void UnLock() {
348             _lock.ReleaseWrite();
349         }
350
351         internal void EnsureUnLock() {
352             _lock.EnsureReleaseWrite();
353         }
354     }
355
356
357     //
358     //  Recursive read-write lock that allows removing of all
359     //  outstanding write locks from the current thread at once
360     //
361     internal class HttpApplicationStateLock : ReadWriteObjectLock {
362         private int _recursionCount;
363         private int _threadId;
364
365         internal HttpApplicationStateLock() {
366         }
367
368         internal override void AcquireRead() {
369             int currentThreadId = SafeNativeMethods.GetCurrentThreadId();
370
371             if (_threadId != currentThreadId)
372                 base.AcquireRead();  // only if no write lock
373         }
374
375         internal override void ReleaseRead() {
376             int currentThreadId = SafeNativeMethods.GetCurrentThreadId();
377
378             if (_threadId != currentThreadId)
379                 base.ReleaseRead();  // only if no write lock
380         }
381
382         internal override void AcquireWrite() {
383             int currentThreadId = SafeNativeMethods.GetCurrentThreadId();
384
385             if (_threadId == currentThreadId) {
386                 _recursionCount++;
387             }
388             else {
389                 base.AcquireWrite();
390                 _threadId = currentThreadId;
391                 _recursionCount = 1;
392             }
393         }
394
395         internal override void ReleaseWrite() {
396             int currentThreadId = SafeNativeMethods.GetCurrentThreadId();
397
398             if (_threadId == currentThreadId) {
399                 if (--_recursionCount == 0) {
400                     _threadId = 0;
401                     base.ReleaseWrite();
402                 }
403             }
404         }
405
406         //
407         // release all write locks held by the current thread
408         //
409
410         internal void EnsureReleaseWrite() {
411             int currentThreadId = SafeNativeMethods.GetCurrentThreadId();
412
413             if (_threadId == currentThreadId) {
414                 _threadId = 0;
415                 _recursionCount = 0;
416                 base.ReleaseWrite();
417             }
418         }
419     }
420
421 }