com.crashlytics.tools.android_2.1.0

e.before(entryDate);
  }
}

/* Location:
 * Qualified Name:     org.apache.http.impl.client.cache.CachingExec
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.http.impl.client.cache;

import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpHost;
import org.apache.http.ProtocolException;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.methods.HttpRequestWrapper;
import org.apache.http.protocol.HttpContext;

class CachingHttpClient$AsynchronousValidationRequest
  implements Runnable
{
  private final CachingHttpClient.AsynchronousValidator parent;
  private final CachingHttpClient cachingClient;
  private final HttpHost target;
  private final HttpRequestWrapper request;
  private final HttpContext context;
  private final HttpCacheEntry cacheEntry;
  private final String identifier;
  private final Log log = LogFactory.getLog(getClass());
  
  CachingHttpClient$AsynchronousValidationRequest(CachingHttpClient.AsynchronousValidator parent, CachingHttpClient cachingClient, HttpHost target, HttpRequestWrapper request, HttpContext context, HttpCacheEntry cacheEntry, String identifier)
  {
    this.parent = parent;
    this.cachingClient = cachingClient;
    this.target = target;
    this.request = request;
    this.context = context;
    this.cacheEntry = cacheEntry;
    this.identifier = identifier;
  }
  
  public void run()
  {
    try
    {
      cachingClient.revalidateCacheEntry(target, request, context, cacheEntry);
    }
    catch (IOException ioe)
    {
      log.debug("Asynchronous revalidation failed due to exception: " + ioe);
    }
    catch (ProtocolException pe)
    {
      log.error("ProtocolException thrown during asynchronous revalidation: " + pe);
    }
    finally
    {
      parent.markComplete(identifier);
    }
  }
  
  String getIdentifier()
  {
    return identifier;
  }
}

/* Location:
 * Qualified Name:     org.apache.http.impl.client.cache.CachingHttpClient.AsynchronousValidationRequest
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.http.impl.client.cache;

import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpHost;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.methods.HttpRequestWrapper;
import org.apache.http.protocol.HttpContext;

class CachingHttpClient$AsynchronousValidator
{
  private final CachingHttpClient cachingClient;
  private final ExecutorService executor;
  private final Set<String> queued;
  private final CacheKeyGenerator cacheKeyGenerator;
  private final Log log = LogFactory.getLog(getClass());
  
  public CachingHttpClient$AsynchronousValidator(CachingHttpClient cachingClient, CacheConfig config)
  {
    this(cachingClient, new ThreadPoolExecutor(config.getAsynchronousWorkersCore(), config.getAsynchronousWorkersMax(), config.getAsynchronousWorkerIdleLifetimeSecs(), TimeUnit.SECONDS, new ArrayBlockingQueue(config.getRevalidationQueueSize())));
  }
  
  CachingHttpClient$AsynchronousValidator(CachingHttpClient cachingClient, ExecutorService executor)
  {
    this.cachingClient = cachingClient;
    this.executor = executor;
    queued = new HashSet();
    cacheKeyGenerator = new CacheKeyGenerator();
  }
  
  public synchronized void revalidateCacheEntry(HttpHost target, HttpRequestWrapper request, HttpContext context, HttpCacheEntry entry)
  {
    String uri = cacheKeyGenerator.getVariantURI(target, request, entry);
    if (!queued.contains(uri))
    {
      CachingHttpClient.AsynchronousValidationRequest revalidationRequest = new CachingHttpClient.AsynchronousValidationRequest(this, cachingClient, target, request, context, entry, uri);
      try
      {
        executor.execute(revalidationRequest);
        queued.add(uri);
      }
      catch (RejectedExecutionException ree)
      {
        log.debug("Revalidation for [" + uri + "] not scheduled: " + ree);
      }
    }
  }
  
  synchronized void markComplete(String identifier)
  {
    queued.remove(identifier);
  }
  
  Set<String> getScheduledIdentifiers()
  {
    return Collections.unmodifiableSet(queued);
  }
  
  ExecutorService getExecutor()
  {
    return executor;
  }
}

/* Location:
 * Qualified Name:     org.apache.http.impl.client.cache.CachingHttpClient.AsynchronousValidator
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.http.impl.client.cache;

import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.URI;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpMessage;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.ProtocolException;
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.apache.http.annotation.ThreadSafe;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.cache.CacheResponseStatus;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheStorage;
import org.apache.http.client.cache.ResourceFactory;
import org.apache.http.client.methods.HttpRequestWrapper;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.cookie.DateParseException;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.Args;
import org.apache.http.util.EntityUtils;
import org.apache.http.util.VersionInfo;

@Deprecated
@ThreadSafe
public class CachingHttpClient
  implements HttpClient
{
  public static final String CACHE_RESPONSE_STATUS = "http.cache.response.status";
  private static final boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false;
  private final AtomicLong cacheHits = new AtomicLong();
  private final AtomicLong cacheMisses = new AtomicLong();
  private final AtomicLong cacheUpdates = new AtomicLong();
  private final Map<ProtocolVersion, String> viaHeaders = new HashMap(4);
  private final HttpClient backend;
  private final HttpCache responseCache;
  private final CacheValidityPolicy validityPolicy;
  private final ResponseCachingPolicy responseCachingPolicy;
  private final CachedHttpResponseGenerator responseGenerator;
  private final CacheableRequestPolicy cacheableRequestPolicy;
  private final CachedResponseSuitabilityChecker suitabilityChecker;
  private final ConditionalRequestBuilder conditionalRequestBuilder;
  private final long maxObjectSizeBytes;
  private final boolean sharedCache;
  private final ResponseProtocolCompliance responseCompliance;
  private final RequestProtocolCompliance requestCompliance;
  private final AsynchronousValidator asynchRevalidator;
  private final Log log = LogFactory.getLog(getClass());
  
  CachingHttpClient(HttpClient client, HttpCache cache, CacheConfig config)
  {
    Args.notNull(client, "HttpClient");
    Args.notNull(cache, "HttpCache");
    Args.notNull(config, "CacheConfig");
    maxObjectSizeBytes = config.getMaxObjectSize();
    sharedCache = config.isSharedCache();
    backend = client;
    responseCache = cache;
    validityPolicy = new CacheValidityPolicy();
    responseCachingPolicy = new ResponseCachingPolicy(maxObjectSizeBytes, sharedCache, config.isNeverCacheHTTP10ResponsesWithQuery(), config.is303CachingEnabled());
    
    responseGenerator = new CachedHttpResponseGenerator(validityPolicy);
    cacheableRequestPolicy = new CacheableRequestPolicy();
    suitabilityChecker = new CachedResponseSuitabilityChecker(validityPolicy, config);
    conditionalRequestBuilder = new ConditionalRequestBuilder();
    
    responseCompliance = new ResponseProtocolCompliance();
    requestCompliance = new RequestProtocolCompliance(config.isWeakETagOnPutDeleteAllowed());
    
    asynchRevalidator = makeAsynchronousValidator(config);
  }
  
  public CachingHttpClient()
  {
    this(new DefaultHttpClient(), new BasicHttpCache(), new CacheConfig());
  }
  
  public CachingHttpClient(CacheConfig config)
  {
    this(new DefaultHttpClient(), new BasicHttpCache(config), config);
  }
  
  public CachingHttpClient(HttpClient client)
  {
    this(client, new BasicHttpCache(), new CacheConfig());
  }
  
  public CachingHttpClient(HttpClient client, CacheConfig config)
  {
    this(client, new BasicHttpCache(config), config);
  }
  
  public CachingHttpClient(HttpClient client, ResourceFactory resourceFactory, HttpCacheStorage storage, CacheConfig config)
  {
    this(client, new BasicHttpCache(resourceFactory, storage, config), config);
  }
  
  public CachingHttpClient(HttpClient client, HttpCacheStorage storage, CacheConfig config)
  {
    this(client, new BasicHttpCache(new HeapResourceFactory(), storage, config), config);
  }
  
  CachingHttpClient(HttpClient backend, CacheValidityPolicy validityPolicy, ResponseCachingPolicy responseCachingPolicy, HttpCache responseCache, CachedHttpResponseGenerator responseGenerator, CacheableRequestPolicy cacheableRequestPolicy, CachedResponseSuitabilityChecker suitabilityChecker, ConditionalRequestBuilder conditionalRequestBuilder, ResponseProtocolCompliance responseCompliance, RequestProtocolCompliance requestCompliance)
  {
    CacheConfig config = new CacheConfig();
    maxObjectSizeBytes = config.getMaxObjectSize();
    sharedCache = config.isSharedCache();
    this.backend = backend;
    this.validityPolicy = validityPolicy;
    this.responseCachingPolicy = responseCachingPolicy;
    this.responseCache = responseCache;
    this.responseGenerator = responseGenerator;
    this.cacheableRequestPolicy = cacheableRequestPolicy;
    this.suitabilityChecker = suitabilityChecker;
    this.conditionalRequestBuilder = conditionalRequestBuilder;
    this.responseCompliance = responseCompliance;
    this.requestCompliance = requestCompliance;
    asynchRevalidator = makeAsynchronousValidator(config);
  }
  
  private AsynchronousValidator makeAsynchronousValidator(CacheConfig config)
  {
    if (config.getAsynchronousWorkersMax() > 0) {
      return new AsynchronousValidator(this, config);
    }
    return null;
  }
  
  public long getCacheHits()
  {
    return cacheHits.get();
  }
  
  public long getCacheMisses()
  {
    return cacheMisses.get();
  }
  
  public long getCacheUpdates()
  {
    return cacheUpdates.get();
  }
  
  public HttpResponse execute(HttpHost target, HttpRequest request)
    throws IOException
  {
    HttpContext defaultContext = null;
    return execute(target, request, defaultContext);
  }
  
  public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler)
    throws IOException
  {
    return (T)execute(target, request, responseHandler, null);
  }
  
  public <T> T execute(HttpHost target, HttpRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
    throws IOException
  {
    HttpResponse resp = execute(target, request, context);
    return (T)handleAndConsume(responseHandler, resp);
  }
  
  public HttpResponse execute(HttpUriRequest request)
    throws IOException
  {
    HttpContext context = null;
    return execute(request, context);
  }
  
  public HttpResponse execute(HttpUriRequest request, HttpContext context)
    throws IOException
  {
    URI uri = request.getURI();
    HttpHost httpHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
    return execute(httpHost, request, context);
  }
  
  public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler)
    throws IOException
  {
    return (T)execute(request, responseHandler, null);
  }
  
  public <T> T execute(HttpUriRequest request, ResponseHandler<? extends T> responseHandler, HttpContext context)
    throws IOException
  {
    HttpResponse resp = execute(request, context);
    return (T)handleAndConsume(responseHandler, resp);
  }
  
  private <T> T handleAndConsume(ResponseHandler<? extends T> responseHandler, HttpResponse response)
    throws Error, IOException
  {
    T result;
    try
    {
      result = responseHandler.handleResponse(response);
    }
    catch (Exception t)
    {
      HttpEntity entity = response.getEntity();
      try
      {
        EntityUtils.consume(entity);
      }
      catch (Exception t2)
      {
        log.warn("Error consuming content after an exception.", t2);
      }
      if ((t instanceof RuntimeException)) {
        throw ((RuntimeException)t);
      }
      if ((t instanceof IOException)) {
        throw ((IOException)t);
      }
      throw new UndeclaredThrowableException(t);
    }
    HttpEntity entity = response.getEntity();
    EntityUtils.consume(entity);
    return result;
  }
  
  public ClientConnectionManager getConnectionManager()
  {
    return backend.getConnectionManager();
  }
  
  public HttpParams getParams()
  {
    return backend.getParams();
  }
  
  public HttpResponse execute(HttpHost target, HttpRequest originalRequest, HttpContext context)
    throws IOException
  {
    HttpRequestWrapper request;
    HttpRequestWrapper request;
    if ((originalRequest instanceof HttpRequestWrapper)) {
      request = (HttpRequestWrapper)originalRequest;
    } else {
      request = HttpRequestWrapper.wrap(originalRequest);
    }
    String via = generateViaHeader(originalRequest);
    
    setResponseStatus(context, CacheResponseStatus.CACHE_MISS);
    if (clientRequestsOurOptions(request))
    {
      setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
      return new OptionsHttp11Response();
    }
    HttpResponse fatalErrorResponse = getFatallyNoncompliantResponse(request, context);
    if (fatalErrorResponse != null) {
      return fatalErrorResponse;
    }
    requestCompliance.makeRequestCompliant(request);
    request.addHeader("Via", via);
    
    flushEntriesInvalidatedByRequest(target, request);
    if (!cacheableRequestPolicy.isServableFromCache(request))
    {
      log.debug("Request is not servable from cache");
      return callBackend(target, request, context);
    }
    HttpCacheEntry entry = satisfyFromCache(target, request);
    if (entry == null)
    {
      log.debug("Cache miss");
      return handleCacheMiss(target, request, context);
    }
    return handleCacheHit(target, request, context, entry);
  }
  
  private HttpResponse handleCacheHit(HttpHost target, HttpRequestWrapper request, HttpContext context, HttpCacheEntry entry)
    throws ClientProtocolException, IOException
  {
    recordCacheHit(target, request);
    HttpResponse out = null;
    Date now = getCurrentDate();
    if (suitabilityChecker.canCachedResponseBeUsed(target, request, entry, now))
    {
      log.debug("Cache hit");
      out = generateCachedResponse(request, context, entry, now);
    }
    else if (!mayCallBackend(request))
    {
      log.debug("Cache entry not suitable but only-if-cached requested");
      out = generateGatewayTimeout(context);
    }
    else
    {
      log.debug("Revalidating cache entry");
      return revalidateCacheEntry(target, request, context, entry, now);
    }
    if (context != null)
    {
      context.setAttribute("http.target_host", target);
      context.setAttribute("http.request", request);
      context.setAttribute("http.response", out);
      context.setAttribute("http.request_sent", Boolean.TRUE);
    }
    return out;
  }
  
  private HttpResponse revalidateCacheEntry(HttpHost target, HttpRequestWrapper request, HttpContext context, HttpCacheEntry entry, Date now)
    throws ClientProtocolException
  {
    try
    {
      if ((asynchRevalidator != null) && (!staleResponseNotAllowed(request, entry, now)) && (validityPolicy.mayReturnStaleWhileRevalidating(entry, now)))
      {
        log.trace("Serving stale with asynchronous revalidation");
        HttpResponse resp = generateCachedResponse(request, context, entry, now);
        
        asynchRevalidator.revalidateCacheEntry(target, request, context, entry);
        
        return resp;
      }
      return revalidateCacheEntry(target, request, context, entry);
    }
    catch (IOException ioex)
    {
      return handleRevalidationFailure(request, context, entry, now);
    }
    catch (ProtocolException e)
    {
      throw new ClientProtocolException(e);
    }
  }
  
  private HttpResponse handleCacheMiss(HttpHost target, HttpRequestWrapper request, HttpContext context)
    throws IOException
  {
    recordCacheMiss(target, request);
    if (!mayCallBackend(request)) {
      return new BasicHttpResponse(HttpVersion.HTTP_1_1, 504, "Gateway Timeout");
    }
    Map<String, Variant> variants = getExistingCacheVariants(target, request);
    if ((variants != null) && (variants.size() > 0)) {
      return negotiateResponseFromVariants(target, request, context, variants);
    }
    return callBackend(target, request, context);
  }
  
  private HttpCacheEntry satisfyFromCache(HttpHost target, HttpRequestWrapper request)
  {
    HttpCacheEntry entry = null;
    try
    {
      entry = responseCache.getCacheEntry(target, request);
    }
    catch (IOException ioe)
    {
      log.warn("Unable to retrieve entries from cache", ioe);
    }
    return entry;
  }
  
  private HttpResponse getFatallyNoncompliantResponse(HttpRequestWrapper request, HttpContext context)
  {
    HttpResponse fatalErrorResponse = null;
    List<RequestProtocolError> fatalError = requestCompliance.requestIsFatallyNonCompliant(request);
    for (RequestProtocolError error : fatalError)
    {
      setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
      fatalErrorResponse = requestCompliance.getErrorForRequest(error);
    }
    return fatalErrorResponse;
  }
  
  private Map<String, Variant> getExistingCacheVariants(HttpHost target, HttpRequestWrapper request)
  {
    Map<String, Variant> variants = null;
    try
    {
      variants = responseCache.getVariantCacheEntriesWithEtags(target, request);
    }
    catch (IOException ioe)
    {
      log.warn("Unable to retrieve variant entries from cache", ioe);
    }
    return variants;
  }
  
  private void recordCacheMiss(HttpHost target, HttpRequestWrapper request)
  {
    cacheMisses.getAndIncrement();
    if (log.isTraceEnabled())
    {
      RequestLine rl = request.getRequestLine();
      log.trace("Cache miss [host: " + target + "; uri: " + rl.getUri() + "]");
    }
  }
  
  private void recordCacheHit(HttpHost target, HttpRequestWrapper request)
  {
    cacheHits.getAndIncrement();
    if (log.isTraceEnabled())
    {
      RequestLine rl = request.getRequestLine();
      log.trace("Cache hit [host: " + target + "; uri: " + rl.getUri() + "]");
    }
  }
  
  private void recordCacheUpdate(HttpContext context)
  {
    cacheUpdates.getAndIncrement();
    setResponseStatus(context, CacheResponseStatus.VALIDATED);
  }
  
  private void flushEntriesInvalidatedByRequest(HttpHost target, HttpRequestWrapper request)
  {
    try
    {
      responseCache.flushInvalidatedCacheEntriesFor(target, request);
    }
    catch (IOException ioe)
    {
      log.warn("Unable to flush invalidated entries from cache", ioe);
    }
  }
  
  private HttpResponse generateCachedResponse(HttpRequestWrapper request, HttpContext context, HttpCacheEntry entry, Date now)
  {
    HttpResponse cachedResponse;
    HttpResponse cachedResponse;
    if ((request.containsHeader("If-None-Match")) || (request.containsHeader("If-Modified-Since"))) {
      cachedResponse = responseGenerator.generateNotModifiedResponse(entry);
    } else {
      cachedResponse = responseGenerator.generateResponse(entry);
    }
    setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
    if (validityPolicy.getStalenessSecs(entry, now) > 0L) {
      cachedResponse.addHeader("Warning", "110 localhost \"Response is stale\"");
    }
    return cachedResponse;
  }
  
  private HttpResponse handleRevalidationFailure(HttpRequestWrapper request, HttpContext context, HttpCacheEntry entry, Date now)
  {
    if (staleResponseNotAllowed(request, entry, now)) {
      return generateGatewayTimeout(context);
    }
    return unvalidatedCacheHit(context, entry);
  }
  
  private HttpResponse generateGatewayTimeout(HttpContext context)
  {
    setResponseStatus(context, CacheResponseStatus.CACHE_MODULE_RESPONSE);
    return new BasicHttpResponse(HttpVersion.HTTP_1_1, 504, "Gateway Timeout");
  }
  
  private HttpResponse unvalidatedCacheHit(HttpContext context, HttpCacheEntry entry)
  {
    HttpResponse cachedResponse = responseGenerator.generateResponse(entry);
    setResponseStatus(context, CacheResponseStatus.CACHE_HIT);
    cachedResponse.addHeader("Warning", "111 localhost \"Revalidation failed\"");
    return cachedResponse;
  }
  
  private boolean staleResponseNotAllowed(HttpRequestWrapper request, HttpCacheEntry entry, Date now)
  {
    return (validityPolicy.mustRevalidate(entry)) || ((isSharedCache()) && (validityPolicy.proxyRevalidate(entry))) || (explicitFreshnessRequest(request, entry, now));
  }
  
  private boolean mayCallBackend(HttpRequestWrapper request)
  {
    for (Header h : request.getHeaders("Cache-Control")) {
      for (HeaderElement elt : h.getElements()) {
        if ("only-if-cached".equals(elt.getName()))
        {
          log.trace("Request marked only-if-cached");
          return false;
        }
      }
    }
    return true;
  }
  
  private boolean explicitFreshnessRequest(HttpRequestWrapper request, HttpCacheEntry entry, Date now)
  {
    for (Header h : request.getHeaders("Cache-Control")) {
      for (HeaderElement elt : h.getElements())
      {
        if ("max-stale".equals(elt.getName())) {
          try
          {
            int maxstale = Integer.parseInt(elt.getValue());
            long age = validityPolicy.getCurrentAgeSecs(entry, now);
            long lifetime = validityPolicy.getFreshnessLifetimeSecs(entry);
            if (age - lifetime > maxstale) {
              return true;
            }
          }
          catch (NumberFormatException nfe)
          {
            return true;
          }
        }
        if (("min-fresh".equals(elt.getName())) || ("max-age".equals(elt.getName()))) {
          return true;
        }
      }
    }
    return false;
  }
  
  private String generateViaHeader(HttpMessage msg)
  {
    ProtocolVersion pv = msg.getProtocolVersion();
    String existingEntry = (String)viaHeaders.get(pv);
    if (existingEntry != null) {
      return existingEntry;
    }
    VersionInfo vi = VersionInfo.loadVersionInfo("org.apache.http.client", getClass().getClassLoader());
    String release = vi != null ? vi.getRelease() : "UNAVAILABLE";
    String value;
    String value;
    if ("http".equalsIgnoreCase(pv.getProtocol())) {
      value = String.format("%d.%d localhost (Apache-HttpClient/%s (cache))", new Object[] { Integer.valueOf(pv.getMajor()), Integer.valueOf(pv.getMinor()), release });
    } else {
      value = String.format("%s/%d.%d localhost (Apache-HttpClient/%s (cache))", new Object[] { pv.getProtocol(), Integer.valueOf(pv.getMajor()), Integer.valueOf(pv.getMinor()), release });
    }
    viaHeaders.put(pv, value);
    
    return value;
  }
  
  private void setResponseStatus(HttpContext context, CacheResponseStatus value)
  {
    if (context != null) {
      context.setAttribute("http.cache.response.status", value);
    }
  }
  
  public boolean supportsRangeAndContentRangeHeaders()
  {
    return false;
  }
  
  public boolean isSharedCache()
  {
    return sharedCache;
  }
  
  Date getCurrentDate()
  {
    return new Date();
  }
  
  boolean clientRequestsOurOptions(HttpRequest request)
  {
    RequestLine line = request.getRequestLine();
    if (!"OPTIONS".equals(line.getMethod())) {
      return false;
    }
    if (!"*".equals(line.getUri())) {
      return false;
    }
    if (!"0".equals(request.getFirstHeader("Max-Forwards").getValue())) {
      return false;
    }
    return true;
  }
  
  HttpResponse callBackend(HttpHost target, HttpRequestWrapper request, HttpContext context)
    throws IOException
  {
    Date requestDate = getCurrentDate();
    
    log.trace("Calling the backend");
    HttpResponse backendResponse = backend.execute(target, request, context);
    backendResponse.addHeader("Via", generateViaHeader(backendResponse));
    return handleBackendResponse(target, request, requestDate, getCurrentDate(), backendResponse);
  }
  
  private boolean revalidationResponseIsTooOld(HttpResponse backendResponse, HttpCacheEntry cacheEntry)
  {
    Header entryDateHeader = cacheEntry.getFirstHeader("Date");
    Header responseDateHeader = backendResponse.getFirstHeader("Date");
    if ((entryDateHeader != null) && (responseDateHeader != null)) {
      try
      {
        Date entryDate = DateUtils.parseDate(entryDateHeader.getValue());
        Date respDate = DateUtils.parseDate(responseDateHeader.getValue());
        if (respDate.before(entryDate)) {
          return true;
        }
      }
      catch (DateParseException e) {}
    }
    return false;
  }
  
  HttpResponse negotiateResponseFromVariants(HttpHost target, HttpRequestWrapper request, HttpContext context, Map<String, Variant> variants)
    throws IOException
  {
    HttpRequestWrapper conditionalRequest = conditionalRequestBuilder.buildConditionalRequestFromVariants(request, variants);
    
    Date requestDate = getCurrentDate();
    HttpResponse backendResponse = backend.execute(target, conditionalRequest, context);
    Date responseDate = getCurrentDate();
    
    backendResponse.addHeader("Via", generateViaHeader(backendResponse));
    if (backendResponse.getStatusLine().getStatusCode() != 304) {
      return handleBackendResponse(target, request, requestDate, responseDate, backendResponse);
    }
    Header resultEtagHeader = backendResponse.getFirstHeader("ETag");
    if (resultEtagHeader == null)
    {
      log.warn("304 response did not contain ETag");
      return callBackend(target, request, context);
    }
    String resultEtag = resultEtagHeader.getValue();
    Variant matchingVariant = (Variant)variants.get(resultEtag);
    if (matchingVariant == null)
    {
      log.debug("304 response did not contain ETag matching one sent in If-None-Match");
      return callBackend(target, request, context);
    }
    HttpCacheEntry matchedEntry = matchingVariant.getEntry();
    if (revalidationResponseIsTooOld(backendResponse, matchedEntry))
    {
      EntityUtils.consume(backendResponse.getEntity());
      return retryRequestUnconditionally(target, request, context, matchedEntry);
    }
    recordCacheUpdate(context);
    
    HttpCacheEntry responseEntry = getUpdatedVariantEntry(target, conditionalRequest, requestDate, responseDate, backendResponse, matchingVariant, matchedEntry);
    
    HttpResponse resp = responseGenerator.generateResponse(responseEntry);
    tryToUpdateVariantMap(target, request, matchingVariant);
    if (shouldSendNotModifiedResponse(request, responseEntry)) {
      return responseGenerator.generateNotModifiedResponse(responseEntry);
    }
    return resp;
  }
  
  private HttpResponse retryRequestUnconditionally(HttpHost target, HttpRequestWrapper request, HttpContext context, HttpCacheEntry matchedEntry)
    throws IOException
  {
    HttpRequestWrapper unconditional = conditionalRequestBuilder.buildUnconditionalRequest(request, matchedEntry);
    
    return callBackend(target, unconditional, context);
  }
  
  private HttpCacheEntry getUpdatedVariantEntry(HttpHost target, HttpRequestWrapper conditionalRequest, Date requestDate, Date responseDate, HttpResponse backendResponse, Variant matchingVariant, HttpCacheEntry matchedEntry)
  {
    HttpCacheEntry responseEntry = matchedEntry;
    try
    {
      responseEntry = responseCache.updateVariantCacheEntry(target, conditionalRequest, matchedEntry, backendResponse, requestDate, responseDate, matchingVariant.getCacheKey());
    }
    catch (IOException ioe)
    {
      log.warn("Could not update cache entry", ioe);
    }
    return responseEntry;
  }
  
  private void tryToUpdateVariantMap(HttpHost target, HttpRequestWrapper request, Variant matchingVariant)
  {
    try
    {
      responseCache.reuseVariantEntryFor(target, request, matchingVariant);
    }
    catch (IOException ioe)
    {
      log.warn("Could not update cache entry to reuse variant", ioe);
    }
  }
  
  private boolean shouldSendNotModifiedResponse(HttpRequestWrapper request, HttpCacheEntry responseEntry)
  {
    return (suitabilityChecker.isConditional(request)) && (suitabilityChecker.allConditionalsMatch(request, responseEntry, new Date()));
  }
  
  HttpResponse revalidateCacheEntry(HttpHost target, HttpRequestWrapper request, HttpContext context, HttpCacheEntry cacheEntry)
    throws IOException, ProtocolException
  {
    HttpRequestWrapper conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
    
    Date requestDate = getCurrentDate();
    HttpResponse backendResponse = backend.execute(target, conditionalRequest, context);
    Date responseDate = getCurrentDate();
    if (revalidationResponseIsTooOld(backendResponse, cacheEntry))
    {
      EntityUtils.consume(backendResponse.getEntity());
      HttpRequest unconditional = conditionalRequestBuilder.buildUnconditionalRequest(request, cacheEntry);
      
      requestDate = getCurrentDate();
      backendResponse = backend.execute(target, unconditional, context);
      responseDate = getCurrentDate();
    }
    backendResponse.addHeader("Via", generateViaHeader(backendResponse));
    
    int statusCode = backendResponse.getStatusLine().getStatusCode();
    if ((statusCode == 304) || (statusCode == 200)) {
      recordCacheUpdate(context);
    }
    if (statusCode == 304)
    {
      HttpCacheEntry updatedEntry = responseCache.updateCacheEntry(target, request, cacheEntry, backendResponse, requestDate, responseDate);
      if ((suitabilityChecker.isConditional(request)) && (suitabilityChecker.allConditionalsMatch(request, updatedEntry, new Date()))) {
        return responseGenerator.generateNotModifiedResponse(updatedEntry);
      }
      return responseGenerator.generateResponse(updatedEntry);
    }
    if ((staleIfErrorAppliesTo(statusCode)) && (!staleResponseNotAllowed(request, cacheEntry, getCurrentDate())) && (validityPolicy.mayReturnStaleIfError(request, cacheEntry, responseDate)))
    {
      HttpResponse cachedResponse = responseGenerator.generateResponse(cacheEntry);
      cachedResponse.addHeader("Warning", "110 localhost \"Response is stale\"");
      HttpEntity errorBody = backendResponse.getEntity();
      if (errorBody != null) {
        EntityUtils.consume(errorBody);
      }
      return cachedResponse;
    }
    return handleBackendResponse(target, conditionalRequest, requestDate, responseDate, backendResponse);
  }
  
  private boolean staleIfErrorAppliesTo(int statusCode)
  {
    return (statusCode == 500) || (statusCode == 502) || (statusCode == 503) || (statusCode == 504);
  }
  
  HttpResponse handleBackendResponse(HttpHost target, HttpRequestWrapper request, Date requestDate, Date responseDate, HttpResponse backendResponse)
    throws IOException
  {
    log.trace("Handling Backend response");
    responseCompliance.ensureProtocolCompliance(request, backendResponse);
    
    boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse);
    responseCache.flushInvalidatedCacheEntriesFor(target, request, backendResponse);
    if ((cacheable) && (!alreadyHaveNewerCacheEntry(target, request, backendResponse))) {
      try
      {
        storeRequestIfModifiedSinceFor304Response(request, backendResponse);
        return responseCache.cacheAndReturnResponse(target, request, backendResponse, requestDate, responseDate);
      }
      catch (IOException ioe)
      {
        log.warn("Unable to store entries in cache", ioe);
      }
    }
    if (!cacheable) {
      try
      {
        responseCache.flushCacheEntriesFor(target, request);
      }
      catch (IOException ioe)
      {
        log.warn("Unable to flush invalid cache entries", ioe);
      }
    }
    return backendResponse;
  }
  
  private void storeRequestIfModifiedSinceFor304Response(HttpRequest request, HttpResponse backendResponse)
  {
    if (backendResponse.getStatusLine().getStatusCode() == 304)
    {
      Header h = request.getFirstHeader("If-Modified-Since");
      if (h != null) {
        backendResponse.addHeader("Last-Modified", h.getValue());
      }
    }
  }
  
  private boolean alreadyHaveNewerCacheEntry(HttpHost target, HttpRequest request, HttpResponse backendResponse)
  {
    HttpCacheEntry existing = null;
    try
    {
      existing = responseCache.getCacheEntry(target, request);
    }
    catch (IOException ioe) {}
    if (existing == null) {
      return false;
    }
    Header entryDateHeader = existing.getFirstHeader("Date");
    if (entryDateHeader == null) {
      return false;
    }
    Header responseDateHeader = backendResponse.getFirstHeader("Date");
    if (responseDateHeader == null) {
      return false;
    }
    try
    {
      Date entryDate = DateUtils.parseDate(entryDateHeader.getValue());
      Date responseDate = DateUtils.parseDate(responseDateHeader.getValue());
      return responseDate.before(entryDate);
    }
    catch (DateParseException e) {}
    return false;
  }
  
  static class AsynchronousValidator
  {
    private final CachingHttpClient cachingClient;
    private final ExecutorService executor;
    private final Set<String> queued;
    private final CacheKeyGenerator cacheKeyGenerator;
    private final Log log = LogFactory.getLog(getClass());
    
    public AsynchronousValidator(CachingHttpClient cachingClient, CacheConfig config)
    {
      this(cachingClient, new ThreadPoolExecutor(config.getAsynchronousWorkersCore(), config.getAsynchronousWorkersMax(), config.getAsynchronousWorkerIdleLifetimeSecs(), TimeUnit.SECONDS, new ArrayBlockingQueue(config.getRevalidationQueueSize())));
    }
    
    AsynchronousValidator(CachingHttpClient cachingClient, ExecutorService executor)
    {
      this.cachingClient = cachingClient;
      this.executor = executor;
      queued = new HashSet();
      cacheKeyGenerator = new CacheKeyGenerator();
    }
    
    public synchronized void revalidateCacheEntry(HttpHost target, HttpRequestWrapper request, HttpContext context, HttpCacheEntry entry)
    {
      String uri = cacheKeyGenerator.getVariantURI(target, request, entry);
      if (!queued.contains(uri))
      {
        CachingHttpClient.AsynchronousValidationRequest revalidationRequest = new CachingHttpClient.AsynchronousValidationRequest(this, cachingClient, target, request, context, entry, uri);
        try
        {
          executor.execute(revalidationRequest);
          queued.add(uri);
        }
        catch (RejectedExecutionException ree)
        {
          log.debug("Revalidation for [" + uri + "] not scheduled: " + ree);
        }
      }
    }
    
    synchronized void markComplete(String identifier)
    {
      queued.remove(identifier);
    }
    
    Set<String> getScheduledIdentifiers()
    {
      return Collections.unmodifiableSet(queued);
    }
    
    ExecutorService getExecutor()
    {
      return executor;
    }
  }
  
  static class AsynchronousValidationRequest
    implements Runnable
  {
    private final CachingHttpClient.AsynchronousValidator parent;
    private final CachingHttpClient cachingClient;
    private final HttpHost target;
    private final HttpRequestWrapper request;
    private final HttpContext context;
    private final HttpCacheEntry cacheEntry;
    private final String identifier;
    private final Log log = LogFactory.getLog(getClass());
    
    AsynchronousValidationRequest(CachingHttpClient.AsynchronousValidator parent, CachingHttpClient cachingClient, HttpHost target, HttpRequestWrapper request, HttpContext context, HttpCacheEntry cacheEntry, String identifier)
    {
      this.parent = parent;
      this.cachingClient = cachingClient;
      this.target = target;
      this.request = request;
      this.context = context;
      this.cacheEntry = cacheEntry;
      this.identifier = identifier;
    }
    
    public void run()
    {
      try
      {
        cachingClient.revalidateCacheEntry(target, request, context, cacheEntry);
      }
      catch (IOException ioe)
      {
        log.debug("Asynchronous revalidation failed due to exception: " + ioe);
      }
      catch (ProtocolException pe)
      {
        log.error("ProtocolException thrown during asynchronous revalidation: " + pe);
      }
      finally
      {
        parent.markComplete(identifier);
      }
    }
    
    String getIdentifier()
    {
      return identifier;
    }
  }
}

/* Location:
 * Qualified Name:     org.apache.http.impl.client.cache.CachingHttpClient
 * Java Class Version: 5 (49.0)
 * JD-Core Version:    0.7.1
 */
