@Override
  protected void addOperationHeaders(AzureStrategyContext context, AzureHttpHeader headers) {
    AzureOperation operation = context.getOperation();
    BlobData blobData = context.getBlobData();
    int blobSequenceNumber = context.getBlobSequenceNumber();
    BlobType blobType = context.getBlobType();
    String cacheControl = null;
    Condition condition = context.getCondition();
    String contentEncoding = null;
    String contentLanguage = null;
    Integer contentLength = null;
    String contentMd5 = null;
    String contentType = null;
    LeaseAction leaseAction = context.getLeaseAction();
    String leaseId = context.getLeaseId();
    int maxPageSize = context.getMaxPageSize();
    MetadataCollection metadata = context.getMetadata();
    BlobRange range = context.getRange();
    Integer sequenceNumber = context.getSequenceNumber();
    SequenceNumberAction sequenceNumberAction = context.getSequenceNumberAction();
    SnapshotDeleteAction snapshotDeleteAction = context.getSnapshotDeleteAction();

    switch (operation) {
      case DeleteBlob:
        if (condition != null) addConditionsToHeaders(headers, condition);
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);
        if (snapshotDeleteAction != null)
          headers.put("x-ms-delete-snapshots", snapshotDeleteAction.toString());
        break;

      case GetBlob:
        if (condition != null) addConditionsToHeaders(headers, condition);
        if (range != null) headers.put("x-ms-range", range.toString());
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);
        break;

      case GetBlobMetadata:
      case GetBlobProperties:
      case GetBlockList:
        if (condition != null) addConditionsToHeaders(headers, condition);
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);
        break;

      case LeaseBlob:
        if (condition != null) addConditionsToHeaders(headers, condition);
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);
        headers.put("x-ms-lease-action", leaseAction.toString());
        break;

      case PutBlob:
        if (condition != null) addConditionsToHeaders(headers, condition);
        headers.put("x-ms-blob-type", blobType.toString());

        if (blobData != null) {
          cacheControl = blobData.getCacheControl();
          if (!Util.isStringNullOrEmpty(cacheControl))
            headers.put(HttpHeader.CACHE_CONTROL, cacheControl);

          contentLanguage = blobData.getContentLanguage();
          if (!Util.isStringNullOrEmpty(contentLanguage))
            headers.put(HttpHeader.CONTENT_LANGUAGE, contentLanguage);

          contentLength = blobData.GetContentLength();
          headers.put(HttpHeader.CONTENT_LENGTH, contentLength);

          contentMd5 = blobData.getContentMd5();
          if (!Util.isStringNullOrEmpty(contentMd5))
            headers.put(HttpHeader.CONTENT_MD5, contentMd5);

          contentEncoding = blobData.getContentEncoding();
          if (!Util.isStringNullOrEmpty(contentEncoding))
            headers.put(AzureHttpHeader.XMS_CONTENT_ENCODING, contentEncoding);

          headers.put(AzureHttpHeader.XMS_CONTENT_TYPE, blobData.getContentType());

          if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);

          if (metadata != null) addMetadataToHeaders(headers, metadata);
        }

        if (blobType == BlobType.PAGE_BLOB) {
          headers.put("x-ms-blob-content-length", maxPageSize);
          headers.put("x-ms-blob-sequence-number", blobSequenceNumber);
        }
        break;

      case PutBlock:
        contentLength = blobData.GetContentLength();
        headers.put(HttpHeader.CONTENT_LENGTH, contentLength);
        contentMd5 = blobData.getContentMd5();
        if (!Util.isStringNullOrEmpty(contentMd5)) headers.put(HttpHeader.CONTENT_MD5, contentMd5);
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);
        break;

      case PutBlockList:
        if (condition != null) addConditionsToHeaders(headers, condition);
        cacheControl = blobData.getCacheControl();
        if (!Util.isStringNullOrEmpty(cacheControl))
          headers.put("x-ms-blob-cache-control", cacheControl);
        contentType = blobData.getContentType();
        if (!Util.isStringNullOrEmpty(contentType))
          headers.put("x-ms-blob-content-type", contentType);
        contentEncoding = blobData.getContentEncoding();
        if (!Util.isStringNullOrEmpty(contentEncoding))
          headers.put("x-ms-blob-content-encoding", contentEncoding);
        contentLanguage = blobData.getContentLanguage();
        if (!Util.isStringNullOrEmpty(contentLanguage))
          headers.put("x-ms-blob-content-language", contentLanguage);
        contentMd5 = blobData.getContentMd5();
        if (!Util.isStringNullOrEmpty(contentMd5)) headers.put("x-ms-blob-content-md5", contentMd5);
        if (metadata != null) addMetadataToHeaders(headers, metadata);
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);
        break;

      case SetBlobMetadata:
        if (condition != null) addConditionsToHeaders(headers, condition);
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);
        addMetadataToHeaders(headers, metadata);
        break;

      case SetBlobProperties:
        if (condition != null) addConditionsToHeaders(headers, condition);
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);

        cacheControl = blobData.getCacheControl();
        contentType = blobData.getContentType();
        contentMd5 = blobData.getContentMd5();
        contentEncoding = blobData.getContentEncoding();
        contentLanguage = blobData.getContentLanguage();
        contentLength = blobData.GetContentLength();
        if (!Util.isStringNullOrEmpty(cacheControl))
          headers.put("x-ms-blob-cache-control", cacheControl);
        if (!Util.isStringNullOrEmpty(contentType))
          headers.put("x-ms-blob-content-type", contentType);
        if (!Util.isStringNullOrEmpty(contentMd5)) headers.put("x-ms-blob-content-md5", contentMd5);
        if (!Util.isStringNullOrEmpty(contentEncoding))
          headers.put("x-ms-blob-content-encoding", contentEncoding);
        if (!Util.isStringNullOrEmpty(contentLanguage))
          headers.put("x-ms-blob-content-language", contentLanguage);
        if (contentLength != null)
          headers.put("x-ms-blob-content-length", contentLength.toString());
        if (sequenceNumberAction != null)
          headers.put("x-ms-sequence-number-action", sequenceNumberAction.toString());
        if (sequenceNumber != null)
          headers.put("x-ms-blob-sequence-number", sequenceNumber.toString());
        break;

      case SnapshotBlob:
        if (condition != null) addConditionsToHeaders(headers, condition);
        if (metadata != null) addMetadataToHeaders(headers, metadata);
        if (!Util.isStringNullOrEmpty(leaseId)) headers.put("x-ms-lease-id", leaseId);
        break;
    }
  }
  @Override
  protected HttpUri getPath(AzureStrategyContext context) throws Exception {

    AzureOperation operation = context.getOperation();
    String blobName = context.getBlobName();
    String blockId = context.getBlockId();
    String delimiter = context.getDelimiter();
    Set<EnumerationFilter> enumerationFilter = context.getEnumerationFilter();
    String marker = context.getMarker();
    int maxResults = context.getMaxResults();
    String prefix = context.getPrefix();
    String snapshot = context.getSnapshot();
    SharedSignatureServiceResponse sssResponse = getSssResponse(context);
    HttpUri uri = null;

    switch (operation) {
      case DeleteBlob:
        uri = sssResponse.getAnyUri();
        uri.appendPath("/" + blobName);
        if (snapshot != null) uri.addParameterWithoutEncoding("snapshot", snapshot);
        break;

      case GetBlob:
      case GetBlobProperties:
        uri = sssResponse.getBlobCollection().getUriForBlob(blobName);
        if (snapshot != null) uri.addParameterWithoutEncoding("snapshot", snapshot);
        break;

      case GetBlobMetadata:
        uri = sssResponse.getBlobCollection().getUriForBlob(blobName);
        uri.addParameterWithoutEncoding("comp", "metadata");
        if (snapshot != null) uri.addParameterWithoutEncoding("snapshot", snapshot);
        break;

      case GetBlockList:
        uri = sssResponse.getBlobCollection().getUriForBlob(blobName);
        uri.addParameterWithoutEncoding("comp", "blocklist");
        if (snapshot != null) uri.addParameterWithoutEncoding("snapshot", snapshot);
        uri.addParameterWithoutEncoding("blocklisttype", "all");
        break;

      case LeaseBlob:
        uri = sssResponse.getAnyUri();
        uri.addParameterWithoutEncoding("comp", "lease");
        break;

      case ListBlobs:
        uri = sssResponse.getAnyUri();
        uri.addParameterWithoutEncoding("restype", "container");
        uri.addParameterWithoutEncoding("comp", "list");
        if (!Util.isStringNullOrEmpty(prefix)) uri.addParameterWithoutEncoding("prefix", prefix);
        if (!Util.isStringNullOrEmpty(delimiter))
          uri.addParameterWithoutEncoding("delimiter", delimiter);
        if (!Util.isStringNullOrEmpty(marker)) uri.addParameterWithoutEncoding("marker", marker);
        uri.addParameterWithoutEncoding("maxresults", Integer.toString(maxResults));
        if (enumerationFilter != null)
          uri.addParameterWithoutEncoding("include", EnumerationFilter.toString(enumerationFilter));
        break;

      case PutBlob:
        uri = sssResponse.getAnyUri();
        uri.appendPath("/" + blobName);
        break;

      case PutBlock:
        uri = sssResponse.getAnyUri();
        uri.addParameterWithoutEncoding("comp", "block");
        uri.addParameterWithoutEncoding("blockid", blockId);
        break;

      case PutBlockList:
        uri = sssResponse.getAnyUri();
        uri.addParameterWithoutEncoding("comp", "blocklist");
        break;

      case SetBlobMetadata:
        uri = sssResponse.getAnyUri();
        uri.appendPath("/" + blobName);
        uri.addParameterWithoutEncoding("comp", "metadata");
        break;

      case SetBlobProperties:
        uri = sssResponse.getAnyUri();
        uri.appendPath("/" + blobName);
        uri.addParameterWithoutEncoding("comp", "properties");
        break;

      case SnapshotBlob:
        uri = sssResponse.getAnyUri();
        uri.addParameterWithoutEncoding("comp", "snapshot");
        break;

      default:
        throw new Exception("Missing case for operation " + operation);
    }

    return uri;
  }