Code:
/ DotNET / DotNET / 8.0 / untmp / whidbey / REDBITS / ndp / fx / src / Net / System / Net / Cache / FtpRequestCacheValidator.cs / 1 / FtpRequestCacheValidator.cs
/*++ Copyright (c) Microsoft Corporation Module Name: FtpRequestCacheValidator.cs Abstract: The class implements FTP Caching validators Author: Alexei Vopilov 3-Aug-2004 Revision History: --*/ namespace System.Net.Cache { using System; using System.Net; using System.IO; using System.Collections; using System.Text; using System.Collections.Specialized; using System.Globalization; using System.Threading; // The class represents an adavanced way for an application to control caching protocol internal class FtpRequestCacheValidator: HttpRequestCacheValidator { DateTime m_LastModified; bool m_HttpProxyMode; private bool HttpProxyMode {get{return m_HttpProxyMode;}} internal new RequestCachePolicy Policy {get {return ((RequestCacheValidator)this).Policy;}} // private void ZeroPrivateVars() { m_LastModified = DateTime.MinValue; m_HttpProxyMode = false; } //public internal override RequestCacheValidator CreateValidator() { return new FtpRequestCacheValidator(StrictCacheErrors, UnspecifiedMaxAge); } //public internal FtpRequestCacheValidator(bool strictCacheErrors, TimeSpan unspecifiedMaxAge): base(strictCacheErrors, unspecifiedMaxAge) { } // // This validation method is called first and before any Cache access is done. // Given the request instance the code has to decide whether the request is ever suitable for caching. // // Returns: // Continue = Proceed to the next protocol stage. // DoNotTakeFromCache = Don't used caches value for this request // DoNotUseCache = Cache is not used for this request and response is not cached. protected internal override CacheValidationStatus ValidateRequest() { // cleanup context after previous request ZeroPrivateVars(); if (Request is HttpWebRequest) { m_HttpProxyMode = true; if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_ftp_proxy_doesnt_support_partial)); return base.ValidateRequest(); } if (Policy.Level == RequestCacheLevel.BypassCache) return CacheValidationStatus.DoNotUseCache; string method = Request.Method.ToUpper(CultureInfo.InvariantCulture); if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_ftp_method, method)); switch (method) { case WebRequestMethods.Ftp.DownloadFile: RequestMethod = HttpMethod.Get; break; case WebRequestMethods.Ftp.UploadFile: RequestMethod = HttpMethod.Put;break; case WebRequestMethods.Ftp.AppendFile: RequestMethod = HttpMethod.Put;break; case WebRequestMethods.Ftp.Rename: RequestMethod = HttpMethod.Put;break; case WebRequestMethods.Ftp.DeleteFile: RequestMethod = HttpMethod.Delete;break; default: RequestMethod = HttpMethod.Other; break; } if ((RequestMethod != HttpMethod.Get || !((FtpWebRequest)Request).UseBinary) && Policy.Level == RequestCacheLevel.CacheOnly) { // Throw because the request must hit the wire and it's cache-only policy FailRequest(WebExceptionStatus.RequestProhibitedByCachePolicy); } if (method != WebRequestMethods.Ftp.DownloadFile) return CacheValidationStatus.DoNotTakeFromCache; if (!((FtpWebRequest)Request).UseBinary) { if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_ftp_supports_bin_only)); return CacheValidationStatus.DoNotUseCache; } if (Policy.Level >= RequestCacheLevel.Reload) return CacheValidationStatus.DoNotTakeFromCache; return CacheValidationStatus.Continue; } // // This validation method is called after caching protocol has retrieved the metadata of a cached entry. // Given the cached entry context, the request instance and the effective caching policy, // the handler has to decide whether a cached item can be considered as fresh. protected internal override CacheFreshnessStatus ValidateFreshness() { if (HttpProxyMode) { if (CacheStream != Stream.Null) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_replacing_entry_with_HTTP_200)); // HTTP validator cannot parse FTP status code and other metadata if (CacheEntry.EntryMetadata == null) CacheEntry.EntryMetadata = new StringCollection(); CacheEntry.EntryMetadata.Clear(); CacheEntry.EntryMetadata.Add("HTTP/1.1 200 OK"); } return base.ValidateFreshness(); } DateTime nowDate = DateTime.UtcNow; if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_now_time, nowDate.ToString("r", CultureInfo.InvariantCulture))); // If absolute Expires can be recovered if (CacheEntry.ExpiresUtc != DateTime.MinValue) { //Take absolute Expires value if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_max_age_absolute, CacheEntry.ExpiresUtc.ToString("r", CultureInfo.InvariantCulture))); if (CacheEntry.ExpiresUtc < nowDate) { return CacheFreshnessStatus.Stale; } return CacheFreshnessStatus.Fresh; } TimeSpan age = TimeSpan.MaxValue; if(CacheEntry.LastSynchronizedUtc != DateTime.MinValue) { age = nowDate - CacheEntry.LastSynchronizedUtc; if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_age1, ((int)age.TotalSeconds).ToString(NumberFormatInfo.InvariantInfo), CacheEntry.LastSynchronizedUtc.ToString("r", CultureInfo.InvariantCulture))); } // // Heruistic expiration // if (CacheEntry.LastModifiedUtc != DateTime.MinValue) { TimeSpan span = (nowDate - CacheEntry.LastModifiedUtc); int maxAgeSeconds = (int)(span.TotalSeconds/10); if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_max_age_use_10_percent, maxAgeSeconds.ToString(NumberFormatInfo.InvariantInfo), CacheEntry.LastModifiedUtc.ToString("r", CultureInfo.InvariantCulture))); if (age.TotalSeconds < maxAgeSeconds) { return CacheFreshnessStatus.Fresh; } return CacheFreshnessStatus.Stale; } // Else we can only rely on UnspecifiedMaxAge hint if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_no_max_age_use_default, ((int)(UnspecifiedMaxAge.TotalSeconds)).ToString(NumberFormatInfo.InvariantInfo))); if (UnspecifiedMaxAge >= age) { return CacheFreshnessStatus.Fresh; } return CacheFreshnessStatus.Stale; //return OnValidateFreshness(this); } // This method may add headers under the "Warning" header name protected internal override CacheValidationStatus ValidateCache() { if (HttpProxyMode) return base.ValidateCache(); if (Policy.Level >= RequestCacheLevel.Reload) { // For those policies cache is never returned GlobalLog.Assert("OnValidateCache()", "This validator should not be called for policy = " + Policy.ToString()); if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_validator_invalid_for_policy, Policy.ToString())); return CacheValidationStatus.DoNotTakeFromCache; } // First check is do we have a cached entry at all? if (CacheStream == Stream.Null || CacheEntry.IsPartialEntry) { if (Policy.Level == RequestCacheLevel.CacheOnly) { // Throw because entry was not found and it's cache-only policy FailRequest(WebExceptionStatus.CacheEntryNotFound); } if (CacheStream == Stream.Null) { return CacheValidationStatus.DoNotTakeFromCache; } // Otherwise it's a partial entry and we can go on the wire } CacheStreamOffset = 0L; CacheStreamLength = CacheEntry.StreamSize; // // Before request submission validation // if (Policy.Level == RequestCacheLevel.Revalidate || CacheEntry.IsPartialEntry) { return TryConditionalRequest(); } long contentOffset = Request is FtpWebRequest ? ((FtpWebRequest)Request).ContentOffset: 0L; if (CacheFreshnessStatus == CacheFreshnessStatus.Fresh || Policy.Level == RequestCacheLevel.CacheOnly || Policy.Level == RequestCacheLevel.CacheIfAvailable) { if (contentOffset != 0) { if (contentOffset >= CacheStreamLength) { if (Policy.Level == RequestCacheLevel.CacheOnly) { // Throw because request is outside of cached size and it's cache-only policy FailRequest(WebExceptionStatus.CacheEntryNotFound); } return CacheValidationStatus.DoNotTakeFromCache; } CacheStreamOffset = contentOffset; } return CacheValidationStatus.ReturnCachedResponse; } return CacheValidationStatus.DoNotTakeFromCache; } // // This is (optionally) called after receiveing a live response // protected internal override CacheValidationStatus RevalidateCache() { if (HttpProxyMode) return base.RevalidateCache(); if (Policy.Level >= RequestCacheLevel.Reload) { // For those policies cache is never returned GlobalLog.Assert("RevalidateCache()", "This validator should not be called for policy = " + Policy.ToString()); if(Logging.On)Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_validator_invalid_for_policy, Policy.ToString())); return CacheValidationStatus.DoNotTakeFromCache; } // First check is do we still hold on a cached entry? if (CacheStream == Stream.Null) { return CacheValidationStatus.DoNotTakeFromCache; } // // This is a second+ time validation after receiving at least one response // CacheValidationStatus result = CacheValidationStatus.DoNotTakeFromCache; FtpWebResponse resp = Response as FtpWebResponse; if (resp == null) { // This will result to an application error return CacheValidationStatus.DoNotTakeFromCache; } if (resp.StatusCode == FtpStatusCode.FileStatus) { if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_response_last_modified, resp.LastModified.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture), resp.ContentLength)); if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_cache_last_modified, CacheEntry.LastModifiedUtc.ToString("r", CultureInfo.InvariantCulture), CacheEntry.StreamSize)); if (CacheStreamOffset != 0L && CacheEntry.IsPartialEntry) { //should never happen if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_partial_and_non_zero_content_offset, CacheStreamOffset.ToString(CultureInfo.InvariantCulture))); result = CacheValidationStatus.DoNotTakeFromCache; } if (resp.LastModified.ToUniversalTime() == CacheEntry.LastModifiedUtc) { if (CacheEntry.IsPartialEntry) { // A caller will need to use Validator.CacheEntry.StreamSize to figure out what the restart point is if (resp.ContentLength > 0) this.CacheStreamLength = resp.ContentLength; else this.CacheStreamLength = -1; result = CacheValidationStatus.CombineCachedAndServerResponse; } else if (resp.ContentLength == CacheEntry.StreamSize) { result = CacheValidationStatus.ReturnCachedResponse; } else result = CacheValidationStatus.DoNotTakeFromCache; } else result = CacheValidationStatus.DoNotTakeFromCache; } else { result = CacheValidationStatus.DoNotTakeFromCache; } return result; } // // This validation method is responsible to answer whether the live response is sufficient to make // the final decision for caching protocol. // This is useful in case of possible failure or inconsistent results received from // the remote cache. // /// Invalid response from this method means the request was internally modified and should be retried protected internal override CacheValidationStatus ValidateResponse() { if (HttpProxyMode) return base.ValidateResponse(); if (Policy.Level != RequestCacheLevel.Default && Policy.Level != RequestCacheLevel.Revalidate) { // Those policy levels do not modify requests if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_response_valid_based_on_policy, Policy.ToString())); return CacheValidationStatus.Continue; } FtpWebResponse resp = Response as FtpWebResponse; if (resp == null) { if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_null_response_failure)); return CacheValidationStatus.Continue; } if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_ftp_response_status, ((int)resp.StatusCode).ToString(CultureInfo.InvariantCulture), resp.StatusCode.ToString())); // If there was a retry already, it should go with cache disabled so by default we won't retry it again if (ResponseCount > 1) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_resp_valid_based_on_retry, ResponseCount)); return CacheValidationStatus.Continue; } if (resp.StatusCode != FtpStatusCode.OpeningData && resp.StatusCode != FtpStatusCode.FileStatus) { return CacheValidationStatus.RetryResponseFromServer; } return CacheValidationStatus.Continue; } ///This action handler is responsible for making final decision on whether // a received response can be cached. // Invalid result from this method means the response must not be cached protected internal override CacheValidationStatus UpdateCache() { if (HttpProxyMode) return base.UpdateCache(); // An combined cace+wire response is not supported if user has specified a restart offset. CacheStreamOffset = 0L; if (RequestMethod == HttpMethod.Other) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_not_updated_based_on_policy, Request.Method)); return CacheValidationStatus.DoNotUpdateCache; } if (ValidationStatus == CacheValidationStatus.RemoveFromCache) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_removed_existing_invalid_entry)); return CacheValidationStatus.RemoveFromCache; } if (Policy.Level == RequestCacheLevel.CacheOnly) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_not_updated_based_on_policy, Policy.ToString())); return CacheValidationStatus.DoNotUpdateCache; } FtpWebResponse resp = Response as FtpWebResponse; if (resp == null) { if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_not_updated_because_no_response)); return CacheValidationStatus.DoNotUpdateCache; } // // Check on cache removal based on the request method // if (RequestMethod == HttpMethod.Delete || RequestMethod == HttpMethod.Put) { if (RequestMethod == HttpMethod.Delete || resp.StatusCode == FtpStatusCode.OpeningData || resp.StatusCode == FtpStatusCode.DataAlreadyOpen || resp.StatusCode == FtpStatusCode.FileActionOK || resp.StatusCode == FtpStatusCode.ClosingData) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_removed_existing_based_on_method, Request.Method)); return CacheValidationStatus.RemoveFromCache; } if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_existing_not_removed_because_unexpected_response_status, (int)resp.StatusCode, resp.StatusCode.ToString())); return CacheValidationStatus.DoNotUpdateCache; } if (Policy.Level == RequestCacheLevel.NoCacheNoStore) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_removed_existing_based_on_policy, Policy.ToString())); return CacheValidationStatus.RemoveFromCache; } if (ValidationStatus == CacheValidationStatus.ReturnCachedResponse) { // have a response still returning from cache means just revalidated the entry. return UpdateCacheEntryOnRevalidate(); } if (resp.StatusCode != FtpStatusCode.OpeningData && resp.StatusCode != FtpStatusCode.DataAlreadyOpen && resp.StatusCode != FtpStatusCode.ClosingData) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_not_updated_based_on_ftp_response_status, FtpStatusCode.OpeningData.ToString() + "|" + FtpStatusCode.DataAlreadyOpen.ToString() + "|" + FtpStatusCode.ClosingData.ToString(), resp.StatusCode.ToString())); return CacheValidationStatus.DoNotUpdateCache; } // Check on no-update or cache removal if restart action has invalidated existing cache entry if (((FtpWebRequest)Request).ContentOffset != 0L) { if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_update_not_supported_for_ftp_restart, ((FtpWebRequest)Request).ContentOffset.ToString(CultureInfo.InvariantCulture))); if (CacheEntry.LastModifiedUtc != DateTime.MinValue && resp.LastModified.ToUniversalTime() != CacheEntry.LastModifiedUtc) { if(Logging.On)Logging.PrintWarning(Logging.RequestCache, SR.GetString(SR.net_log_cache_removed_entry_because_ftp_restart_response_changed, CacheEntry.LastModifiedUtc.ToString("r", CultureInfo.InvariantCulture), resp.LastModified.ToUniversalTime().ToString("r", CultureInfo.InvariantCulture))); return CacheValidationStatus.RemoveFromCache; } return CacheValidationStatus.DoNotUpdateCache; } return UpdateCacheEntryOnStore(); } // // // private CacheValidationStatus UpdateCacheEntryOnStore() { CacheEntry.EntryMetadata = null; CacheEntry.SystemMetadata = null; FtpWebResponse resp = Response as FtpWebResponse; if (resp.LastModified != DateTime.MinValue) { CacheEntry.LastModifiedUtc = resp.LastModified.ToUniversalTime(); } ResponseEntityLength = Response.ContentLength; CacheEntry.StreamSize = ResponseEntityLength; //This is passed down to cache on what size to expect CacheEntry.LastSynchronizedUtc = DateTime.UtcNow; return CacheValidationStatus.CacheResponse; } // // private CacheValidationStatus UpdateCacheEntryOnRevalidate() { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_last_synchronized, CacheEntry.LastSynchronizedUtc.ToString("r", CultureInfo.InvariantCulture))); DateTime nowUtc = DateTime.UtcNow; if (CacheEntry.LastSynchronizedUtc + TimeSpan.FromMinutes(1) >= nowUtc) { if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_suppress_update_because_synched_last_minute)); return CacheValidationStatus.DoNotUpdateCache; } CacheEntry.EntryMetadata = null; CacheEntry.SystemMetadata = null; CacheEntry.LastSynchronizedUtc = nowUtc; if(Logging.On)Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_updating_last_synchronized, CacheEntry.LastSynchronizedUtc.ToString("r", CultureInfo.InvariantCulture))); return CacheValidationStatus.UpdateResponseInformation; } // private CacheValidationStatus TryConditionalRequest() { FtpWebRequest request = Request as FtpWebRequest; if (request == null || !request.UseBinary) return CacheValidationStatus.DoNotTakeFromCache; if (request.ContentOffset != 0L) { if (CacheEntry.IsPartialEntry || request.ContentOffset >= CacheStreamLength) return CacheValidationStatus.DoNotTakeFromCache; CacheStreamOffset = request.ContentOffset; } return CacheValidationStatus.Continue; } } }
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- DesignColumn.cs
- CacheForPrimitiveTypes.cs
- SByteStorage.cs
- PeerEndPoint.cs
- XhtmlStyleClass.cs
- DateTimeFormatInfoScanner.cs
- UpdatableGenericsFeature.cs
- ListViewInsertedEventArgs.cs
- WebBrowserContainer.cs
- IpcChannelHelper.cs
- KeyValueSerializer.cs
- WsatStrings.cs
- ColumnHeaderConverter.cs
- JoinElimination.cs
- TableCellCollection.cs
- IdentityValidationException.cs
- PTUtility.cs
- ProfileEventArgs.cs
- GorillaCodec.cs
- Triplet.cs
- GB18030Encoding.cs
- ValidationHelper.cs
- ComponentResourceKey.cs
- FormViewRow.cs
- DataProtection.cs
- RepeaterItemCollection.cs
- ThumbAutomationPeer.cs
- Transform3D.cs
- ListDictionary.cs
- TextTreePropertyUndoUnit.cs
- KeysConverter.cs
- DataPagerField.cs
- HtmlMeta.cs
- AutoGeneratedField.cs
- WebBaseEventKeyComparer.cs
- DataGridViewHeaderCell.cs
- StylusCaptureWithinProperty.cs
- List.cs
- SqlBulkCopy.cs
- ViewStateException.cs
- Section.cs
- RelationshipSet.cs
- ThumbButtonInfo.cs
- SqlDataSourceFilteringEventArgs.cs
- ResourcePermissionBaseEntry.cs
- cookieexception.cs
- BrowserTree.cs
- ScrollProviderWrapper.cs
- SelectedDatesCollection.cs
- ConfigurationProperty.cs
- ThemeDirectoryCompiler.cs
- TextEditorParagraphs.cs
- TableCell.cs
- XmlNamespaceManager.cs
- VirtualPathUtility.cs
- WorkflowElementDialogWindow.xaml.cs
- QuadraticBezierSegment.cs
- BitmapEffectInput.cs
- ToolboxItem.cs
- FtpWebRequest.cs
- HttpPostProtocolReflector.cs
- ItemsChangedEventArgs.cs
- BrowserCapabilitiesCompiler.cs
- DrawingGroup.cs
- NameValuePair.cs
- TextElementEnumerator.cs
- EndpointDesigner.cs
- FontStretch.cs
- ActionMessageFilterTable.cs
- PrintPreviewGraphics.cs
- SrgsGrammarCompiler.cs
- HyperLink.cs
- RegexCode.cs
- BitmapEffectRenderDataResource.cs
- DictationGrammar.cs
- QueryAsyncResult.cs
- StreamAsIStream.cs
- Symbol.cs
- Control.cs
- NumberFormatter.cs
- HostingEnvironmentWrapper.cs
- UidPropertyAttribute.cs
- TableParaClient.cs
- SqlDataSourceStatusEventArgs.cs
- CompositeControl.cs
- TextureBrush.cs
- WebPartZoneBase.cs
- HostedController.cs
- ButtonColumn.cs
- DesignerCategoryAttribute.cs
- TempFiles.cs
- StoreItemCollection.Loader.cs
- XmlSchemaAny.cs
- XmlReader.cs
- SqlWebEventProvider.cs
- ListItemCollection.cs
- PropertyItemInternal.cs
- Size3DValueSerializer.cs
- XmlMembersMapping.cs
- DodSequenceMerge.cs