package org.apache.http.impl.client.cache;

import java.io.File;
import org.apache.http.client.cache.HttpCacheInvalidator;
import org.apache.http.client.cache.HttpCacheStorage;
import org.apache.http.client.cache.ResourceFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.execchain.ClientExecChain;

public class CachingHttpClientBuilder
  extends HttpClientBuilder
{
  private ResourceFactory resourceFactory;
  private HttpCacheStorage storage;
  private File cacheDir;
  private CacheConfig cacheConfig;
  private SchedulingStrategy schedulingStrategy;
  private HttpCacheInvalidator httpCacheInvalidator;
  
  public static CachingHttpClientBuilder create()
  {
    return new CachingHttpClientBuilder();
  }
  
  public final CachingHttpClientBuilder setResourceFactory(ResourceFactory resourceFactory)
  {
    this.resourceFactory = resourceFactory;
    return this;
  }
  
  public final CachingHttpClientBuilder setHttpCacheStorage(HttpCacheStorage storage)
  {
    this.storage = storage;
    return this;
  }
  
  public final CachingHttpClientBuilder setCacheDir(File cacheDir)
  {
    this.cacheDir = cacheDir;
    return this;
  }
  
  public final CachingHttpClientBuilder setCacheConfig(CacheConfig cacheConfig)
  {
    this.cacheConfig = cacheConfig;
    return this;
  }
  
  public final CachingHttpClientBuilder setSchedulingStrategy(SchedulingStrategy schedulingStrategy)
  {
    this.schedulingStrategy = schedulingStrategy;
    return this;
  }
  
  public final CachingHttpClientBuilder setHttpCacheInvalidator(HttpCacheInvalidator cacheInvalidator)
  {
    httpCacheInvalidator = cacheInvalidator;
    return this;
  }
  
  protected ClientExecChain decorateMainExec(ClientExecChain ma
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

Further reading...

For more information on Java 1.5 Tiger, you may find Java 1.5 Tiger, A developer's Notebook by D. Flanagan and B. McLaughlin from O'Reilly of interest.

New!JAR listings


Copyright 2006-2019. Infinite Loop Ltd