1 /*++
2 Copyright (c) Microsoft Corporation
3 
4 Module Name:
5 
6     RequestCacheValidator.cs
7 
8 Abstract:
9 
10     The file specifies the contract for plugged cache validation logic.
11 
12 Author:
13 
14     Alexei Vopilov    21-Dec-2002
15 
16 Revision History:
17     Aug 25 2003 - Moved into a separate file and implemented Whidbey M3 changes
18     Jan 25 2004 - Changed the visibility of the class from public to internal.
19 
20 --*/
21 namespace System.Net.Cache {
22 using System;
23 using System.Diagnostics;
24 using System.Text;
25 using System.IO;
26 using System.Collections.Specialized;
27 using System.Threading;
28 
29 
30     //
31     // We need Undefined value because sometime a cache entry does not provide a clue when it should expire
32     // not flags!
33     internal enum CacheFreshnessStatus
34     {
35         Undefined   = 0,
36         Fresh       = 1,
37         Stale       = 2
38     }
39 
40     //
41     // These are valus that can be returned from validation methods.
42     // Most validation methods can only return a subset of below values.
43     //
44     // not flags!
45     internal enum CacheValidationStatus
46     {
47         DoNotUseCache               = 0,    //Cache is not used for this request and response is not cached.
48         Fail                        = 1,    //Fail this request (allows a protocol to generate own exception)
49         DoNotTakeFromCache          = 2,    //Don't used caches value for this request
50         RetryResponseFromCache      = 3,    //Retry cache lookup using changed cache key
51         RetryResponseFromServer     = 4,    //Retry this request as the result of invalid response received
52         ReturnCachedResponse        = 5,    //Return cached response to the application
53         CombineCachedAndServerResponse = 6, //Combine cached and live responses for this request
54         CacheResponse               = 7,    //Replace cache entry with received live response
55         UpdateResponseInformation   = 8,    //Update Metadata of cache entry using live response headers
56         RemoveFromCache             = 9,    //Remove cache entry referenced to by a cache key.
57         DoNotUpdateCache            = 10,   //Do nothing on cache update.
58         Continue                    = 11    //Proceed to the next protocol stage.
59     }
60 
61     /// <summary>
62     /// <para>
63     /// This class reserves a pattern for all WebRequest related cache validators.
64     /// All exposed protected methods are virtual.
65     /// If a derived class method does not call the base method implementation,
66     /// then the base class context may not be updated so it's recommended suppressing the base
67     /// methods for all subsequent calls on this class.
68     /// </para>
69     /// </summary>
70     internal abstract class RequestCacheValidator {
71 
72         internal WebRequest              _Request;
73         internal WebResponse             _Response;
74         internal Stream                  _CacheStream;
75 
76         private RequestCachePolicy      _Policy;
77         private Uri                     _Uri;
78         private String                  _CacheKey;
79         private RequestCacheEntry       _CacheEntry;
80         private int                     _ResponseCount;
81         private CacheValidationStatus   _ValidationStatus;
82         private CacheFreshnessStatus    _CacheFreshnessStatus;
83         private long                    _CacheStreamOffset;
84         private long                    _CacheStreamLength;
85 
86         private bool            _StrictCacheErrors;
87         private TimeSpan        _UnspecifiedMaxAge;
88 
89         /*-------------- public members -------------*/
90 
CreateValidator()91         internal abstract RequestCacheValidator CreateValidator();
92 
93         /*
94         // Consider removing.
95         protected RequestCacheValidator(): this(false, TimeSpan.FromDays(1))
96         {
97         }
98         */
99 
RequestCacheValidator(bool strictCacheErrors, TimeSpan unspecifiedMaxAge)100         protected RequestCacheValidator(bool strictCacheErrors, TimeSpan unspecifiedMaxAge)
101         {
102             _StrictCacheErrors    = strictCacheErrors;
103             _UnspecifiedMaxAge    = unspecifiedMaxAge;
104             _ValidationStatus     = CacheValidationStatus.DoNotUseCache;
105             _CacheFreshnessStatus = CacheFreshnessStatus.Undefined;
106         }
107 
108         //public
109         internal bool StrictCacheErrors
110         {
111             get {return _StrictCacheErrors;}
112         }
113         //
114         // This would help cache validation when the entry does
115         // not have any expiration mechanism defined.
116         //public
117         internal TimeSpan UnspecifiedMaxAge
118         {
119             get {return _UnspecifiedMaxAge;}
120         }
121 
122         /*------------- get-only protected properties -------------*/
123         protected internal Uri          Uri                             {get {return _Uri;}}
124         protected internal WebRequest   Request                         {get {return _Request; }}
125         protected internal WebResponse  Response                        {get {return _Response; }}
126         protected internal RequestCachePolicy Policy                    {get {return _Policy; }}
127         protected internal int          ResponseCount                   {get {return _ResponseCount;}}
128         protected internal CacheValidationStatus ValidationStatus       {get {return _ValidationStatus;}}
129         protected internal CacheFreshnessStatus  CacheFreshnessStatus   {get {return _CacheFreshnessStatus;}}
130         protected internal RequestCacheEntry     CacheEntry             {get {return _CacheEntry;}}
131 
132         /*------------- protected methods and settable protected properties ------------*/
133         protected internal Stream CacheStream
134         {
135             get {return _CacheStream;}
136             set {_CacheStream = value;}
137         }
138         //
139         protected internal long CacheStreamOffset
140         {
141             get {return _CacheStreamOffset;}
142             set {_CacheStreamOffset = value;}
143         }
144         //
145         protected internal long CacheStreamLength
146         {
147             get {return _CacheStreamLength;}
148             set {_CacheStreamLength = value;}
149         }
150         //
151         protected internal string CacheKey
152         {
153             get {return _CacheKey;}
154             /*
155             // Consider removing.
156             set
157             {
158                 // Security: Setting a cache key would allow reading an arbitrary cache location
159                 //new RequestCachePermission(RequestCacheActions.CacheReadWrite, value).Demand();
160                 _CacheKey = value;
161             }
162             */
163         }
164         //
165         /*-------------- protected virtual methods -------------*/
166         //
ValidateRequest()167         protected internal abstract CacheValidationStatus ValidateRequest();
168         //
ValidateFreshness()169         protected internal abstract CacheFreshnessStatus  ValidateFreshness();
170         //
ValidateCache()171         protected internal abstract CacheValidationStatus ValidateCache();
172         //
ValidateResponse()173         protected internal abstract CacheValidationStatus ValidateResponse();
174         //
RevalidateCache()175         protected internal abstract CacheValidationStatus RevalidateCache();
176         //
UpdateCache()177         protected internal abstract CacheValidationStatus UpdateCache();
178         //
FailRequest(WebExceptionStatus webStatus)179         protected internal virtual void FailRequest(WebExceptionStatus webStatus)
180         {
181             if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_failing_request_with_exception, webStatus.ToString()));
182             if (webStatus == WebExceptionStatus.CacheEntryNotFound)
183                 throw ExceptionHelper.CacheEntryNotFoundException;
184             else if (webStatus == WebExceptionStatus.RequestProhibitedByCachePolicy)
185                 throw ExceptionHelper.RequestProhibitedByCachePolicyException;
186 
187             throw new WebException(NetRes.GetWebStatusString("net_requestaborted", webStatus), webStatus);
188         }
189 
190         /*-------------- internal members -------------*/
191         //
FetchRequest(Uri uri, WebRequest request)192         internal void FetchRequest(Uri uri, WebRequest request)
193         {
194             _Request = request;
195             _Policy  = request.CachePolicy;
196             _Response = null;
197             _ResponseCount = 0;
198             _ValidationStatus     = CacheValidationStatus.DoNotUseCache;
199             _CacheFreshnessStatus = CacheFreshnessStatus.Undefined;
200             _CacheStream          = null;
201             _CacheStreamOffset    = 0L;
202             _CacheStreamLength    = 0L;
203 
204             if (!uri.Equals(_Uri))
205             {
206                 // it's changed from previous call
207                 _CacheKey = uri.GetParts(UriComponents.AbsoluteUri, UriFormat.Unescaped);
208             }
209             _Uri = uri;
210         }
211         //
FetchCacheEntry(RequestCacheEntry fetchEntry)212         internal void FetchCacheEntry(RequestCacheEntry fetchEntry)
213         {
214             _CacheEntry = fetchEntry;
215         }
216 
FetchResponse(WebResponse fetchResponse)217         internal void FetchResponse(WebResponse fetchResponse)
218         {
219             ++_ResponseCount;
220             _Response = fetchResponse;
221         }
222 
SetFreshnessStatus(CacheFreshnessStatus status)223         internal void SetFreshnessStatus(CacheFreshnessStatus status)
224         {
225             _CacheFreshnessStatus = status;
226         }
227 
SetValidationStatus(CacheValidationStatus status)228         internal void SetValidationStatus(CacheValidationStatus status)
229         {
230             _ValidationStatus = status;
231         }
232     }
233 
234 }
235