//
        // Returns UpdateResponseInformation if passed response stream has to be replaced (cache is updated in some way)
        // Returns Fail if request is to fail
        // Any other return value should be ignored
        //
        internal CacheValidationStatus GetUpdateStatus (WebResponse response, Stream responseStream)
        {
            if (response == null)
                throw new ArgumentNullException("response");

            if (_ProtocolStatus == CacheValidationStatus.DoNotUseCache)
                return CacheValidationStatus.DoNotUseCache;

            try {
                if(Logging.On) Logging.Enter(Logging.RequestCache, this, "GetUpdateStatus", null);

                if (_Validator.Response == null)
                    _Validator.FetchResponse(response);

                if (_ProtocolStatus == CacheValidationStatus.RemoveFromCache)
                {
                    EnsureCacheRemoval(_Validator.CacheKey);
                    return _ProtocolStatus;
                }

                if (_ProtocolStatus != CacheValidationStatus.DoNotTakeFromCache &&
                    _ProtocolStatus != CacheValidationStatus.ReturnCachedResponse &&
                    _ProtocolStatus != CacheValidationStatus.CombineCachedAndServerResponse)
                {
                    if(Logging.On) Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_not_updated_based_on_cache_protocol_status, "GetUpdateStatus()", _ProtocolStatus.ToString()));
                    return _ProtocolStatus;
                }

                CheckUpdateOnResponse(responseStream);
            }
            catch (Exception e) {
                _ProtocolException = e;
                _ProtocolStatus = CacheValidationStatus.Fail;
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException) {
                    throw;
                }
                if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString())));
            }
            finally {
                if(Logging.On)Logging.Exit(Logging.RequestCache, this, "GetUpdateStatus", "result = " + _ProtocolStatus.ToString());
            }
            return _ProtocolStatus;
        }
        //
        internal CacheValidationStatus  GetRetrieveStatus (Uri cacheUri, WebRequest request)
        {

            if (cacheUri == null)
                throw new ArgumentNullException("cacheUri");

            if (request == null)
               throw new ArgumentNullException("request");

            if (!_CanTakeNewRequest || _ProtocolStatus == CacheValidationStatus.RetryResponseFromServer)
                return CacheValidationStatus.Continue;
            _CanTakeNewRequest = false;


            // Reset protocol state
            _ResponseStream       = null;
            _ResponseStreamLength = 0L;
            _ProtocolStatus       = CacheValidationStatus.Continue;
            _ProtocolException    = null;

            if(Logging.On) Logging.Enter(Logging.RequestCache, this, "GetRetrieveStatus", request);
            try {
                if (request.CachePolicy == null || request.CachePolicy.Level == RequestCacheLevel.BypassCache)
                {
                    _ProtocolStatus = CacheValidationStatus.DoNotUseCache;
                    return _ProtocolStatus;
                }

                if (_RequestCache == null || _Validator == null)
                {
                    _ProtocolStatus = CacheValidationStatus.DoNotUseCache;
                    return _ProtocolStatus;
                }

                _Validator.FetchRequest(cacheUri, request);

                switch(_ProtocolStatus = ValidateRequest())
                {
                case CacheValidationStatus.Continue:            // This is a green light for cache protocol
                    break;

                case CacheValidationStatus.DoNotTakeFromCache:  // no cache but response can be cached
                case CacheValidationStatus.DoNotUseCache:       // ignore cache entirely
                    break;

                case CacheValidationStatus.Fail:
                    _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateRequest"));
                    break;

                default:
                    _ProtocolStatus = CacheValidationStatus.Fail;
                    _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateRequest", _Validator.ValidationStatus.ToString()));
                    if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateRequest()", _Validator.ValidationStatus.ToString()));
                    break;
                }

                if (_ProtocolStatus != CacheValidationStatus.Continue)
                    return _ProtocolStatus;

                //
                // Proceed with validation
                //
                CheckRetrieveBeforeSubmit();
            }
            catch (Exception e) {
                _ProtocolException = e;
                _ProtocolStatus = CacheValidationStatus.Fail;
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                    throw;

                if(Logging.On) Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString())));
            }
            finally {
                if(Logging.On) Logging.Exit(Logging.RequestCache, this, "GetRetrieveStatus", "result = " + _ProtocolStatus.ToString());
            }
            return _ProtocolStatus;
        }
        //
        internal CacheValidationStatus  GetRetrieveStatus(Uri cacheUri, WebRequest request)
        {
            if (cacheUri == null)
            {
                throw new ArgumentNullException("cacheUri");
            }

            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (!_CanTakeNewRequest || _ProtocolStatus == CacheValidationStatus.RetryResponseFromServer)
            {
                return(CacheValidationStatus.Continue);
            }
            _CanTakeNewRequest = false;


            // Reset protocol state
            _ResponseStream       = null;
            _ResponseStreamLength = 0L;
            _ProtocolStatus       = CacheValidationStatus.Continue;
            _ProtocolException    = null;

            if (Logging.On)
            {
                Logging.Enter(Logging.RequestCache, this, "GetRetrieveStatus", request);
            }
            try {
                if (request.CachePolicy == null || request.CachePolicy.Level == RequestCacheLevel.BypassCache)
                {
                    _ProtocolStatus = CacheValidationStatus.DoNotUseCache;
                    return(_ProtocolStatus);
                }

                if (_RequestCache == null || _Validator == null)
                {
                    _ProtocolStatus = CacheValidationStatus.DoNotUseCache;
                    return(_ProtocolStatus);
                }

                _Validator.FetchRequest(cacheUri, request);

                switch (_ProtocolStatus = ValidateRequest())
                {
                case CacheValidationStatus.Continue:            // This is a green light for cache protocol
                    break;

                case CacheValidationStatus.DoNotTakeFromCache:  // no cache but response can be cached
                case CacheValidationStatus.DoNotUseCache:       // ignore cache entirely
                    break;

                case CacheValidationStatus.Fail:
                    _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_fail, "ValidateRequest"));
                    break;

                default:
                    _ProtocolStatus    = CacheValidationStatus.Fail;
                    _ProtocolException = new InvalidOperationException(SR.GetString(SR.net_cache_validator_result, "ValidateRequest", _Validator.ValidationStatus.ToString()));
                    if (Logging.On)
                    {
                        Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_unexpected_status, "ValidateRequest()", _Validator.ValidationStatus.ToString()));
                    }
                    break;
                }

                if (_ProtocolStatus != CacheValidationStatus.Continue)
                {
                    return(_ProtocolStatus);
                }

                //
                // Proceed with validation
                //
                CheckRetrieveBeforeSubmit();
            }
            catch (Exception e) {
                _ProtocolException = e;
                _ProtocolStatus    = CacheValidationStatus.Fail;
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                {
                    throw;
                }

                if (Logging.On)
                {
                    Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString())));
                }
            }
            finally {
                if (Logging.On)
                {
                    Logging.Exit(Logging.RequestCache, this, "GetRetrieveStatus", "result = " + _ProtocolStatus.ToString());
                }
            }
            return(_ProtocolStatus);
        }
        //
        private CacheValidationStatus ValidateResponse()
        {
            CacheValidationStatus result = _Validator.ValidateResponse();

            _Validator.SetValidationStatus(result);

            if (Logging.On)
            {
                Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_result, "ValidateResponse()", result.ToString()));
            }
            return(result);
        }
        //
        // Returns UpdateResponseInformation if passed response stream has to be replaced (cache is updated in some way)
        // Returns Fail if request is to fail
        // Any other return value should be ignored
        //
        internal CacheValidationStatus GetUpdateStatus(WebResponse response, Stream responseStream)
        {
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            if (_ProtocolStatus == CacheValidationStatus.DoNotUseCache)
            {
                return(CacheValidationStatus.DoNotUseCache);
            }

            try {
                if (Logging.On)
                {
                    Logging.Enter(Logging.RequestCache, this, "GetUpdateStatus", null);
                }

                if (_Validator.Response == null)
                {
                    _Validator.FetchResponse(response);
                }

                if (_ProtocolStatus == CacheValidationStatus.RemoveFromCache)
                {
                    EnsureCacheRemoval(_Validator.CacheKey);
                    return(_ProtocolStatus);
                }

                if (_ProtocolStatus != CacheValidationStatus.DoNotTakeFromCache &&
                    _ProtocolStatus != CacheValidationStatus.ReturnCachedResponse &&
                    _ProtocolStatus != CacheValidationStatus.CombineCachedAndServerResponse)
                {
                    if (Logging.On)
                    {
                        Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_not_updated_based_on_cache_protocol_status, "GetUpdateStatus()", _ProtocolStatus.ToString()));
                    }
                    return(_ProtocolStatus);
                }

                CheckUpdateOnResponse(responseStream);
            }
            catch (Exception e) {
                _ProtocolException = e;
                _ProtocolStatus    = CacheValidationStatus.Fail;
                if (e is ThreadAbortException || e is StackOverflowException || e is OutOfMemoryException)
                {
                    throw;
                }
                if (Logging.On)
                {
                    Logging.PrintError(Logging.RequestCache, SR.GetString(SR.net_log_cache_object_and_exception, "CacheProtocol#" + this.GetHashCode().ToString(NumberFormatInfo.InvariantInfo), (e is WebException? e.Message: e.ToString())));
                }
            }
            finally {
                if (Logging.On)
                {
                    Logging.Exit(Logging.RequestCache, this, "GetUpdateStatus", "result = " + _ProtocolStatus.ToString());
                }
            }
            return(_ProtocolStatus);
        }
        //
        // This optional method is only for protocols supporting a revalidation concept
        // For a retried request this method must be called again.
        //
        internal CacheValidationStatus GetRevalidateStatus(WebResponse response, Stream responseStream)
        {
            if (response == null)
            {
                throw new ArgumentNullException("response");
            }

            if (_ProtocolStatus == CacheValidationStatus.DoNotUseCache)
            {
                return(CacheValidationStatus.DoNotUseCache);
            }

            // If we returned cached response, switch the state to not call cache anymore.
            if (_ProtocolStatus == CacheValidationStatus.ReturnCachedResponse)
            {
                _ProtocolStatus = CacheValidationStatus.DoNotUseCache;
                return(_ProtocolStatus);
            }

            try {
                if (Logging.On)
                {
                    Logging.Enter(Logging.RequestCache, this, "GetRevalidateStatus", (_Validator == null? null: _Validator.Request));
                }

                _Validator.FetchResponse(response);

                if (_ProtocolStatus != CacheValidationStatus.Continue && _ProtocolStatus != CacheValidationStatus.RetryResponseFromServer)
                {
                    if (Logging.On)
                    {
                        Logging.PrintInfo(Logging.RequestCache, SR.GetString(SR.net_log_cache_revalidation_not_needed, "GetRevalidateStatus()"));
                    }
                    return(_ProtocolStatus);
                }
                CheckRetrieveOnResponse(responseStream);
            }
            finally {
                if (Logging.On)
                {
                    Logging.Exit(Logging.RequestCache, this, "GetRevalidateStatus", "result = " + _ProtocolStatus.ToString());
                }
            }
            return(_ProtocolStatus);
        }
        private CacheValidationStatus ValidateResponse()
        {
            CacheValidationStatus status = this._Validator.ValidateResponse();

            this._Validator.SetValidationStatus(status);
            if (Logging.On)
            {
                Logging.PrintInfo(Logging.RequestCache, SR.GetString("net_log_cache_result", new object[] { "ValidateResponse()", status.ToString() }));
            }
            return(status);
        }