Package org.sonatype.nexus.proxy.maven

Source Code of org.sonatype.nexus.proxy.maven.ChecksumContentValidator

/*
* Sonatype Nexus (TM) Open Source Version
* Copyright (c) 2007-2014 Sonatype, Inc.
* All rights reserved. Includes the third-party code listed at http://links.sonatype.com/products/nexus/oss/attributions.
*
* This program and the accompanying materials are made available under the terms of the Eclipse Public License Version 1.0,
* which accompanies this distribution and is available at http://www.eclipse.org/legal/epl-v10.html.
*
* Sonatype Nexus (TM) Professional Version is available from Sonatype, Inc. "Sonatype" and "Sonatype Nexus" are trademarks
* of Sonatype, Inc. Apache Maven is a trademark of the Apache Software Foundation. M2eclipse is a trademark of the
* Eclipse Foundation. All other trademarks are the property of their respective owners.
*/
package org.sonatype.nexus.proxy.maven;

import java.io.IOException;

import javax.inject.Named;
import javax.inject.Singleton;

import org.sonatype.nexus.proxy.ItemNotFoundException;
import org.sonatype.nexus.proxy.LocalStorageException;
import org.sonatype.nexus.proxy.RemoteAccessException;
import org.sonatype.nexus.proxy.RemoteStorageException;
import org.sonatype.nexus.proxy.ResourceStoreRequest;
import org.sonatype.nexus.proxy.access.Action;
import org.sonatype.nexus.proxy.attributes.Attributes;
import org.sonatype.nexus.proxy.attributes.inspectors.DigestCalculatingInspector;
import org.sonatype.nexus.proxy.item.AbstractStorageItem;
import org.sonatype.nexus.proxy.item.DefaultStorageFileItem;
import org.sonatype.nexus.proxy.item.RepositoryItemUid;
import org.sonatype.nexus.proxy.item.StorageFileItem;
import org.sonatype.nexus.proxy.item.StorageItem;
import org.sonatype.nexus.proxy.item.StringContentLocator;
import org.sonatype.nexus.proxy.repository.ItemContentValidator;
import org.sonatype.nexus.proxy.repository.ProxyRepository;
import org.sonatype.nexus.proxy.storage.UnsupportedStorageOperationException;

