org.sonatype.nexus.repository.cache.CacheInfo Java Examples

The following examples show how to use org.sonatype.nexus.repository.cache.CacheInfo. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: ComposerProxyFacetImpl.java    From nexus-repository-composer with Eclipse Public License 1.0 6 votes vote down vote up
@Override
protected void indicateVerified(final Context context, final Content content, final CacheInfo cacheInfo)
    throws IOException
{
  AssetKind assetKind = context.getAttributes().require(AssetKind.class);
  switch (assetKind) {
    case PACKAGES:
      content().setCacheInfo(PACKAGES_JSON, content, cacheInfo);
      break;
    case LIST:
      content().setCacheInfo(LIST_JSON, content, cacheInfo);
      break;
    case PROVIDER:
      content().setCacheInfo(buildProviderPath(context), content, cacheInfo);
      break;
    case ZIPBALL:
      content().setCacheInfo(buildZipballPath(context), content, cacheInfo);
      break;
    default:
      throw new IllegalStateException();
  }
}
 
Example #2
Source File: ConcurrentProxyTest.java    From nexus-public with Eclipse Public License 1.0 6 votes vote down vote up
@Before
public void setUp() throws Exception {
  // this is the mock index used for indirect requests
  when(metaRequest.getPath()).thenReturn("index.json");
  when(metaContext.getRequest()).thenReturn(metaRequest);

  when(attributesMap.get(CacheInfo.class)).thenReturn(cacheInfo);

  when(metaContent.getAttributes()).thenReturn(attributesMap);
  when(assetContent.getAttributes()).thenReturn(attributesMap);

  when(metaContent.openInputStream()).thenAnswer(invocation -> new ByteArrayInputStream(META_CONTENT));
  when(assetContent.openInputStream()).thenAnswer(invocation -> new ByteArrayInputStream(ASSET_CONTENT));

  when(cacheController.isStale(cacheInfo)).thenReturn(false);
  when(cacheControllerHolder.getContentCacheController()).thenReturn(cacheController);

  when(repository.getName()).thenReturn("test-repo");

  underTest.cacheControllerHolder = cacheControllerHolder;
  underTest.attach(repository);
}
 
