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
- WebPartConnectionsConfigureVerb.cs
- ItemsControl.cs
- XmlAttribute.cs
- TextRangeProviderWrapper.cs
- ByteStack.cs
- InfoCardRSAPKCS1KeyExchangeDeformatter.cs
- Accessible.cs
- MasterPage.cs
- HyperLinkColumn.cs
- Visual3D.cs
- DefaultMergeHelper.cs
- ValidatorCollection.cs
- MinMaxParagraphWidth.cs
- DSASignatureDeformatter.cs
- QueryOptionExpression.cs
- PixelFormat.cs
- SessionPageStatePersister.cs
- FilePrompt.cs
- PrintingPermission.cs
- DataGridViewTextBoxColumn.cs
- DataBoundControl.cs
- ExpressionConverter.cs
- RecipientInfo.cs
- OracleMonthSpan.cs
- IDispatchConstantAttribute.cs
- GraphicsContext.cs
- InstanceDataCollection.cs
- IBuiltInEvidence.cs
- DataSourceSelectArguments.cs
- RelationshipConverter.cs
- DependencyProperty.cs
- ModuleConfigurationInfo.cs
- ConvertTextFrag.cs
- XmlArrayItemAttribute.cs
- CustomAssemblyResolver.cs
- CodeBinaryOperatorExpression.cs
- Annotation.cs
- UniqueID.cs
- WorkflowServiceBuildProvider.cs
- Size3D.cs
- _Win32.cs
- RectangleGeometry.cs
- RadioButtonRenderer.cs
- PingReply.cs
- Win32Exception.cs
- SQLResource.cs
- JavaScriptSerializer.cs
- DescendentsWalkerBase.cs
- ScriptMethodAttribute.cs
- ToolboxService.cs
- ExpanderAutomationPeer.cs
- CodeArrayIndexerExpression.cs
- ApplicationException.cs
- PolicyChain.cs
- PagesSection.cs
- FilteredXmlReader.cs
- XmlSerializationWriter.cs
- codemethodreferenceexpression.cs
- OracleBoolean.cs
- NamespaceInfo.cs
- SqlMultiplexer.cs
- ControlsConfig.cs
- SecurityResources.cs
- SQLSingle.cs
- DispatchProxy.cs
- TypeInfo.cs
- URL.cs
- CacheSection.cs
- DynamicMethod.cs
- FileAuthorizationModule.cs
- UndoManager.cs
- Icon.cs
- TextEditorTyping.cs
- KnownBoxes.cs
- shaperfactoryquerycachekey.cs
- FormatConvertedBitmap.cs
- WindowsClientCredential.cs
- EntityDesignerDataSourceView.cs
- CommonXSendMessage.cs
- DesignerWebPartChrome.cs
- CacheHelper.cs
- FontSizeConverter.cs
- SymbolEqualComparer.cs
- RoleManagerEventArgs.cs
- ProofTokenCryptoHandle.cs
- Win32Exception.cs
- SqlDataAdapter.cs
- EntitySqlQueryState.cs
- listitem.cs
- _NtlmClient.cs
- Package.cs
- FilterException.cs
- MultipartIdentifier.cs
- DispatcherHooks.cs
- _Semaphore.cs
- RpcCryptoRequest.cs
- Exceptions.cs
- RealProxy.cs
- SafeLocalMemHandle.cs
- TagPrefixInfo.cs