/**
* Maven checksum content validator.
*
* @author cstamas
*/
@Named(ChecksumContentValidator.ID)
@Singleton
public class ChecksumContentValidator
    extends AbstractChecksumContentValidator
    implements ItemContentValidator
{

  public static final String ID = "ChecksumContentValidator";

  public static final String SUFFIX_MD5 = ".md5";

  public static final String SUFFIX_SHA1 = ".sha1";

  /**
   * Key of item attribute that holds contents of remote .sha1 file. The attribute is not present if the item does
   * not
   * have corresponding .sha1 file
   */
  public static final String ATTR_REMOTE_SHA1 = "remote.sha1";

  /**
   * Key of item attribute that is set to <code>true</code> if and only if the item does not have corresponding
   * remote
   * .sha1 file.
   */
  public static final String ATTR_NO_REMOTE_SHA1 = "remote.no-sha1";

  /**
   * Key of item attribute that holds contents of remote .md5 file. The attribute is not present if the item does not
   * have corresponding .md5 file
   */
  public static final String ATTR_REMOTE_MD5 = "remote.md5";

  /**
   * Key of item attribute that is set to <code>true</code> if and only if the item does not have corresponding
   * remote
   * .md5 file.
   */
  public static final String ATTR_NO_REMOTE_MD5 = "remote.no-md5";

  @Override
  protected void cleanup(ProxyRepository proxy, RemoteHashResponse remoteHash, boolean contentValid)
      throws LocalStorageException
  {
    if (!contentValid && remoteHash != null && remoteHash.getHashItem() != null) {
      // TODO should we remove bad checksum if policy==WARN?
      try {
        String path = remoteHash.getHashItem().getRepositoryItemUid().getPath();
        proxy.getLocalStorage().deleteItem(proxy, new ResourceStoreRequest(path, true));
      }
      catch (ItemNotFoundException e) {
        // ignore
      }
      catch (UnsupportedStorageOperationException e) {
        // huh?
      }
    }
  }

  @Override
  protected ChecksumPolicy getChecksumPolicy(ProxyRepository proxy, AbstractStorageItem item) {
    if (isChecksum(item.getRepositoryItemUid().getPath())) {
      // do not validate checksum files
      return null;
    }

    if (!proxy.getRepositoryKind().isFacetAvailable(MavenProxyRepository.class)) {
      // we work only with maven proxy reposes, all others are neglected
      return null;
    }

    MavenProxyRepository mpr = proxy.adaptToFacet(MavenProxyRepository.class);

    ChecksumPolicy checksumPolicy = mpr.getChecksumPolicy();

    if (checksumPolicy == null || !checksumPolicy.shouldCheckChecksum()
        || !(item instanceof DefaultStorageFileItem)) {
      // there is either no need to validate or we can't validate the item content
      return null;
    }

    return checksumPolicy;
  }

  @Override
  protected RemoteHashResponse retrieveRemoteHash(AbstractStorageItem item, ProxyRepository proxy, String baseUrl)
      throws LocalStorageException
  {
    RepositoryItemUid uid = item.getRepositoryItemUid();

    ResourceStoreRequest request = new ResourceStoreRequest(item);

    RemoteHashResponse response = null;
    try {
      // we prefer SHA1 ...
      request.pushRequestPath(uid.getPath() + SUFFIX_SHA1);
      try {
        response = doRetrieveSHA1(proxy, request, item);
      }
      finally {
        request.popRequestPath();
      }
    }
    catch (ItemNotFoundException e) {
      // ... but MD5 will do too
      request.pushRequestPath(uid.getPath() + SUFFIX_MD5);
      try {
        response = doRetrieveMD5(proxy, request, item);
      }
      catch (ItemNotFoundException e1) {
        log.debug("Item checksums (SHA1, MD5) remotely unavailable " + uid.toString());
      }
      finally {
        request.popRequestPath();
      }
    }

    return response;
  }

  private boolean isChecksum(String path) {
    return path.endsWith(SUFFIX_SHA1) || path.endsWith(SUFFIX_MD5);
  }

  public static RemoteHashResponse doRetrieveSHA1(ProxyRepository proxy, ResourceStoreRequest hashRequest,
                                                  StorageItem artifact)
      throws LocalStorageException, ItemNotFoundException
  {
    return doRetrieveChecksumItem(proxy, hashRequest, artifact, DigestCalculatingInspector.DIGEST_SHA1_KEY,
        ATTR_REMOTE_SHA1, ATTR_NO_REMOTE_SHA1);
  }

  public static RemoteHashResponse doRetrieveMD5(ProxyRepository proxy, ResourceStoreRequest hashRequest,
                                                 StorageItem artifact)
      throws LocalStorageException, ItemNotFoundException
  {
    return doRetrieveChecksumItem(proxy, hashRequest, artifact, DigestCalculatingInspector.DIGEST_MD5_KEY,
        ATTR_REMOTE_MD5, ATTR_NO_REMOTE_MD5);
  }

  private static RemoteHashResponse doRetrieveChecksumItem(ProxyRepository proxy, ResourceStoreRequest request,
                                                           StorageItem artifact, String inspector, String attrname,
                                                           String noattrname)
      throws ItemNotFoundException, LocalStorageException
  {
    final RepositoryItemUid itemUid = artifact.getRepositoryItemUid();
    itemUid.getLock().lock(Action.read);
    try {
      final Attributes attributes = artifact.getRepositoryItemAttributes();

      if (attributes == null) {
        throw new LocalStorageException("Null item repository attributes");
      }

      if (Boolean.parseBoolean(attributes.get(noattrname)) && !request.isRequestAsExpired()) {
        throw new ItemNotFoundException(request);
      }

      String hash = attributes.get(attrname);
      if (hash == null || request.isRequestAsExpired()) {
        try {
          final StorageFileItem remoteItem =
              (StorageFileItem) proxy.getRemoteStorage().retrieveItem(proxy, request, proxy.getRemoteUrl());
          hash = MUtils.readDigestFromFileItem(remoteItem); // closes http input stream
        }
        catch (ItemNotFoundException e) {
          // fall through
        }
        catch (RemoteAccessException e) {
          // fall through
        }
        catch (RemoteStorageException e) {
          // this is (potentially) transient network or remote server problem will be cached
          // there is no automatic retry for this hash time
          // either expire the artifact or request the hash asExpired to retry
        }

        doStoreChechsumItem(proxy, artifact, attrname, noattrname, hash);
      }

      if (hash != null) {
        return new RemoteHashResponse(inspector, hash, newHashItem(proxy, request, artifact, hash));
      }
      else {
        throw new ItemNotFoundException(request);
      }
    }
    catch (IOException e) {
      throw new LocalStorageException(e);
    }
    finally {
      itemUid.getLock().unlock();
    }
  }

  public static void doStoreSHA1(ProxyRepository proxy, StorageItem artifact, StorageFileItem hash)
      throws LocalStorageException
  {
    try {
      doStoreChechsumItem(proxy, artifact, ATTR_REMOTE_SHA1, ATTR_NO_REMOTE_SHA1,
          MUtils.readDigestFromFileItem(hash));
    }
    catch (IOException e) {
      throw new LocalStorageException(e);
    }
  }

  public static void doStoreMD5(ProxyRepository proxy, StorageItem artifact, StorageFileItem hash)
      throws LocalStorageException
  {
    try {
      doStoreChechsumItem(proxy, artifact, ATTR_REMOTE_MD5, ATTR_NO_REMOTE_MD5,
          MUtils.readDigestFromFileItem(hash));
    }
    catch (IOException e) {
      throw new LocalStorageException(e);
    }
  }

  private static void doStoreChechsumItem(ProxyRepository proxy, StorageItem artifact, String attrname,
                                          String noattrname, String hash)
      throws IOException
  {
    final RepositoryItemUid itemUid = artifact.getRepositoryItemUid();
    itemUid.getLock().lock(Action.update);
    final Attributes attributes = artifact.getRepositoryItemAttributes();
    try {
      if (hash != null) {
        attributes.put(attrname, hash);
      }
      else {
        attributes.put(noattrname, Boolean.toString(true));
      }
      proxy.getAttributesHandler().storeAttributes(artifact);
    }
    finally {
      itemUid.getLock().unlock();
    }
  }

  public static DefaultStorageFileItem newHashItem(ProxyRepository proxy, ResourceStoreRequest request,
                                                   StorageItem artifact, String hash)
  {
    StringContentLocator content = new StringContentLocator(hash);
    // XXX do we need to clone request here?
    DefaultStorageFileItem hashItem =
        new DefaultStorageFileItem(proxy, request, true /* canRead */, false/* canWrite */, content);
    hashItem.setModified(artifact.getModified());
    return hashItem;
  }
}
TOP

Related Classes of org.sonatype.nexus.proxy.maven.ChecksumContentValidator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.