Example #3
Source File: MavenProxyFacet.java    From nexus-public with Eclipse Public License 1.0 6 votes vote down vote up
@Override
@TransactionalTouchMetadata
protected void indicateVerified(final Context context, final Content content, final CacheInfo cacheInfo)
    throws IOException
{
  final StorageTx tx = UnitOfWork.currentTx();
  final Bucket bucket = tx.findBucket(getRepository());
  final MavenPath path = mavenPath(context);

  // by EntityId
  Asset asset = Content.findAsset(tx, bucket, content);
  if (asset == null) {
    // by format coordinates
    asset = findAsset(tx, bucket, path);
  }
  if (asset == null) {
    log.debug("Attempting to set cache info for non-existent maven asset {}", path.getPath());
    return;
  }

  log.debug("Updating cacheInfo of {} to {}", path.getPath(), cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #4
Source File: RawContentFacetImpl.java    From nexus-public with Eclipse Public License 1.0 6 votes vote down vote up
@Override
@TransactionalTouchMetadata
public void setCacheInfo(final String path, final Content content, final CacheInfo cacheInfo) throws IOException {
  StorageTx tx = UnitOfWork.currentTx();
  Bucket bucket = tx.findBucket(getRepository());

  // by EntityId
  Asset asset = Content.findAsset(tx, bucket, content);
  if (asset == null) {
    // by format coordinates
    Component component = tx.findComponentWithProperty(P_NAME, path, bucket);
    if (component != null) {
      asset = tx.firstAsset(component);
    }
  }
  if (asset == null) {
    log.debug("Attempting to set cache info for non-existent raw component {}", path);
    return;
  }

  log.debug("Updating cacheInfo of {} to {}", path, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #5
Source File: OrientPyPiGroupFacet.java    From nexus-public with Eclipse Public License 1.0 6 votes vote down vote up
@TransactionalStoreBlob
public Content saveToCache(final String name, final Content content) throws IOException {
  StorageTx tx = UnitOfWork.currentTx();

  Asset asset = getAsset(tx, name);
  AttributesMap contentAttributes = Content.maintainLastModified(asset, null);
  contentAttributes.set(CacheInfo.class, cacheController.current());
  Content.applyToAsset(asset, contentAttributes);

  AssetBlob blob = updateAsset(tx, asset, content);

  Content response = new Content(new BlobPayload(blob.getBlob(), ContentTypes.TEXT_HTML));
  Content.extractFromAsset(asset, HASH_ALGORITHMS, response.getAttributes());

  return response;
}
 
Example #6
Source File: OrientPyPiProxyFacetImpl.java    From nexus-public with Eclipse Public License 1.0 6 votes vote down vote up
@TransactionalTouchMetadata
protected void setCacheInfo(final Content content, final CacheInfo cacheInfo) throws IOException {
  StorageTx tx = UnitOfWork.currentTx();

  Asset asset = Content.findAsset(tx, tx.findBucket(getRepository()), content);
  if (asset == null) {
    log.debug(
        "Attempting to set cache info for non-existent pypi asset {}", content.getAttributes().require(Asset.class)
    );
    return;
  }

  log.debug("Updating cacheInfo of {} to {}", asset, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #7
Source File: RProxyFacetImpl.java    From nexus-repository-r with Eclipse Public License 1.0 6 votes vote down vote up
@TransactionalTouchMetadata
public void setCacheInfo(final Content content, final CacheInfo cacheInfo) {
  StorageTx tx = UnitOfWork.currentTx();

  Asset asset = Content.findAsset(tx, tx.findBucket(getRepository()), content);
  if (asset == null) {
    log.debug(
        "Attempting to set cache info for non-existent R asset {}", content.getAttributes().require(Asset.class)
    );
    return;
  }

  log.debug("Updating cacheInfo of {} to {}", asset, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #8
Source File: OrientNpmProxyFacet.java    From nexus-public with Eclipse Public License 1.0 6 votes vote down vote up
@TransactionalTouchMetadata
public void setCacheInfo(final Content content, final CacheInfo cacheInfo) throws IOException {
  StorageTx tx = UnitOfWork.currentTx();

  Asset asset = Content.findAsset(tx, tx.findBucket(getRepository()), content);
  if (asset == null) {
    log.debug(
        "Attempting to set cache info for non-existent npm asset {}", content.getAttributes().require(Asset.class)
    );
    return;
  }

  log.debug("Updating cacheInfo of {} to {}", asset, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #9
Source File: Content.java    From nexus-public with Eclipse Public License 1.0 6 votes vote down vote up
/**
 * Extracts non-format specific content attributes into the passed in {@link AttributesMap} (usually originating from
 * {@link Content#getAttributes()}) from passed in {@link Asset} and format required hashes.
 */
public static void extractFromAsset(final Asset asset,
                                    final Iterable<HashAlgorithm> hashAlgorithms,
                                    final AttributesMap contentAttributes)
{
  checkNotNull(asset);
  checkNotNull(hashAlgorithms);
  final NestedAttributesMap assetAttributes = asset.attributes().child(CONTENT);
  final DateTime lastModified = toDateTime(assetAttributes.get(P_LAST_MODIFIED, Date.class));
  final String etag = assetAttributes.get(P_ETAG, String.class);

  final Map<HashAlgorithm, HashCode> checksums = asset.getChecksums(hashAlgorithms);

  contentAttributes.set(Asset.class, asset);
  contentAttributes.set(Content.CONTENT_LAST_MODIFIED, lastModified);
  contentAttributes.set(Content.CONTENT_ETAG, etag);
  contentAttributes.set(Content.CONTENT_HASH_CODES_MAP, checksums);
  contentAttributes.set(CacheInfo.class, CacheInfo.extractFromAsset(asset));
}
 
Example #10
Source File: CocoapodsProxyFacet.java    From nexus-public with Eclipse Public License 1.0 6 votes vote down vote up
@TransactionalTouchMetadata
public void setCacheInfo(final Content content, final CacheInfo cacheInfo) throws IOException {
  StorageTx tx = UnitOfWork.currentTx();

  Asset asset = Content.findAsset(tx, tx.findBucket(getRepository()), content);
  if (asset == null) {
    log.debug(
        "Attempting to set cache info for non-existent Cocoapods asset {}",
        content.getAttributes().require(Asset.class)
    );
    return;
  }

  log.debug("Updating cacheInfo of {} to {}", asset, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #11
Source File: GolangProxyFacetImpl.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@TransactionalTouchMetadata
public void setCacheInfo(final Content content, final CacheInfo cacheInfo) throws IOException {
  StorageTx tx = UnitOfWork.currentTx();
  Asset asset = Content.findAsset(tx, tx.findBucket(getRepository()), content);
  if (asset == null) {
    log.debug(
        "Attempting to set cache info for non-existent go asset {}", content.getAttributes().require(Asset.class)
    );
    return;
  }
  log.debug("Updating cacheInfo of {} to {}", asset, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #12
Source File: ComposerContentFacetImpl.java    From nexus-repository-composer with Eclipse Public License 1.0 5 votes vote down vote up
@Override
@TransactionalTouchMetadata
public void setCacheInfo(final String path, final Content content, final CacheInfo cacheInfo) throws IOException {
  StorageTx tx = UnitOfWork.currentTx();
  Bucket bucket = tx.findBucket(getRepository());

  Asset asset = Content.findAsset(tx, bucket, content);
  if (asset == null) {
    log.debug("Attempting to set cache info for non-existent Composer asset {}", path);
    return;
  }

  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #13
Source File: OrientMavenGroupFacet.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Tries to invalidate the current main cached asset for the given {@link MavenPath}.
 */
@Transactional(retryOn = ONeedRetryException.class, swallow = ORecordNotFoundException.class)
protected void doInvalidate(final MavenPath mavenPath) {
  StorageTx tx = UnitOfWork.currentTx();
  final Asset asset = findAsset(tx, tx.findBucket(getRepository()), mavenPath.main());
  if (asset != null && CacheInfo.invalidateAsset(asset)) {
    tx.saveAsset(asset);
  }
}
 
Example #14
Source File: OrientMetadataUtils.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Checks whether or not the maven metadata should be rebuilt via its associated {@link Asset}
 *
 * Metadata should be rebuilt if either it has been manually marked via {@link OrientMetadataUtils#addRebuildFlag} or
 * if it has been invalidated via it's {@link CacheInfo}.
 */
public static boolean requiresRebuild(final Asset metadataAsset) {
  requireNonNull(metadataAsset);

  if (TRUE.equals(metadataAsset.formatAttributes().get(METADATA_REBUILD_KEY, false))) {
    return true;
  }

  CacheInfo cacheInfo = extractFromAsset(metadataAsset);
  return cacheInfo != null && cacheInfo.isInvalidated();
}
 
Example #15
Source File: AptProxyFacet.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
private Optional<SnapshotItem> fetchLatest(final ContentSpecifier spec) throws IOException {
  AptFacet aptFacet = getRepository().facet(AptFacet.class);
  ProxyFacet proxyFacet = facet(ProxyFacet.class);
  HttpClientFacet httpClientFacet = facet(HttpClientFacet.class);
  HttpClient httpClient = httpClientFacet.getHttpClient();
  CacheController cacheController = cacheControllerHolder.getMetadataCacheController();
  CacheInfo cacheInfo = cacheController.current();
  Content oldVersion = aptFacet.get(spec.path);

  URI fetchUri = proxyFacet.getRemoteUrl().resolve(spec.path);
  HttpGet getRequest = buildFetchRequest(oldVersion, fetchUri);

  HttpResponse response = httpClient.execute(getRequest);
  StatusLine status = response.getStatusLine();

  if (status.getStatusCode() == HttpStatus.SC_OK) {
    HttpEntity entity = response.getEntity();
    Content fetchedContent = new Content(new HttpEntityPayload(response, entity));
    AttributesMap contentAttrs = fetchedContent.getAttributes();
    contentAttrs.set(Content.CONTENT_LAST_MODIFIED, getDateHeader(response, HttpHeaders.LAST_MODIFIED));
    contentAttrs.set(Content.CONTENT_ETAG, getQuotedStringHeader(response, HttpHeaders.ETAG));
    contentAttrs.set(CacheInfo.class, cacheInfo);
    Content storedContent = getAptFacet().put(spec.path, fetchedContent);
    return Optional.of(new SnapshotItem(spec, storedContent));
  }

  try {
    if (status.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
      checkState(oldVersion != null, "Received 304 without conditional GET (bad server?) from %s", fetchUri);
      doIndicateVerified(oldVersion, cacheInfo, spec.path);
      return Optional.of(new SnapshotItem(spec, oldVersion));
    }
    throwProxyExceptionForStatus(response);
  }
  finally {
    HttpClientUtils.closeQuietly(response);
  }

  return Optional.empty();
}
 
Example #16
Source File: AptProxyFacet.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@Transactional(retryOn = {ONeedRetryException.class})
protected void doIndicateVerified(final Content content, final CacheInfo cacheInfo, final String assetPath) {
  StorageTx tx = UnitOfWork.currentTx();
  Bucket bucket = tx.findBucket(getRepository());

  Asset asset = Content.findAsset(tx, bucket, content);
  if (asset == null) {
    asset = tx.findAssetWithProperty(P_NAME, assetPath, bucket);
  }
  if (asset == null) {
    return;
  }
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #17
Source File: Content.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Applies non-format specific content attributes onto passed in {@link Asset} from passed in {@link AttributesMap}
 * (usually originating from {@link Content#getAttributes()}).
 */
public static void applyToAsset(final Asset asset, final AttributesMap contentAttributes) {
  checkNotNull(asset);
  checkNotNull(contentAttributes);
  final NestedAttributesMap assetAttributes = asset.attributes().child(CONTENT);
  assetAttributes.set(P_LAST_MODIFIED, toDate(contentAttributes.get(Content.CONTENT_LAST_MODIFIED, DateTime.class)));
  assetAttributes.set(P_ETAG, contentAttributes.get(Content.CONTENT_ETAG, String.class));
  final CacheInfo cacheInfo = contentAttributes.get(CacheInfo.class);
  if (cacheInfo != null) {
    CacheInfo.applyToAsset(asset, cacheInfo);
  }
}
 
Example #18
Source File: FluentAssetImpl.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@Override
public FluentAsset markAsCached(final Payload content) {
  if (content instanceof Content) {
    AttributesMap contentAttributes = ((Content) content).getAttributes();
    CacheInfo cacheInfo = contentAttributes.get(CacheInfo.class);
    if (cacheInfo != null) {
      markAsCached(cacheInfo);
    }
    cacheContentHeaders(contentAttributes);
  }
  return this;
}
 
Example #19
Source File: ContentProxyFacetSupport.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@Override
protected void indicateVerified(
    final Context context,
    final Content content,
    final CacheInfo cacheInfo) throws IOException
{
  // refresh internal cache details to record that we know this asset is up-to-date
  Asset asset = content.getAttributes().get(Asset.class);
  if (asset != null) {
    facet(ContentFacet.class).assets().with(asset).markAsCached(cacheInfo);
  }
  else {
    log.debug("Proxied content has no attached asset; cannot refresh cache details");
  }
}
 
Example #20
Source File: GroupFacetImpl.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
/**
 * Returns {@code true} if the content is considered stale; otherwise {@code false}.
 */
protected boolean isStale(@Nullable final Content content) {
  if (content == null) {
    return true;
  }

  final CacheInfo cacheInfo = content.getAttributes().get(CacheInfo.class);

  if(isNull(cacheInfo)) {
    log.warn("CacheInfo missing for {}, assuming stale content.", content);
    return true;
  }
  return cacheController.isStale(cacheInfo);
}
 
Example #21
Source File: ProxyFacetSupport.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
private boolean isStale(final Context context, final Content content) {
  if (content == null) {
    // not in cache, consider it stale
    return true;
  }

  final CacheInfo cacheInfo = content.getAttributes().get(CacheInfo.class);

  if(isNull(cacheInfo)) {
    log.warn("CacheInfo missing for {}, assuming stale content.", content);
    return true;
  }
  return getCacheController(context).isStale(cacheInfo);
}
 
Example #22
Source File: GroupFacetImplTest.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@Test
public void whenCacheInfoIsNullThenIsStale() {
  when(content.getAttributes()).thenReturn(attributesMap);
  when(attributesMap.get(CacheInfo.class)).thenReturn(null);

  assertThat(underTest.isStale(content), is(true));
}
 
Example #23
Source File: GroupFacetImplTest.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@Test
public void whenCachePresentTheNotStale() {
  when(content.getAttributes()).thenReturn(attributesMap);
  when(attributesMap.get(CacheInfo.class)).thenReturn(cacheInfo);
  CacheController cacheController = mock(CacheController.class);
  underTest.cacheController = cacheController;
  when(cacheController.isStale(cacheInfo)).thenReturn(false);

  assertThat(underTest.isStale(content), is(false));
}
 
Example #24
Source File: ProxyFacetSupportTest.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@Test
public void whenCacheInfoIsNullThenIsStaleIsTrue() throws Exception {
  when(attributesMap.get(CacheInfo.class)).thenReturn(null);
  when(cacheController.isStale(cacheInfo)).thenReturn(true);
  doReturn(content).when(underTest).getCachedContent(cachedContext);

  doReturn(reFetchedContent).when(underTest).fetch(cachedContext, content);
  doReturn(reFetchedContent).when(underTest).store(cachedContext, reFetchedContent);

  Content foundContent = underTest.get(cachedContext);

  assertThat(foundContent, is(reFetchedContent));
}
 
Example #25
Source File: P2ProxyFacetImpl.java    From nexus-repository-p2 with Eclipse Public License 1.0 5 votes vote down vote up
@TransactionalTouchMetadata
public void setCacheInfo(final Content content, final CacheInfo cacheInfo) {
  StorageTx tx = UnitOfWork.currentTx();
  Asset asset = Content.findAsset(tx, tx.findBucket(getRepository()), content);
  if (asset == null) {
    log.debug(
        "Attempting to set cache info for non-existent P2 asset {}", content.getAttributes().require(Asset.class)
    );
    return;
  }
  log.debug("Updating cacheInfo of {} to {}", asset, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #26
Source File: HelmProxyFacetImpl.java    From nexus-repository-helm with Eclipse Public License 1.0 5 votes vote down vote up
@TransactionalTouchMetadata
public void setCacheInfo(final Content content, final CacheInfo cacheInfo) {
  StorageTx tx = UnitOfWork.currentTx();
  Asset asset = Content.findAsset(tx, tx.findBucket(getRepository()), content);
  if (asset == null) {
    log.debug(
        "Attempting to set cache info for non-existent Helm asset {}", content.getAttributes().require(Asset.class)
    );
    return;
  }
  log.debug("Updating cacheInfo of {} to {}", asset, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #27
Source File: OrientNpmProxyFacet.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@Override
protected void indicateVerified(final Context context,
                                final Content content,
                                final CacheInfo cacheInfo) throws IOException
{
  setCacheInfo(content, cacheInfo);
}
 
Example #28
Source File: CondaProxyFacetImpl.java    From nexus-public with Eclipse Public License 1.0 5 votes vote down vote up
@TransactionalTouchMetadata
protected void setCacheInfo(final Content content, final CacheInfo cacheInfo)
{
  StorageTx tx = UnitOfWork.currentTx();
  Asset asset = Content.findAsset(tx, tx.findBucket(getRepository()), content);
  if (asset == null) {
    log.debug(
        "Attempting to set cache info for non-existent Conda asset {}", content.getAttributes().require(Asset.class)
    );
    return;
  }
  log.debug("Updating cacheInfo of {} to {}", asset, cacheInfo);
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #29
Source File: AptProxyFacet.java    From nexus-repository-apt with Eclipse Public License 1.0 5 votes vote down vote up
@Transactional(retryOn = { ONeedRetryException.class })
protected void doIndicateVerified(Content content, CacheInfo cacheInfo, String assetPath) {
  StorageTx tx = UnitOfWork.currentTx();
  Bucket bucket = tx.findBucket(getRepository());

  Asset asset = Content.findAsset(tx, bucket, content);
  if (asset == null) {
    asset = tx.findAssetWithProperty(P_NAME, assetPath, bucket);
  }
  if (asset == null) {
    return;
  }
  CacheInfo.applyToAsset(asset, cacheInfo);
  tx.saveAsset(asset);
}
 
Example #30
Source File: AptProxyFacet.java    From nexus-repository-apt with Eclipse Public License 1.0 5 votes vote down vote up
private Optional<SnapshotItem> fetchLatest(ContentSpecifier spec) throws IOException {
  AptFacet aptFacet = getRepository().facet(AptFacet.class);
  ProxyFacet proxyFacet = facet(ProxyFacet.class);
  HttpClientFacet httpClientFacet = facet(HttpClientFacet.class);
  HttpClient httpClient = httpClientFacet.getHttpClient();
  CacheController cacheController = cacheControllerHolder.getMetadataCacheController();
  CacheInfo cacheInfo = cacheController.current();
  Content oldVersion = aptFacet.get(spec.path);

  URI fetchUri = proxyFacet.getRemoteUrl().resolve(spec.path);
  HttpGet getRequest = buildFetchRequest(oldVersion, fetchUri);

  HttpResponse response = httpClient.execute(getRequest);
  StatusLine status = response.getStatusLine();

  if (status.getStatusCode() == HttpStatus.SC_OK) {
    HttpEntity entity = response.getEntity();
    Content fetchedContent = new Content(new HttpEntityPayload(response, entity));
    AttributesMap contentAttrs = fetchedContent.getAttributes();
    contentAttrs.set(Content.CONTENT_LAST_MODIFIED, getDateHeader(response, HttpHeaders.LAST_MODIFIED));
    contentAttrs.set(Content.CONTENT_ETAG, getQuotedStringHeader(response, HttpHeaders.ETAG));
    contentAttrs.set(CacheInfo.class, cacheInfo);
    Content storedContent = getAptFacet().put(spec.path, fetchedContent);
    return Optional.of(new SnapshotItem(spec, storedContent));
  }

  try {
    if (status.getStatusCode() == HttpStatus.SC_NOT_MODIFIED) {
      checkState(oldVersion != null, "Received 304 without conditional GET (bad server?) from %s", fetchUri);
      doIndicateVerified(oldVersion, cacheInfo, spec.path);
      return Optional.of(new SnapshotItem(spec, oldVersion));
    }
    throwProxyExceptionForStatus(response);
  }
  finally {
    HttpClientUtils.closeQuietly(response);
  }

  return Optional.empty();
}