2010-02-03 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Caching / OutputCacheModule.cs
index f723c8b91c062a3c4700ee1b7b0552ab281f3a4b..00fea61b66089e399d604a204d5526ad98bcbeb8 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.Configuration.Provider;
 using System.IO;
 using System.Text;
 using System.Web;
+using System.Web.Hosting;
 using System.Web.UI;
 using System.Web.Util;
 using System.Web.Compilation;
@@ -42,15 +45,52 @@ namespace System.Web.Caching
 {      
        sealed class OutputCacheModule : IHttpModule
        {
+               OutputCacheProvider provider;
                CacheItemRemovedCallback response_removed;
                static object keysCacheLock = new object ();
                Dictionary <string, string> keysCache;
                Dictionary <string, string> entriesToInvalidate;
-               
+
                public OutputCacheModule ()
                {
                }
 
+               OutputCacheProvider FindCacheProvider (HttpApplication app)
+               {                               
+#if NET_4_0
+                       HttpContext ctx = HttpContext.Current;
+                       if (app == null) {
+                               app = ctx != null ? ctx.ApplicationInstance : null;
+
+                               if (app == null)
+                                       throw new InvalidOperationException ("Unable to find output cache provider.");
+                       }
+
+                       string providerName = app.GetOutputCacheProviderName (ctx);
+                       if (String.IsNullOrEmpty (providerName))
+                               throw new ProviderException ("Invalid OutputCacheProvider name. Name must not be null or an empty string.");
+                       
+                       if (String.Compare (providerName, OutputCache.DEFAULT_PROVIDER_NAME, StringComparison.Ordinal) == 0) {
+                               if (provider == null)
+                                       provider = new InMemoryOutputCacheProvider ();
+                               return provider;
+                       }
+
+                       OutputCacheProviderCollection providers = OutputCache.Providers;
+                       OutputCacheProvider ret = providers != null ? providers [providerName] : null;
+
+                       if (ret == null)
+                               throw new ProviderException (String.Format ("OutputCacheProvider named '{0}' cannot be found.", providerName));
+
+                       return ret;
+#else
+                       if (provider == null)
+                               provider = new InMemoryOutputCacheProvider ();
+                       
+                       return provider;
+#endif
+               }
+               
                public void Dispose ()
                {
                }
@@ -67,11 +107,11 @@ namespace System.Web.Caching
                        string entry = args.EntryName;
                        HttpContext context = args.Context;
                        string cacheValue;
-                       
+
                        lock (keysCacheLock) {
                                if (!keysCache.TryGetValue (entry, out cacheValue))
                                        return;
-                               
+
                                keysCache.Remove (entry);
                                if (context == null) {
                                        if (entriesToInvalidate == null) {
@@ -85,18 +125,23 @@ namespace System.Web.Caching
                                }
                        }
 
-                       context.Cache.Remove (entry);
+                       OutputCacheProvider provider = FindCacheProvider (context != null ? context.ApplicationInstance : null);
+                       provider.Remove (entry);
                        if (!String.IsNullOrEmpty (cacheValue))
-                               context.InternalCache.Remove (cacheValue);
+                               provider.Remove (cacheValue);
                }
 
                void OnResolveRequestCache (object o, EventArgs args)
                {
-                       HttpApplication app = (HttpApplication) o;
-                       HttpContext context = app.Context;
-                       
+                       HttpApplication app = o as HttpApplication;
+                       HttpContext context = app != null ? app.Context : null;
+
+                       if (context == null)
+                               return;
+
+                       OutputCacheProvider provider = FindCacheProvider (app);
                        string vary_key = context.Request.FilePath;
-                       CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy;
+                       CachedVaryBy varyby = provider.Get (vary_key) as CachedVaryBy;
                        string key;
                        CachedRawResponse c;
 
@@ -104,15 +149,15 @@ namespace System.Web.Caching
                                return;
 
                        key = varyby.CreateKey (vary_key, context);
-                       c = context.InternalCache [key] as CachedRawResponse;
+                       c = provider.Get (key) as CachedRawResponse;
                        if (c == null)
                                return;
 
                        lock (keysCacheLock) {
                                string invValue;
                                if (entriesToInvalidate != null && entriesToInvalidate.TryGetValue (vary_key, out invValue) && String.Compare (invValue, key, StringComparison.Ordinal) == 0) {
-                                       context.Cache.Remove (vary_key);
-                                       context.InternalCache.Remove (key);
+                                       provider.Remove (vary_key);
+                                       provider.Remove (key);
                                        entriesToInvalidate.Remove (vary_key);
                                        return;
                                }
@@ -147,9 +192,8 @@ namespace System.Web.Caching
                                if (!isValid) {
                                        OnRawResponseRemoved (key, c, CacheItemRemovedReason.Removed);
                                        return;
-                               } else if (isIgnored) {
+                               } else if (isIgnored)
                                        return;
-                               }
                        }
 
                        HttpResponse response = context.Response;                       
@@ -186,33 +230,28 @@ namespace System.Web.Caching
 
                void OnUpdateRequestCache (object o, EventArgs args)
                {
-                       HttpApplication app = (HttpApplication) o;
-                       HttpContext context = app.Context;
-
-                       if (context.Response.IsCached && context.Response.StatusCode == 200 && 
-                           !context.Trace.IsEnabled)
-                               DoCacheInsert (context);
+                       HttpApplication app = o as HttpApplication;
+                       HttpContext context = app != null ? app.Context : null;
+                       HttpResponse response = context != null ? context.Response : null;
+                       
+                       if (response != null && response.IsCached && response.StatusCode == 200 && !context.Trace.IsEnabled)
+                               DoCacheInsert (context, app, response);
                }
 
-               void DoCacheInsert (HttpContext context)
+               void DoCacheInsert (HttpContext context, HttpApplication app, HttpResponse response)
                {
                        string vary_key = context.Request.FilePath;
                        string key;
-                       CachedVaryBy varyby = context.Cache [vary_key] as CachedVaryBy;
+                       OutputCacheProvider provider = FindCacheProvider (app);
+                       CachedVaryBy varyby = provider.Get (vary_key) as CachedVaryBy;
                        CachedRawResponse prev = null;
                        bool lookup = true;
                        string cacheKey = null, cacheValue = null;
+                       HttpCachePolicy cachePolicy = response.Cache;
                        
                        if (varyby == null) {
-                               string path = context.Request.MapPath (vary_key);
-                               string [] files = new string [] { path };
-                               string [] keys = new string [0];
-                               varyby = new CachedVaryBy (context.Response.Cache, vary_key);
-                               context.Cache.Insert (vary_key, varyby,
-                                                             new CacheDependency (files, keys),
-                                                             Cache.NoAbsoluteExpiration,
-                                                             Cache.NoSlidingExpiration,
-                                                             CacheItemPriority.Normal, null);
+                               varyby = new CachedVaryBy (cachePolicy, vary_key);
+                               provider.Add (vary_key, varyby, Cache.NoAbsoluteExpiration);
                                lookup = false;
                                cacheKey = vary_key;
                        } 
@@ -220,24 +259,31 @@ namespace System.Web.Caching
                        key = varyby.CreateKey (vary_key, context);
 
                        if (lookup)
-                               prev = context.InternalCache [key] as CachedRawResponse;
+                               prev = provider.Get (key) as CachedRawResponse;
                        
                        if (prev == null) {
-                               CachedRawResponse c = context.Response.GetCachedResponse ();
+                               CachedRawResponse c = response.GetCachedResponse ();
                                if (c != null) {
-                                       string [] files = new string [] { };
                                        string [] keys = new string [] { vary_key };
-                                       bool sliding = context.Response.Cache.Sliding;
-
-                                       context.InternalCache.Insert (key, c, new CacheDependency (files, keys),
-                                                                     (sliding ? Cache.NoAbsoluteExpiration :
-                                                                      context.Response.Cache.Expires),
-                                                                     (sliding ? TimeSpan.FromSeconds (
-                                                                             context.Response.Cache.Duration) :
-                                                                      Cache.NoSlidingExpiration),
-                                                                     CacheItemPriority.Normal, response_removed);
+                                       DateTime utcExpiry, absoluteExpiration;
+                                       TimeSpan slidingExpiration;
+
                                        c.VaryBy = varyby;
                                        varyby.ItemList.Add (key);
+
+                                       if (cachePolicy.Sliding) {
+                                               slidingExpiration = TimeSpan.FromSeconds (cachePolicy.Duration);
+                                               absoluteExpiration = Cache.NoAbsoluteExpiration;
+                                               utcExpiry = DateTime.UtcNow + slidingExpiration;
+                                       } else {
+                                               slidingExpiration = Cache.NoSlidingExpiration;
+                                               absoluteExpiration = cachePolicy.Expires;
+                                               utcExpiry = absoluteExpiration.ToUniversalTime ();
+                                       }
+
+                                       provider.Set (key, c, utcExpiry);
+                                       HttpRuntime.InternalCache.Insert (key, c, new CacheDependency (null, keys), absoluteExpiration, slidingExpiration,
+                                                                         CacheItemPriority.Normal, response_removed);
                                        cacheValue = key;
                                }
                        }
@@ -254,16 +300,23 @@ namespace System.Web.Caching
                        }
                }
 
-               static void OnRawResponseRemoved (string key, object value, CacheItemRemovedReason reason)
+               void OnRawResponseRemoved (string key, object value, CacheItemRemovedReason reason)
                {
-                       CachedRawResponse c = (CachedRawResponse) value;
+                       CachedRawResponse c = value as CachedRawResponse;
+                       CachedVaryBy varyby = c != null ? c.VaryBy : null;
+                       if (varyby == null)
+                               return;
 
-                       c.VaryBy.ItemList.Remove (key);                 
-                       if (c.VaryBy.ItemList.Count != 0)
+                       List <string> itemList = varyby.ItemList;
+                       OutputCacheProvider provider = FindCacheProvider (null);
+                       
+                       itemList.Remove (key);
+                       provider.Remove (key);
+                       
+                       if (itemList.Count != 0)
                                return;                 
 
-                       HttpRuntime.Cache.Remove (c.VaryBy.Key);
+                       provider.Remove (varyby.Key);
                }
        }
 }
-