All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.snowflake.client.jdbc.cloud.storage.StorageObjectSummary Maven / Gradle / Ivy

There is a newer version: 3.19.0
Show newest version
/*
 * Copyright (c) 2012-2018 Snowflake Computing Inc. All right reserved.
 */
package net.snowflake.client.jdbc.cloud.storage;

import com.amazonaws.services.s3.model.S3ObjectSummary;
import com.amazonaws.util.Base64;
import com.microsoft.azure.storage.StorageException;
import com.microsoft.azure.storage.blob.BlobProperties;
import com.microsoft.azure.storage.blob.CloudBlob;
import com.microsoft.azure.storage.blob.ListBlobItem;

import java.net.URISyntaxException;

/**
 * Storage platform agnostic class that encapsulates remote storage object properties
 *
 * @author lgiakoumakis
 */
public class StorageObjectSummary
{
  private String location;      // location translates to "bucket" for S3
  private String key;
  private String md5;
  private long size;


  /**
   * Contructs a StorageObjectSummary object from the S3 equivalent S3ObjectSummary
   * @param
   */
  private StorageObjectSummary(String location, String key, String md5, long size)
  {
    this.location = location;
    this.key = key;
    this.md5 = md5;
    this.size = size;
  }

  /**
   * Contructs a StorageObjectSummary object from the S3 equivalent S3ObjectSummary
   * @param objSummary the AWS S3 ObjectSummary object to copy from
   * @return the ObjectSummary object created
   */
 public static StorageObjectSummary createFromS3ObjectSummary(S3ObjectSummary objSummary)
  {

    return new StorageObjectSummary(
                  objSummary.getBucketName(),
                  objSummary.getKey(),
                  // S3 ETag is not always MD5, but since this code path is only
                  // used in skip duplicate files in PUT command, It's not
                  // critical to guarantee that it's MD5
                  objSummary.getETag(),
                  objSummary.getSize()
                  );
  }

  /**
   * Contructs a StorageObjectSummary object from Azure BLOB properties
   * Using factory methods to create these objects since Azure can throw,
   * while retrieving the BLOB properties
   * @param listBlobItem an Azure ListBlobItem object
   * @return the ObjectSummary object created
   */
  public static StorageObjectSummary createFromAzureListBlobItem(ListBlobItem listBlobItem)
    throws StorageProviderException
  {
    String location, key, md5;
    long size;

    // Retrieve the BLOB properties that we need for the Summary
    // Azure Storage stores metadata inside each BLOB, therefore the listBlobItem
    // will point us to the underlying BLOB and will get the properties from it
    // During the process the Storage Client could fail, hence we need to wrap the
    // get calls in try/catch and handle possible exceptions
    try
    {
      location = listBlobItem.getContainer().getName();

      CloudBlob cloudBlob = (CloudBlob) listBlobItem;
      key = cloudBlob.getName();

      BlobProperties blobProperties = cloudBlob.getProperties();
      // the content md5 property is not always the actual md5 of the file. But for here, it's only
      // used for skipping file on PUT command, hense is ok.
      md5 = convertBase64ToHex(blobProperties.getContentMD5());
      size = blobProperties.getLength();
    }
    catch (URISyntaxException | StorageException ex)
    {
      // This should only happen if somehow we got here with and invalid URI (it should never happen)
      // ...or there is a Storage service error. Unlike S3, Azure fetches metadata from the BLOB itself,
      // and its a lazy operation
      throw new StorageProviderException(ex);
    }
    return new StorageObjectSummary(location, key, md5, size);

  }

  private static String convertBase64ToHex(String base64String){
    try{
      byte[] bytes = Base64.decode(base64String);
    
      final StringBuilder builder = new StringBuilder();
      for(byte b : bytes) {
        builder.append(String.format("%02x", b));
      }
      return builder.toString();
    // return empty string if input is not a valid Base64 string
    }catch(Exception e){
      return "";
    }
  }
  
  /**
   * @return returns the location of the object
   */
  public String getLocation()
  {
    return location;
  }

  /**
   * @return returns the key property of the object
   */
  public String getKey() {
    return key;
  }

  /**
   * @return returns the MD5 hash of the object
   */
  public String getMD5()
  {
    return md5;
  }

  /**
   * @return returns the size property of the object
   */
  public long getSize()
  {
    return size;
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy